
Эпичная история установки всех* расширений для браузера Firefox. Это был непростой процесс, который-таки увенчался успехом. Не обошлось в нём и без некоторых любопытных поворотов, неразрешённых вопросов и помощи друга.
Как выяснилось, всего у Firefox 84 тысячи расширений. Вроде бы не особо много, и по факту даже меньше 50 ГБ. Так что приступим!
*Всех, кроме 8, которые мы не соскрейпили (или которые удалили в промежутке между моментом проверки их списка на сайте и запуском скрипта), и 42, которые отсутствовали в extensions.json.1 Так что чисто технически мы установили 99,94% всех расширений.
Скрейпим все расширения
У магазина расширений есть публичный API. Никакой аутентификации и вроде как лимитов на скачивание. Всё должно быть просто.
Поисковый эндпоинт может принимать пустой запрос, что позволяет легко прочитать каждую страницу:
let url = "https://addons.mozilla.org/api/v5/addons/search/?page_size=50&type=extension&app=firefox&appversion=150.0" let extensions = [] let page = 1 while (true) { let res = await fetch(url) let data = await res.json() console.log(`PAGE ${page++}: ${data.results.length} EXTENSIONS`) extensions.push(...data.results) url = data.next if (!data.next) break } Bun.write("extensions-default.json", JSON.stringify(extensions))
Всего API поиска выдал 600 страниц. То есть я могу видеть лишь 30 тысяч расширений — даже не половину из всех.
Обойти эту проблему получилось с помощью изменения параметра сортировки. По умолчанию используется sort=recommended,users: сначала выводятся рекомендуемые расширения, потом они сортируются по количеству пользователей в порядке убывания. Изменив эту установку на sort=created, я получил часть длинного хвоста менее популярных расширений:
let url = "https://addons.mozilla.org/api/v5/addons/search/?page_size=50&type=extension&app=firefox&appversion=150.0" "https://addons.mozilla.org/api/v5/addons/search/?page_size=50&type=extension&app=firefox&appversion=150.0&sort=created"
Bun.write("extensions-default.json", JSON.stringify(extensions)) Bun.write("extensions-newest.json", JSON.stringify(extensions))
count.ts import extensions_default from "../extensions-default.json" import extensions_newest from "../extensions-newest.json" let extensions = {} // Yes, somehow I got the same slug twice for (const ext of extensions_default) { extensions[ext.slug] = ext } for (const ext of extensions_newest) { extensions[ext.slug] = ext } console.log(`TOTAL UNIQUE EXTENSIONS: ${Object.keys(extensions).length}`)
~/Developer/every-addon> bun count TOTAL UNIQUE EXTENSIONS: 54218
Мне по-прежнему не хватает 30 0252 расширений, поэтому я добавил к сортировке критерии rating и hotness.
~/Developer/every-addon> bun count TOTAL UNIQUE EXTENSIONS: 67458
Всё ещё недостаёт 16 7852 штук. Добавляю updated…
~/Developer/every-addon> bun count TOTAL UNIQUE EXTENSIONS: 67945
Полезный выхлоп становится всё меньше. Пока я семь минут ожидал завершения скрейпинга последнего списка (мой код выполняет запросы не параллельно), меня осенило — можно же использовать exclude_addons. Я могу просто запросить страницу 600 и затем при запросе страницы 601 исключить все аддоны, которые уже были на 600-й.
let url = "https://addons.mozilla.org/api/v5/addons/search/?page_size=50&page=600&type=extension&app=firefox&appversion=150.0&sort=updated" const page_600 = await fetch(url).then(res => res.json()) const page_601 = await fetch( `${url}&exclude_addons=${page_600.results.map(ext => ext.id).join(",")}`, ).then(res => res.json())
Работает! К сожалению, длина URL-адреса ограничена, так что я могу запросить только 20 дополнительных страниц.
let url = "https://addons.mozilla.org/api/v5/addons/search/?page_size=50&page=600&type=extension&app=firefox&appversion=150.0&sort=created&exclude_addons=" let extensions = [] let page = 600 try { while (true) { let res = await fetch(url) let data = await res.json() console.log(`PAGE ${page++}: ${data.results.length} EXTENSIONS`) if (data.results.at(-1).id === extensions.at(-1)?.id) break // IDK extensions.push(...data.results) url += data.results.map(ext => ext.id).join(",") } } catch {} Bun.write("created-2.json", JSON.stringify(extensions))
Смотрите:
~/Developer/every-addon> bun count TOTAL UNIQUE EXTENSIONS: 68035
Намного меньше, чем я ожидал, особенно с учётом результатов добавления сортировки по downloads:
~/Developer/every-addon> bun count TOTAL UNIQUE EXTENSIONS: 68901
Ещё раз перечитав документацию, я заметил, что можно делать фильтрацию и по категориям. Мне надоело ждать по семь минут, поэтому я решил запрашивать все страницы параллельно.
function get(url: string, path: string) { return Promise.all( Array.from({ length: 600 }, (_, i) => fetch(`${url}&page=${i + 1}`).then(res => res.json())), ).then(pages => { let extensions = pages.flatMap(page => page.results) Bun.write(path, JSON.stringify(extensions)) }) } const categories = await fetch("https://addons.mozilla.org/api/v5/addons/categories/").then(res => res.json(), ) await Promise.all( categories .filter(category => category.type === "extension") .map(category => { return get( `https://addons.mozilla.org/api/v5/addons/search/?page_size=50&type=extension&app=firefox&sort=created&category=${category.slug}&appversion=150.0`, `./newest-${category.slug}.json`, ) }), )
Таким образом мне удалось заполучить практически все расширения, после чего мои предыдущие старания выглядели какой-то глупостью.
~/Developer/every-addon> bun analyze
Найдено 84 235 уникальных расширений.
Всего они занимают 49,3 ГБ, то есть в среднем по 584,9 КБ на расширение.
Всего получилось на 8 расширений меньше, чем указано на сайте. Когда я проделал этот эксперимент в сентябре 2025 года, то, наоборот, нашёл на 21 расширение больше. Так что, думаю, этого достаточно.
И чтобы никому не пришлось повторять всё это снова, я загрузил датасет на Hugging Face.
Либо можно воспользоваться функцией CORS, которая на сервере расширений включена — просто кликните по этой забавной кнопке ниже (работает только в оригинале статьи), и вы получите копию all_extensions.json:

Обновление от 11 апреля
Поисковый API поддерживает фильтрацию по датам: created__gte и created__lte. Этот API также возвращает все расширения, которые соответствуют запросу.
Можете начать с фильтра, включающего все расширения, и потом разделять диапазон дат пополам, пока в каждом из полученных наборов не окажется менее 30 тысяч результатов, после чего уже запросить их все.
Я обновил загрузчик — теперь он работает быстрее, делает меньше лишних запросов и скрейпит конкретно все расширения.
Этот подход не сработает, если окажется, что за одну секунду было создано более 30 тысяч расширений. Но это уже на грани фантастики.
Анализ каждого расширения
У меня есть Bun и копия all_extensions.json, так что теперь я буду хвастать своей несравненной мощью скриптов.
Самые большие расширения
Самое мясистое расширение Firefox весом 196,3 МБ — это dmitlichess. Оно содержит 2000+ аудиофайлов.
Вот остальные топ-10:
(Неофициальное) ReactBot Web, 184,9 МБ. Я думал, что это прямой порт jacksfilms ReactBot, но нет, это лишь кучка
.webms.Eric’s Thumbnail Seasoning!, 146,6 МБ. Чей-то личный форк YouTube MrBeastify. Содержит 900
.pngs.Animal Forest:PG BGM, 137,4 МБ. Агрессивная версия https://tane.us/ac.
YouTube OCR, 128,3 МБ: Tesseract.js.
Image to Text for ChatGPT, 128,3 МБ. Тоже Tesseract.js.
qwip AI Detection BETA, 126,0 МБ. ИИ-модели (не Tesseract.js).
Kumo Study, 117,0 МБ. 50 студийных lo-fi битов без роялти.
YouTube Jakkify, 114,0 МБ. Ещё один форк YouTube MrBeastify. Предлагает 500 сойджеков.
True Paper, 111,6 МБ. Тоже ИИ-модели, не относящиеся к Tesseract.js.
Когда я впервые провёл этот анализ в сентябре, на 10-м месте находилось расширение Cute doggy — Dog puppies. Решил всё же упомянуть его здесь, ибо это чертовски странно:

Самое мелкое расширение — это theTabs-saver. В нём совсем нет кода, а размер составляет 7 518 байт.
Худшее расширение
Чисто субъективно — это Cute doggy — Dog puppies, но по факту:
import extensions from "../all_extensions.json" console.log( extensions .filter(ext => ext.ratings.count > 10) .sort((a, b) => a.ratings.bayesian_average - b.ratings.bayesian_average)[0], )
…это Tab Stack for Firefox от lolicon (?!?!?!?!?!).
Первое расширение
Больше всего скриншотов
В RDS Bar их 54.
Номинация «Middle Finger Emoji Sticker»

FalscheLaden, не имея пользователей, запрашивает 3 695 разрешений. Его автор даже написал об этом статью.
Второе место за Google Dark Theme, требующим 2 675 разрешений. Но у него хотя бы есть 1 687 пользователей.
Самый продуктивный разработчик
import extensions from "../all_extensions.json" console.log( Object.values( Object.groupBy( extensions.flatMap(e => e.authors), author => author.id, ), ).sort((a, b) => b.length - a.length)[0][0], )
Королём слопа определённо является Dr. B, который навайбкодил 84 расширения.
Откуда я знаю, что именно навайбкодил? В большинстве его аддонов есть файл README.md, где описывается процесс ревью с упоминанием Grok 3. Кроме того, ни у одного из его творений нет ни иконок, ни скриншотов.
Лично я удивлён столь небольшим числом. Ожидал, что будут разработчики с сотнями расширений!
Фишинг
Я проанализировал исходники пары ловушек для крипто-кошельков на основе гомоглифной атаки, которые нашёл в датасете. К моему разочарованию, выяснилось, что они просто показывают всплывающее окно с просьбой ввести сид-фразу, которую отправляют на свой сервер. Чёрт побери, это же расширение! Вы можете украсть пользовательский токен с coinbase.com, можете мониторить буфер обмена и подставлять туда свой адрес! Можете даже крашнуть браузер и предложить в качестве «лекарства» свою малварь!
Зачем вам делать фейковое расширение MetaMask и накручивать отзывы с одной звездой?

Или это проделки конкурентов по кибермошенничеству, которые на собственное расширение накручивают четыре звезды?

Как бы то ни было, эти расширения явно фишинговые. Я отправил отчёт о некоторых таких поделках в Mozilla, и на следующий день они исчезли из магазина — даже те, на которые я жаловаться поленился. Вот только забыл их заархивировать, так что остались они, пожалуй, только на виртуалке Мэй.
В плане реализации самым интересным их них оказалось “Іron Wаllеt” (I, a и e написаны кириллицей). Буквально через три секунды после установки оно запрашивает URL фишинговой страницы из первой записи таблицы NocoDB и открывает его:
static/background/index.js var r = e("./lib/noco") chrome.runtime.onInstalled.addListener(async () => { try { await new Promise(e => setTimeout(e, 3e3)) let e = await (0, r.fetchUrlFromNocoRest)() e ? await chrome.tabs.create({ url: e, }) : console.warn("No valid URL from NocoDB.") } catch (e) { console.error("Install flow failed:", e) } })
Причём описание расширения как «не использующего учётные записи и удалённое выполнение кода» выглядит забавным. Это как сопроводить свой ролик подписью «нарушения авторских прав не было» на случай, если YouTube следит. У меня был API-ключ с правом записи, так что я очистил эту таблицу.
SEO-спам
На странице установленного расширения и странице вашего профиля появляется ссылка «Homepage». И хотя она уже два года как помечена атрибутом nofollow, мошенников это не останавливает.
При Попытке 1 (описана ниже) я столкнулся с Typo Sniper и Tab Fortune Teller — сгенерированными ИИ расширениями, у которых ссылки Homepage ведут на страницу казино.
В собранном датасете есть множество расширений «Code Injector». Все они практически идентичны, и их ссылки Homepage ведут на разные сайты.
Все эти расширения от 2025 года. Неужели в вебе гуляет какой-то древний гайд по SEO? А может, дело в багах AMO-фронтенда, из которого они до сих пор умудряются получать обратные ссылки? Какая-то непонятная чертовщина.
Потенциально нежелательные приложения (PUA)
Взгляните на список ниже. Замечаете общий паттерн?
Maps Assist & Custom Web Search: 138 082 пользователей
Package Tracking Tab & Custom Web Search: 83 506 пользователей
Converter Suite & Custom Web Search: 82 502 пользователей
Manuals Explorer & Custom Web Search: 66 835 пользователей
Ezy Photo Tab & Custom Web Search: 54 347 пользователей
Easy Games Tab & Custom Web Search: 34 918 пользователей
Task Manager Tab & Custom Web Search: 34 585 пользователей
Turbo Converter & Custom Web Search: 32 236 пользователей
Quick Live News & Custom Web Search: 31 542 пользователей
Ezy Speed Test & Custom Web Search: 30 853 пользователей
Quick Recipe Hub & Custom Web Search: 29 556 пользователей
Flight Tab Pro & Custom Web Search: 28 633 пользователей
Weather Authority & Custom Web Search: 13 658 пользователей
Video Converter World & Custom Web Search: 13 191 пользователей
Daily Top Coupons & Custom Web Search: 9 385 пользователей
Password Generator Pro & Custom Web Search: 5 289 пользователей
Calculator Whiz & Custom Web Search: 4 563 пользователей
Calendar Planner & Custom Web Search: 4 223 пользователей
Ezy Alarm Clock & Custom Web Search: 4 051 пользователей
Zip-Unzip Files & Custom Web Search: 3 298 пользователей
Latest Wallpapers & Custom Web Search: 2 648 пользователей
Ezy Screenshot & Custom Web Search: 2 231 пользователей
Precious Bible & Custom Search: 1 946 пользователей
Grammar Wise & Custom Web Search: 1 115 пользователей
Stream Live Radio & Custom Web Search: 725 пользователей
Astrology Craft & Custom Web Search: 185 пользователей
AI Chat Pro & Custom Web Search: 1 несчастный пользователь
Более 700 000 пользователей в общем.
Все эти расширения являются единственным, что загрузили их авторы, и у каждого есть свой домен. Большинство из них есть как в Firefox, так и в Chrome, у них похожие сайты, и в пользовательском соглашении каждого упоминается Innover Online Group Ltd, причём в виде .png.
Так как я дважды соскрейпил все расширения Firefox, то вижу, какие из них были удалены. Три расширения Innover Group — Earth View 360°, View Manuals и View Recipes, с общим числом пользователей около 115 000 — в Mozilla убрали.
Innover Group публикует для своих расширений рекламные баннеры Google, на многих из которых просто сказано «Continue».
«Custom Web Search» работает через Yahoo, только со своим партнёрским кодом. Выглядит этот код как safeplexsearch, и у него есть родительский сайт, где, естественно, упоминается Innover Online Group Ltd и присутствуют ссылки на расширение с 3 892 пользователями, которое по факту является эксклюзивом Firefox. На деле «Custom Web Search» — это единственный эксклюзив для Firefox из всех расширений. Зачем они вообще создавали версию для Chrome? Чтобы продать её АНБ?
Один пользователь заявил, что Ezy Speed Test «при установке отключает Ublock Origin», но я этого в коде расширения не нашёл.
Хотя существует миллион подобных компаний. Я просто зашёл на Download.com с выключенным Ad-блокером, где с ходу нашёл объявление от компании Atom Apps, которая тоже загружает расширения для Chrome и Firefox, создавая новый аккаунт для каждого. Она точно так же встраивает поиск Yahoo только в версии для Firefox и называет расширения с окончанием на «and Search» или «& Search». И имя компании в их пользовательских соглашениях тоже представлено в виде .png. Всего по 12 расширениям у этой конторы 220 000 ежедневных пользователей, и ни одно из них до сих пор не удалено.
Немного статистики в процентах
-
34,3% расширений не имеют ежедневных пользователей.
у 25,1% более 10 ежедневных пользователей.
у 10,6% более 100 ежедневных пользователей.
у 3,2% более 1 000 ежедневных пользователей.
у 0,7% более 10 000 ежедневных пользователей
76,7% всех расширений являются опенсорсными (под лицензией SPDX, отличной от «Все права защищены»)
-
23% расширений были созданы после написания этой статьи.
у 19% нет пользователей, отзывов, скриншотов, скачиваний и иконок.
-
2,4% расширений требуют оплату.
38,1% из них являются опенсорсными. (???)
Установка всех расширений Firefox
Ясное дело, я не собираюсь открывать каждое расширение в новой вкладке и прокликивать все эти всплывающие окна. Не то, чтобы я не пробовал:

У каждого расширения есть свойство current_version.file.url, отвечающее за его прямое скачивание. Я скачал их в каталог extensions своего профиля, указав в качестве имени guid, а в качестве расширения .xpi. Иначе установить их не получится.
После этого я удалил файлы addonStartup.json.lz4 и extensions.json. Теперь, когда я открываю Firefox, все расширения отключены. Правка extensions.json — это стандартная практика, так что можете попросить помощи у любого чат-бота:
enable.js const fs = require("fs") // ПОЧЕМУ ЭТО COMMONJS? const path = require("path") // Путь к extensions.json (укажите каталог своего профиля Firefox). // ПОЧЕМУ ОН В CAMELCASE? const extensionsJsonPath = "/Users/user/Library/Application Support/Firefox/Profiles/1avegyqd.default-release/extensions.json" try { // Считывает файл extensions.json. const data = fs.readFileSync(extensionsJsonPath, "utf-8") // ПОЧЕМУ ЭТО НЕ NODE:FS/PROMISES? const extensionsData = JSON.parse(data) // Изменяет расширения. if (Array.isArray(extensionsData.addons)) { extensionsData.addons.forEach(addon => { addon.userDisabled = false addon.active = true addon.seen = true }) // ПОЧЕМУ ЭТО НЕ GUARD? } else { console.error("Unexpected format: addons property is missing or not an array.") process.exit(1) } // Записывает изменённые данные обратно в extensions.json. fs.writeFileSync(extensionsJsonPath, JSON.stringify(extensionsData, null, 2)) console.log("All extensions enabled successfully!") } catch (error) { console.error("Error processing extensions.json:", error) }
Попытка 0: 65 335
Свою первую попытку я проделал на VM tiny11 core на своём десктопном ПК.
Сначала вместо того, чтобы скачать все расширения через скрипт, я пытался использовать корпоративные политики, но в этом случае они копируются в каталог. Память быстро закончилась, и файл подкачки занял весь оставшийся объём, выделенный под VM. Я также ожидал, что Firefox сразу запустится, и расширения автоматически установятся в процессе использования браузера. Но и этого не произошло — он просто завис.

Попытка 1: ~1 000
Тогда я попробовал скачать их сам.
download.ts import extensions from "./all_extensions.json" import { exists } from "node:fs/promises" let progress = 0 let count = extensions.length const PATH_TO_EXTENSIONS_FOLDER = "C:\\Users\\user\\AppData\\Local\\Mozilla\\Firefox\\Profiles\\mkrso47f.default-release\\" await Promise.all( extensions.map(async ext => { if (await exists(PATH_TO_EXTENSIONS_FOLDER + ext.guid + ".xpi")) { progress++ } else { console.log("Downloading", ext.current_version.file.url) const file = await fetch(ext.current_version.file.url) await Bun.write(PATH_TO_EXTENSIONS_FOLDER + ext.guid + ".xpi", file) console.log("Downloaded", ext.slug, `${(++progress / count) * 100}% done`) } }), )

Чтобы убедиться в том, что я всё делаю правильно, я перенёс каталог extensions в другое место и затем вернул примерно 1 000 расширений. Сработало.

Среди аддонов было много таких, которые меняли весь текст страницы на конкретную строку. В этой битве bruh-ifier проиграл Se ni važn, которое на фоне страницы добавляет Гоку.
Моё контекстное меню настолько длинное, что я покажу его боком:

Я установил много защитных расширений. Одно из них блокирует отправку трафика на домены .zip и .mov — вероятно, потому что это расширения файлов. Да это же дискриминация .cab (блог автора оригинала находится в домене .cab, — прим. пер.). Потом я понял, что мою историю браузера наверняка кто-то просматривает, и решил оставить этим людям послание.

Это всплывающее окно “⚠️ SCAM WARNING!” взято из аддона Anti-Phishing Alert. Как вы могли догадаться, оно существует только ради ссылки на его Homepage. Как же оно работает?
phishing_detector.js function isPhishingURL(url) { const suspiciousPatterns = [ /[\.\-]login[\.\-]/i, /[\.\-]secure[\.\-]/i, /[\.\-]account[\.\-]/i, /[\.\-]verify[\.\-]/i, /[a-z0-9\-]{1,}\.com\.xyz/i, /https?:\/\/(?!www\.)[a-z0-9\-]+\.([a-z]{2,}){2,}/i, ] return suspiciousPatterns.some(pattern => pattern.test(url)) }
У Vasavi Fraudulent Detector также есть всплывающее окно для случаев, когда сайт безопасен:
modal.js $.sweetModal({ title: "Vasavi Fraudulent Detector", content: "Safe Webpage !!", icon: $.sweetModal.ICON_SUCCESS, buttons: [ { label: "Continue", classes: "greenB", }, ], })
Попытка 2: 65 335
Реально загрузились только аддоны из Попытки 1, так как сначала я не знал, что нужно удалить addonStartup.json.lz4.net. Я промотал страницу со скачанными расширениями, после чего открыл DevTools, чтобы проверить, все ли 65 335 установились. Но на этом браузер завис, и заново перезапустить его не получилось.
Попытка 3: 65 335 (на Mac)
После этого я создал на своём Mac нового пользователя (не администратора), чтобы повторить попытку на более мощном устройстве.
Раз за разом, поглядывая за тем, как мой скрипт в течение шести часов скачивает расширения по одному, я постепенно запоминал их названия. Похоже, теперь я могу считать себя экспертом по AMO! При параллельном скачивании процесс ближе к последним 4 000 расширений замедлялся, чего на VM с Windows не происходило.
Когда вся эта процедура закончилась, я попытался одновременно запустить все 65 335 аддонов. Увы, безуспешно. Спустя какое-то время окно браузера всё же открывается, но в итоге никак не реагирует. Неужели придётся оставлять ноутбук работать всю ночь...3
Тем временем Firefox записал более 400 ГБ данных. Забыв о существовании файла подкачки, я пытался найти причину в конфигурации профиля, и как раз тогда понял, что нужно удалить addonStartup.json.lz4 и изменить extensions.json. Размер extensions.json составлял 144 МБ. К сравнению, у меня на ПК он весит 336 КБ.

Попытки с 4 по 10: 1 000 — 6 000
В качестве обходного пути я решил добавлять по 1 000 расширений за раз, пока запуск Firefox не станет слишком долгим. В итоге я дошёл до 6 000.
На 3 000 страницы уже перестали загружаться.

После 4 000 и до 5 000 расширений никаких явных изменений не было. Я даже снял ролик (для эпилептиков не рекомендуется):
При 5 000 всё работало так же, как и при 4 000, но любой сайт блокировался каким-то расширением. Его название начинается на S, заканчивается на Blocker, а в логотипе присутствуют иероглифы. Когда число расширений достигло 6 000, единственным, что загружалось, была страница about:addons.
Попытка 11: 84 194 (спустя полгода)
У меня в ПК установлено 16 ГБ RAM, а в ноутбуке 24 ГБ объединённой памяти. Очевидно, что 49,3 ГБ превышает этот объём больше, чем вдвое.
Тогда я попросил помощи у подруги.
Ниже я покажу и опишу то, что было зафиксировано на виртуальной машине Мэй. Не пытайтесь проделать это в собственном профиле.
Скачивание
Мой скрипт скачивания запускался в параллельном режиме, и потом, когда скорость падала, мы переключали его в последовательный. В общей сложности этот процесс занял 1 час и 43 минуты.
Всё это время я был на звонке, и мы заметили в логах много странных расширений. Например, какой чудак стал бы использовать «KiwiFarms Math Renderer»? Он что, разрабатывает теорию соитивности?
После включения Mullvad VPN и маршрутизации через Тель-Авив процесс ускорился. Нет, дело не в «Большом Яху» (Big Yahu), просто Мэй перезапустила скрипт. В итоге она даже повторила это пару раз. Возможно, это какой-то баг в Bun, но я не уверен, да оно и не важно. Мэй пошутила про возможную необходимость доработки скрипта, о чём я даже не хочу думать.
Defender обозначил одно из расширений — HackTools — как вредонос. После этого Мэй исключила каталог расширений из проверки, так что оно могло быть не единственным.

Запуск 1
Firefox неспешно переписывал свой extensions.json, и размер продолжал расти. Где-то через 39 минут показа голого скелета (то есть «он ещё не отрисовал даже второй фрейм»), файл раздулся до 189 МБ — новый рекорд. Тогда Мэй убила его процесс и запустила enable.js.

Мне стало интересно разобраться, почему всё это происходит так долго. В итоге выяснилось, что 13 лет назад файл extensions.json был extensions.sqlite. Сегодня же его данные сериализуются и полностью переписываются при каждом изменении с задержкой в 20 мс. И это нормально, если вы ставите 15 расширений, но не 84 194.
Запуск 2
Наконец-то мы увидели браузер. Вкладки окна приветствия появились, но до конца так и не загрузились.

Три минуты спустя Firefox упал.
Запуск 3
Мэй заново его открыла, сходила в душ, и когда вернулась, увидела следующее:

Он стабилизировался. Вы реально можете (кое-как) использовать Firefox со всеми 84 тысячами расширений.

И мы реально уверены, что установили именно столько. По крайней мере среди них был Tab Counter, и полоса прокрутки в панели расширений была невероятно длинной.
Использование всех расширений Firefox
Реально.
about:addons
Страница аддонов
Мэй открыла страницы настроек двух расширений. При этом iframe с опциями так и не загрузился.


Индексная страница
Я догадался, что нужно отключить автообновление, пока браузер не отправит очередные 84 тысячи запросов. Загружался список расширений долго.
Сначала он загрузился без иконок и перестал отвечать, но через 6 часов прогрузился полностью.

Мы записывали весь процесс. Потребление памяти колебалось между 27 и 37 ГиБ.
У нас были установлены буквально все расширения, включая собственный аддон Мэй mt-rpc.

Я до сих пор не понимаю, почему страница about:addons загружалась 6 часов.
Я протестировал свою изначальную теорию о том, что иконки расширений не загружаются «ленивым» образом — по иронии снова отправив 84 тысячи запросов — для чего внёс однострочную правку в код Firefox и установил три тысячи (отключенных) расширений на Mac. Чтобы скомпилировать Firefox, мне пришлось удалить аддоны, установленные на Попытке 3, иначе места не хватало.

Меньше от этого браузер зависать не стал. Если посчитать, то при этой проверке я использовал в 28 раз меньше расширений, чем при Попытке 11. Так что, похоже, проблема проявляется уже и на этих масштабах.
about:support
М-да, расширений до фига. Но для точности лучше перепроверить.
Я попросил Мэй открыть DevTools и выполнить $$("#addons-tbody tr").length, чтобы подтвердить установку, как мы считали, именно 84 205 расширений.

Более внимательно изучив about:support, я понял, что мои изначальные опасения были верны, но причина была в другом — просто основные 84 205 расширений включали встроенные дополнения вроде Web Compatibility Interventions. При их исключении общее количество составляло 84 194.
До этого я писал, что в DevTools не загружались никакие расширения, так как это была страница about:, но вот я установил webhint и перешёл на about:support, где оно вполне отобразилось. Так что не знаю, в чём была причина.
about:preferences
Мы хотели проверить, какие варианты создания новой вкладки нам доступны.

В процессе мы также включили отправку отчётов о сбоях.
New Tab
Какое же расширение победило? Да ни одно. Страница новой вкладки так и не загрузилась, какое бы расширение мы ни пробовали. Исключением стала только домашняя страница Firefox, которая открылась мгновенно.
moz-extension
Страница расширения buyPal (с одним пользователем) открылась сама, без нашей помощи, заменив при этом все открытые вкладки. Это единственная страница не из категории about:, которая реально загрузилась.

После этого Firefox снова лёг.
example.com
Это первая страница, где могут выполняться встраиваемые скрипты.
Как и в Попытке 9, здесь явно присутствовало много расширений, блокирующих любой сайт. Хотя это было неважно, так как мы продержали вкладку открытой 24 часа, но она так и не загрузилась.
about:telemetry
Эта страница загрузилась, потом Мэй кликнула по Environment Data, и браузер крашнулся.

Можно ли таким пользоваться?
Нет.
Что ещё можно проверить?
Выяснить, почему
about:addonsзагружалась шесть часов, и почему example.com так и не загрузилась.Firefox — это не единственный браузер с поддержкой
.xpis: она есть в Kagi Orion и GNOME Web, оба из которых основаны на WebKit. В Orion нет функции массовой установки расширений, поэтому пробовать я его не стал, а Web и без расширений весьма медленный.Мы намеренно установили именно все расширения, а не все типы дополнений. Несложно догадаться, к чему приведёт, например установка всех тем, которых около 500 тысяч, и чей размер в среднем больше размера расширения.
-
Установить все пользовательские скрипты и стили? Общей базы данных для этих вещей нет.
В Stylus жёстко прописано ограничение 1 ГБ на размер резервной копии, и когда я отключил его правкой кода, возникла новая, ещё более странная ошибка.
Установить все расширения Chrome? Да ладно, шучу. Их слишком много, и скрейпить их та ещё морока.
Сноски
Вот расширения, которые были в all_extensions.json, но отсутствовали в extensions.json. Если перечёркнуто, значит, было удалено из AMO.
Расширение |
GUID |
|
facebook-downloader@daniel.extensions |
Restart Web Browser / Shutdown OS After Download |
@restart_web_browser |
Toolship: Toolkit for DEV & QA |
toolship@shridhar |
|
clickarmor@clickarmor.dev |
当图-高级二维码生成器 |
{af68df6c-3dc8-4986-ade3-633c34a0b16a} |
Auto Link Open |
mosa.allbedre0@gmail.com |
|
{f885cff8-968c-462b-817f-8060be9b1635} |
|
virustotal-scanner@jaffacakes118.dev |
|
aistore@example.com |
BraveFox Enhancer |
enhancer@goldenfox.com |
SecNote Messages encryption |
{07d7c62a-d3c3-484f-99d3-47641e13b24c} |
|
cs.dorgpio.23@gmail.com |
|
nyx@alsania-io |
|
outlook-extension@kitamura.jf7 |
|
mistral-text-assistant@addons |
|
{e07663c2-b159-4f18-b382-2b44d615f5ed} |
(WIP) LHS - 8248 New Tab |
custom-new-tab@8248.local |
Product Image Scraper |
techpriest@gurglorium.com |
Bitculator |
id@bitculator.com |
|
emoji-replacer@nadz.dev |
Monitorizo |
monitorizo@monitorizo.net |
Azninj |
azninj@azninj.com |
Anime Streaming |
extension@anime-streaming.eu |
TSS+ |
tss_plus@mozilla.org |
TruSearch |
trusearchnewtab@gmail.com |
Class Link Check for Google Classroom™ |
{9b887266-8284-4069-8f12-c9bd326979c2} |
History Overrid |
{f9d43888-0f36-4b8c-b5f2-f5f595547ddf} |
History Overrides |
{41e67140-ef2b-42a4-a9b3-758b4e9df8da} |
OnPageSeoCheck |
{9c3f49f3-9346-40d5-ba97-0b1872526a41} |
tnt-signuature |
{493830f0-1fff-4f9a-aa1e-444bafbc7312} |
CheharaTime |
{fc1f9366-1a9c-4aac-8113-d91e9ecb7a74} |
Social Networks Automation |
social-networks-automation@mozilla.org |
History Override |
{c09a4ed2-c611-41af-b3e4-79a810216f93} |
Facebook Always Active (DCS) |
DCS-FB-AA@mozilla.org |
Font Finder Lm |
{ee6a863e-c039-4f97-af7c-dd4f65e7af95} |
Classroom Meeting Link Checker |
{fb6bc162-d129-45d1-8da9-7a132342b667} |
ZimRim Search Extension |
zimrim-extension@mozilla.org |
ZimRim Extension |
{ccd4a5ce-0a3b-449e-b3f8-43a90ec7aaa9} |
HipDash |
dev@hipdash.com |
LANeros - Galería De Imagenes |
carlos.gaviria.gallego1@outlook.com |
Priberam dictionary search |
priberam_dictionary_search_@voila.tech |
Site Annonce |
extension@classified-media.com |
-
Эту статью я опубликовал в апреле 2026 года, но её первую версию, включая скрипты скрейпинга, написал в сентябре 2025. Я просто заново выполнил последний скрипт и попросил Claude обновить цифры. Вместо того, чтобы заново скрейпить данные, что привело бы к неточностям, так как с тех пор многое изменилось, он просто в обратном порядке перебрал все созданные мной файлы. Финальные числа получились достаточно точными. Количество отсутствующих расширений я обновил сам, так как предполагал, что их итоговое число 84 000, а не 84 243. ↩ ↩
Затравка — литературный приём, с помощью которого писатели намекают читателям на будущие события истории. ↩
Комментарии (6)

Vsevo10d
19.04.2026 09:34Помню, когда-то очень давно натыкался в мозилле на расширение Mozilla Fuckfox, без иконок и описания. Устанавливать на всякий случай не стал.

fire64
Месте знает толк...
Ну самом деле интересно было читать, что из этого получится.