Botasaurus — это Python-фреймворк для веб-скрейпинга от Omkar Cloud, который подаётся как универсальный набор для создания парсеров. Пишешь обычную функцию, вешаешь на неё декоратор @browser, @request или @task, и фреймворк сам подцепляет к ней браузерный драйвер, HTTP-клиент, похожий на браузер, кэширование, параллельную обработку и экспорт в разные форматы. По сути это метапакет, и именно в этом весь фокус: pip install botasaurus не ставит в окружение одну библиотеку, а собирает целую небольшую линейку собственных wheel-пакетов плюс довольно широкое дерево зависимостей. И именно эта механическая деталь оказалась самой интересной из того, что удалось честно измерить.
Botasaurus много говорит об антидетекте, и именно этот момент в обзоре я не трогаю. Я провёл инвентаризацию фреймворка — что ставится, что импортируется, какие методы доступны, сколько он весит и под какой лицензией распространяется — вместо того чтобы сравнивать его с реальными защитными системами. Все цифры по размеру и импорту ниже получены из pip, из python -c "import ..." и из инспекции классов, которые были созданы, но ни разу не отправлялись за страницей; ни один браузер для этого не запускался. Позже я действительно запускал браузеры, но только на страницах, которые написал и сам же отдал с 127.0.0.1, чтобы посмотреть, что драйвер сообщает о себе и умеет ли он вытащить контент со страницы, которая строится на JavaScript. Ни одного живого сайта я не трогал, ни с одной anti-bot системой не взаимодействовал и ни одной CAPTCHA не касался. Проверка эффективности на реальных сайтах сознательно не входила в задачу, и я лучше скажу это прямо, чем создам видимость бенчмарка, которого на самом деле не было.
С таким ограничением главный вывод сводится к истории про размер, и в целом она довольно спокойная. Чистая установка создаёт каталог site-packages объёмом 122,3 МБ и 44 пакетами, при этом сам браузерный драйвер в центре всей этой конструкции весит примерно 4 МБ. Фреймворк тяжёлый не потому, что сам драйвер тяжёлый; он тяжёлый потому, что «всё включено» означает numpy, lxml, gevent и ещё с десяток библиотек для задачи, которая по сути сводится к получению HTML. А вторая важная цифра — это именно тот показатель, который любят приводить как достоинство и который не стоит принимать на веру: import botasaurus занимает всего 0,08 мс, что выглядит как сверхлёгкий фреймворк, но на деле является просто пустой парадной дверью.
Что такое Botasaurus на самом деле
Botasaurus — omkarcloud/botasaurus на GitHub, где на момент, когда я забирал метаданные 14 июля 2026 года, было 5 561 звезда, 486 форков и 58 открытых issues — это Python-фреймворк, а не узкоспециализированная библиотека. В моих тестах использовались botasaurus 4.0.97 для метапакета и botasaurus-driver 4.0.92 для ядра под ним. Метапакет заявляет requires-python >=3.7 (драйвер — >=3.5), а классификаторы на PyPI указывают поддержку только до 3.11. На моей машине он установился и прошёл smoke test импорта под Python 3.14.2. Это говорит только о работоспособности именно этой установки, но не гарантирует совместимость всех функций.
Категорию важно зафиксировать, потому что от неё зависит смысл слова «хороший». Botasaurus находится на стороне фреймворков, в том же районе, что и Scrapy и Crawlee: ты принимаешь его структуру, декораторы и соглашения, а взамен получаешь готовую обвязку. Это совсем не то же самое, что узкий драйвер вроде nodriver, который даёт соединение через Chrome DevTools Protocol и почти не вмешивается в работу. Botasaurus тоже содержит драйвер (botasaurus-driver), но оборачивает его в task runner, слой кэширования, сериализаторы вывода и HTTP-клиент для запросов. Ты покупаешь не просто драйвер, а целый предписывающий рабочий процесс с драйвером внутри.
Три декоратора — это весь дизайн в миниатюре, и все три точки входа реально существуют: я подтвердил, что botasaurus.browser.browser, botasaurus.request.request и botasaurus.task.task есть и импортируются. @browser запускает твою функцию на браузерном драйвере, @request — на лёгком HTTP-клиенте, который старается вести себя как браузер, а @task служит универсальной обёрткой для всего, что не попадает в первые две категории. Помечаешь функцию — и Botasaurus подставляет всю окружающую инфраструктуру: параллельное выполнение, повторное использование драйвера, кэш результатов и запись в JSON, CSV, Excel и HTML. Идея цельная. А вот нужен ли тебе настолько «обрамлённый» скрейпер — это уже вопрос вкуса, а не недостатка.
Итог и граница оценки
Botasaurus компетентен, хорошо собран и делает то, что и должен делать фреймворк: сокращает путь в типовом сценарии. Модель на декораторах аккуратная. Лицензия MIT действительно щедрая. Установка проходит без драм. Если бы я оценивал только удобство API, оценка была бы высокой.
Но я снова и снова возвращаюсь к тому, что ключевая заявка фреймворка — антидетект — это как раз то, о чём ответственный обзор не должен рассуждать, не проверив всё на реальной защитной инфраструктуре. У драйвера действительно есть открытый API с антидетект-ориентированными методами: я подтвердил их наличие, но не проверял их поведение на конкретной цели. На этом и всё, что я готов утверждать. Я не направлял его на защищённый сайт, не измерял процент успеха, не реверс-инжинирил механизм и не буду намекать на это формулировками. Методы в классе есть. Что они дают в реальном мире — это уже совсем другой обзор.
Дальше будет инвентаризация возможностей, установки, ресурсов и лицензии, а затем то, что драйвер делает на странице, которую контролирую я сам. Это более узкое утверждение, чем в большинстве обзоров подобных инструментов, и именно в этой узости смысл.
Что он сообщает о себе

Вот вопрос, на который можно ответить, не приближаясь к реальной защите: когда Botasaurus управляет браузером, что именно этот браузер сообщает о себе странице? Я написал страницу, которая читает очевидные вещи — navigator.webdriver, user-agent, platform, languages, количество плагинов и аппаратных потоков, форму window.chrome, ответы Permissions API, геометрию окна и экрана, — выложил её на 127.0.0.1 и направил на неё четыре стека: Botasaurus, nodriver, а также стандартные Playwright и Puppeteer в качестве контрольных примеров. Все четыре управляли одной и той же сборкой Chrome (Chrome for Testing 151.0.7922.10), так что любые различия — это различия библиотек, а не браузера. В headless и headed режимах было по три прогона. Все значения ниже совпадали во всех трёх.
| Стек | Режим | navigator.webdriver | Токен user-agent | navigator.languages |
|---|---|---|---|---|
| Botasaurus 4.0.92 | headless | false | HeadlessChrome/151.0.0.0 | ["en-US"] |
| Botasaurus 4.0.92 | headed | false | Chrome/151.0.0.0 | ["en-US"] |
| nodriver 0.50.3 | headless / headed | false | HeadlessChrome/151 / Chrome/151 | ["en-US"] |
| Playwright 1.56.0 | headless / headed | true | HeadlessChrome/151 / Chrome/151 | ["en-US","en"] |
| Puppeteer 24.16.0 | headless / headed | true | HeadlessChrome/151 / Chrome/151 | ["en-US"] |
Различия зависят от того, какой контрольный стек ты берёшь за точку сравнения. По сравнению со стандартным Puppeteer, Botasaurus изменил navigator.webdriver; список языков и геометрия окна совпали, а user-agent отличался только форматом версии. По сравнению со стандартным Playwright наблюдаемые расхождения включали ещё и список языков и размеры окна. По сравнению с nodriver булево значение и языки совпали, а отличался только формат user-agent в показанных полях. Это наблюдения о том, что по умолчанию раскрывает стек, а не оценка антидетекта.
Есть две детали, которые делают картину интереснее, чем просто false. Первая — как именно это значение появляется. Во всех четырёх стеках свойство остаётся нативным геттером браузера на Navigator.prototype — function get webdriver() { [native code] }, — а не собственным свойством, внедрённым в экземпляр, и не подменённой функцией. То есть Botasaurus не переписывает свойство после загрузки страницы; значение определяется при старте браузера, а само свойство при этом не трогается.
Вторая деталь — это то, что ограничивает маркетинговую формулировку. В headless-режиме user-agent у Botasaurus всё равно сообщает HeadlessChrome/151.0.0.0 — в точности как стандартный Puppeteer и стандартный Playwright. Если запустить headed-режим, строка становится Chrome/151.0.0.0, тоже без отличий. В конструкторе Driver есть параметр user_agent, так что задать свой вариант можно одной опцией, но в настройках по умолчанию ничего не маскирует самую известную сигнатуру браузерной автоматизации.
Почти всё остальное совпало во всех четырёх стеках, и это тоже важно сказать прямо, потому что так история становится уже — ниже перечисленные свойства были одинаковыми у Botasaurus, nodriver, Playwright и Puppeteer:
| Свойство | Значение, одинаковое для всех четырёх стеков |
|---|---|
platform | MacIntel |
vendor | Google Inc. |
| Плагины | пять |
| MIME-типы | два |
pdfViewerEnabled | true |
| Логические ядра | двенадцать |
| Заявленный объём памяти устройства | 16 GB |
| Количество touch-точек | ноль |
window.chrome | присутствует, с app/csi/loadTimes и без runtime |
| Строка WebGL renderer | одинакова во всех четырёх |
Старая история, когда Permissions API и Notification.permission противоречат друг другу, нигде не всплыла — все четыре стека вернули согласованные default и prompt. Я также просканировал document и window на остатки в стиле cdc_, характерные для старых WebDriver-стеков: везде пусто.
Ещё один полезный факт перед внедрением: при всех своих 122 МБ Botasaurus не поставляет и не скачивает браузер. find_chrome_executable() находит тот Chrome, который уже установлен в системе — у меня это /Applications/Google Chrome.app, версия 150.0.7871.187 — и именно эту версию затем и раскрывает user-agent. Ваш парк сообщает ровно ту версию Chrome, которая стоит на ваших машинах. Для настолько «мнениями насыщенного» фреймворка это удивительно немнительный дефолт.
Назовём вещи своими именами. Это запись о том, что автоматизированный стек раскрывает, когда его никто не просит скрываться. Полезно для тех, кто защищается, и полезно, если ты хочешь понять, что именно транслируют твои инструменты. Но это не измерение того, насколько это важно для какого-либо конкретного сервиса. Я этого не тестировал, и ни одна строка выше не должна читаться как намёк на результат.
Более мягкий взгляд на поведение на тестовой странице
Объявить о себе — одно, а вернуть правильный HTML — совсем другое. Я прогнал Botasaurus на той же тестовой странице с тремя классами контента, которую использует и остальная часть этого бенчмарка, чтобы цифры можно было сопоставить с другими инструментами. На странице есть три сущности: A — статическая ссылка, маркер которой буквально присутствует в байтах ответа; B — узел, созданный встроенным скриптом во время разбора, где и маркер, и URL собираются из фрагментов, так что увидеть их можно только после выполнения JavaScript; и C — узел, внедряемый через 800 мс после события load, собранный тем же способом. Класс C — самый неудобный: если читать страницу в момент load, его не видно.
| Стек | Значение по умолчанию | При явном ожидании |
|---|---|---|
| Botasaurus 4.0.92 | 2 из 3 (A + B, C пропускается) | 3 из 3 |
| nodriver 0.50.3 | 2 из 3 | 3 из 3 |
| Playwright 1.56.0 | 2 из 3 | 3 из 3 |
| Puppeteer 24.16.0 | 2 из 3 | 3 из 3 |
Botasaurus приходит к тем же результатам, что и тяжеловесы. driver.get(), за которым сразу идёт driver.page_html, — это снимок на момент загрузки: JavaScript он отрабатывает корректно, и класс B это доказывает, поскольку B вообще не существует в исходных байтах страницы, — но контент, появляющийся через 800 мс, он пропускает. Добавь driver.wait_for_element("#delayed-injected"), и получишь все три. Результат стабилен в трёх повторах и трёх отдельных прогонах всего набора, без флаков.
Интереснее становится при переборе задержки внедрения, чтобы увидеть, где именно стандартное чтение каждого стека сдаётся:
| Класс C внедрён через | Botasaurus | nodriver | Playwright | Puppeteer |
|---|---|---|---|---|
| 0 ms | найден | найден | найден | найден |
| 100 ms | найден | — | — | — |
| 200 ms | найден | — | — | — |
| 300 ms | найден | — | — | — |
| 400 ms и выше | — | — | — | — |
Все остальные стеки теряют класс C, как только он появляется через 100 мс или позже после load. Botasaurus всё ещё ловит его на 300 мс и сдаётся только на 400. Это и есть поведение фреймворка как фреймворка, а причина видна прямо в конструкторе: wait_for_complete_page_load=True включён по умолчанию, поэтому get() возвращается заметно позже, чем просто событие load. На практике это означает 401–431 мс wall clock на чтение по умолчанию против 119–129 мс у nodriver и 125–171 мс у Puppeteer.
На этом локальном fixture с отложенной инъекцией компромисс составил примерно 250 мс на каждую навигацию ради более позднего снимка по умолчанию. Это позволило захватить контент, появляющийся до 300 мс после load, но не доказывает, что Botasaurus объективно точнее на любых сайтах. Если ты пишешь быстрые скрейперы без явных условий ожидания, этот запас может помочь не пропустить поздний узел. Но при высокой частоте навигаций или если ты уже ждёшь конкретное условие, это просто накладные расходы.
Ещё две цифры для понимания масштаба. Подъём браузера у Botasaurus оказался примерно на уровне nodriver и Puppeteer и заметно позади Playwright:
| Стек | Запуск браузера, по всем прогонам |
|---|---|
| Botasaurus 4.0.92 | 986–1151 ms |
| nodriver 0.50.3 | 910–1583 ms |
| Puppeteer 24.16.0 | 969–1008 ms |
| Playwright 1.56.0 | 282–365 ms |
А wait_for_element() ничего не добавляет до задержки 300 мс — к этому моменту get() уже дошёл до точки, где инъекция видна, — затем увеличивает время примерно до 1,42 с при 400–800 мс и до 2,43 с при 1500 мс.
Вопрос о 122 МБ: что на самом деле ставит метапакет

Вот арифметика, потому что это, пожалуй, самое полезное, что я могу тебе дать. Чистая установка pip install botasaurus в свежем virtualenv создала дерево site-packages объёмом 122,3 МБ и 44 dist-info-пакета. Если вычесть сам pip (10,9 МБ, то есть это накладные расходы venv, а не то, что запросил Botasaurus), то останется примерно 111 МБ фреймворка и зависимостей. Сам браузерный драйвер — компонент, который и занимается автоматизацией, — весит около 4 МБ. То есть примерно 107 МБ — это всё остальное, что метапакет решил тебе навязать.
Куда уходят эти мегабайты? На пять самых тяжёлых транзитивных зависимостей приходится основная масса (каждая строка — это поле install_footprint.heaviest_deps_mb из artifacts/raw/runs/resource_baseline.run1.json; итог я считаю сам, в файле его нет):
| Пакет | Размер на диске |
|---|---|
| numpy | 30,9 МБ |
| lxml | 19,2 МБ |
| botasaurus_requests | 12,6 МБ |
| gevent | 11,3 МБ |
| pygments | 8,4 МБ |
| Пять пакетов вместе | 82,4 МБ (30,9 + 19,2 + 12,6 + 11,3 + 8,4) |
То, что numpy оказался самым крупным элементом, заставило меня приподнять бровь: это библиотека для линейной алгебры внутри инструмента, который в основном должен получать и парсить веб-страницы. Строго говоря, это не ошибка; фреймворки обрастают вспомогательными зависимостями, и, очевидно, что-то в дереве хочет работать с массивами. Просто машин для такой работы многовато.
Для масштаба: узкий драйвер nodriver весит около 17,2 МБ и состоит из 6 пакетов на той же машине — то есть примерно в 7 раз легче. (Эта цифра не из этого пакета: это install_footprint.site_packages_total_mb в собственном artifacts/raw/runs/resource_baseline.run1.json nodriver, измеренный отдельным прогоном на том же хосте; 122,3 ÷ 17,2 = 7,1.) Ни одна из этих цифр не является дефектом, и это не рейтинг возможностей; это просто механическая разница между фреймворком «с батарейками в комплекте» и узким драйвером. В контейнере измеренный размер site-packages добавляется к слою приложения. Это не полный размер образа, и в этом тесте я не измерял ни сборку, ни холодный деплой.
Ещё одна особенность footprint: во время инспекции первый вызов from botasaurus.request import request вызвал одноразовую загрузку примерно 12,8 МБ. По сохранённому прогону нельзя было достаточно уверенно определить артефакт и место назначения, чтобы считать это стабильным увеличением установленного размера. Но это показывает, что при первом использовании этому коду может понадобиться сетевой доступ — и это стоит проверить в собственном образе до развёртывания в изолированной среде.
Импорт, который обманывает
Замер cold-start импорта — то место, где простое чтение цифр вводит в заблуждение. Если брать семь свежих subprocess-импортов, import botasaurus на верхнем уровне дал медиану 0,08 мс. Если цитировать только это, кажется, что перед тобой самый лёгкий фреймворк в категории.
Но это не так. Он быстрый потому, что внутри почти ничего нет. Верхнеуровневый пакет botasaurus не экспортирует даже __version__ и почти не содержит публичного пространства имён — импорт почти ничего не делает, потому что почти ничего не содержит. Цифра, которая действительно важна для CLI или serverless cold start, — это импорт ядра: from botasaurus_driver import Driver занимает около 135 мс, и разброс по прогонам — всего несколько миллисекунд. Это и есть реальная фиксированная цена, которую ты платишь до того, как будет получена хоть одна страница. А после импорта модуля драйвера resident memory составляет примерно 29–30 МБ — опять же, до запуска любого Chrome-процесса. Если запустить настоящий браузер, это вырастет заметно; память с уже запущенным браузером я не измерял, поэтому цифру не назову.
Вывод здесь короткий, но важный: мгновенный import botasaurus — это свойство пустоватого верхнего пакета, а не дешёвизны самого фреймворка. Если считаешь cold start, измеряй тот импорт, на который реально будешь опираться.
API-форма: 99 методов за почти пустым входом

Класс Driver в ядре предоставляет 99 публичных методов — широкий набор, покрывающий навигацию, поиск элементов, cookies и local storage, действия мышью и клавиатурой, скриншоты, управление вкладками, передачу CDP-команд и загрузку файлов. Конструктор принимает 18 параметров, и это вполне нормальная карта настраиваемых опций: headless, proxy, profile, tiny_profile, block_images, block_images_and_css, wait_for_complete_page_load, chrome_executable_path, extensions, arguments, user_agent, window_size, lang и ещё несколько. Как API уровня создания объекта, он закрывает обычные потребности browser automation.
Особенность формы — на верхнем уровне, и она не вредная, но реальная. import botasaurus даёт почти пустое пространство имён: ни __version__, ни по сути каких-либо верхнеуровневых публичных объектов. Всё, чем ты будешь пользоваться, находится в подмодулях: from botasaurus.browser import browser, Driver, from botasaurus.request import request, from botasaurus.task import task. Если захочешь записать в лог версию через botasaurus.__version__, у тебя это не получится; придётся обращаться к importlib.metadata. Это ничего не ломает. Просто это не та структура, которую Python-разработчик обычно ожидает автоматически, и понимание этого экономит несколько минут недоумения в первый день.
Одно наблюдение по документации к методам, о котором я говорил выше, вполне честное и укладывается в мои рамки: из тех методов с антидетект-ориентированными названиями, которые существуют, только 2 имеют docstring прямо в коде. Остальные самоочевидны только по названию, а подробная документация живёт на внешнем сайте, а не в установленном исходнике. Это замечание о локализации документации, а не оценка качества — многие хорошие библиотеки выносят тексты из кода — но если твой рабочий стиль это «читать исходники, чтобы понять метод», большая часть этой поверхности скажет тебе только имя и ничего больше.
Лицензия: MIT до самого драйвера
И метапакет, и botasaurus-driver распространяются под MIT, с классическим классификатором License :: OSI Approved :: MIT License. MIT — это permissive-лицензия: без copyleft-обязательств, без требования открывать собственный код, с минимальными барьерами для коммерческого использования. Это действительно важное и неочевидное отличие от nodriver, соседнего anti-detect-драйвера, который выходит под AGPL-3.0 — copyleft-лицензией, чьё положение о сетевом использовании заставляет многие юридические отделы нервничать. Если лицензия для тебя — ограничивающий фактор, MIT у Botasaurus — это реальный плюс.
Но тут снова важно помнить о форме метапакета. Этот permissive MIT относится к собственным wheel-пакетам Botasaurus. Он автоматически не покрывает примерно 40 транзитивных зависимостей, которые ставятся вместе с ним, и у каждой из них своя лицензия. Я подтвердил MIT на верхнем уровне у пакетов, которые публикует Omkar Cloud; лицензии каждой зависимости в дереве я не аудировал. Для хобби-проекта это обычно не критично. Для корпоративного внедрения всего дерева, где важен software bill of materials, эти 40 пакетов нужно прогнать через собственный лицензирующий сканер до принятия решения — не потому, что я нашёл проблему, а потому, что я её не проверял, а метапакет — как раз то место, где может скрываться неожиданный лицензированный компонент.
Плюсы и минусы
Плюсы:
- Чистый дизайн с тремя декораторами (
@browser/@request/@task), и все три точки входа действительно есть — типовой сценарий получается коротким. - Лицензия MIT и у метапакета, и у драйвера; это заметный контраст с AGPL-3.0 у сопоставимого драйвера. Permissive, удобно для бизнеса, без copyleft.
- Широкая поверхность драйвера: 99 публичных методов и конструктор с 18 параметрами покрывают обычные потребности browser automation.
- Установка и smoke-тест импорта прошли под Python 3.14.2 и 3.12.13, то есть версиями новее, чем заявленные в classifiers (они заканчиваются на 3.11); полная runtime-совместимость не подтверждена.
- Самое «позднее» окно корректного default-read среди всех стеков, которые я измерял: контент, внедрённый через 300 мс после load, всё ещё подхватывается, тогда как nodriver, Playwright и Puppeteer теряют его уже на 100 мс.
wait_for_complete_page_load=Trueреально работает. - По умолчанию
navigator.webdriverвозвращается какfalse, тогда как оба стандартных контроля показываютtrue, и при этом свойство не патчится — дескриптор остаётся нативным геттером браузера. - Дизайн с батарейками в комплекте: кэширование, параллельность, повторное использование драйвера и вывод в JSON/CSV/Excel/HTML уже входят во фреймворк, а не прикручиваются отдельно.
Минусы:
- Тяжёлый на диске: 122,3 МБ и 44 пакета, примерно в 7 раз больше, чем у узкого драйвера, причём вес создают зависимости вроде numpy (30,9 МБ) и lxml (19,2 МБ), а не сам драйвер (~4 МБ).
- Успокаивающий
import botasaurusна 0,08 мс вводит в заблуждение; нужный тебе импорт ядра — около 135 мс, а после него resident memory уже порядка 29–30 МБ, ещё до запуска браузера. - Более «мягкое» default-read окно съедает около 250 мс на каждую навигацию.
- Headless-режим по умолчанию всё ещё раскрывает
HeadlessChromeв user-agent, в точности как стандартные стеки; параметрuser_agentесть, но автоматически его никто не задаёт. - При весе в 122 МБ фреймворк всё равно не поставляет браузер — он использует тот Chrome, который уже установлен в системе, так что раскрываемая версия браузера зависит от парка машин.
- Первый вызов
@requestв этом прогоне вызвал одноразовую загрузку примерно 12,8 МБ; артефакт и место назначения не были зафиксированы достаточно хорошо, чтобы считать это стабильным увеличением размера установки. - Верхнеуровневый пакет почти пустой и не экспортирует
__version__; реальный API и версия живут не там, где их обычно ищут. - У большинства методов с антидетект-ориентированными названиями нет docstring в коде, так что из исходников ты увидишь имена, но не поведение.
Вне того, что покрывали эти числа, и потому здесь не тестировалось: всё, что касается реальной антибот-эффективности (это сознательно вне scope), память на уровне отдельных страниц, работа с proxy и profile, пропускная способность на масштабе и любые платформы кроме macOS arm64. Показатели размера и импорта были получены вообще без запуска браузера; цифры по корректности чтения и по раскрытию данных — с браузеров, которые общались только с fixture на 127.0.0.1.
Для кого это и кому лучше пройти мимо
Botasaurus подойдёт, если тебе нужен именно фреймворк, а не отдельная деталь. Если ты начинаешь скрейпинг-проект с пустого файла и предпочёл бы взять готовую структуру, а не собирать её самому — декораторы для входных точек, кэширование и параллельность уже решены, вывод встроен — это цельный MIT-licensed вариант. MIT permissive, но твоя модель использования и распространения всё равно заслуживает обычной проверки на compliance. Команды, которые уже мыслят в терминах Scrapy или Crawlee, быстро поймут логику этого подхода.
Лучше пройти мимо, или хотя бы серьёзно подумать ещё раз, если твой target чувствителен к размеру. Установка на 122 МБ с numpy и gevent внутри — это много для slim-контейнера, если реальная задача звучит как «управлять браузером и вытащить несколько полей». Узкий драйвер даст автоматизацию при куда меньшем весе, но тебе придётся самому писать всю обвязку. И точно не стоит брать его, если тебе нужен ответ именно об anti-detect-эффективности, потому что это единственное, чего я сознательно не проверял, — ты бы доверял маркетинговому обещанию, которое я ни подтвердил, ни опроверг.
Альтернативы и место Thunderbit
Сначала честная рамка: Botasaurus бесплатный, под MIT и self-hosted. Ты сам запускаешь инфраструктуру, сам управляешь обновлениями и владеешь всем деревом зависимостей — всеми 44 пакетами — включая патчи, соблюдение лицензий и всё, что numpy решит сделать в следующем релизе. Для многих команд именно такая модель и нужна, и никакой managed service не победит по цене «фреймворк, который у тебя уже есть».
Среди open source сравнения удобнее строить по форме. Если ты на стороне фреймворков вместе с Botasaurus, Scrapy и Crawlee — очевидные кандидаты для сравнения: зрелые, с выраженной философией и собственными соглашениями. Если тебе нужен LLM-ready Markdown со страницы, а не фреймворк для построения краулера, Crawl4AI и ориентированная на контент Trafilatura решают именно эту задачу. Если тебе нравится связка Python и anti-detect, но хочется чего-то легче метапакета, стоит посмотреть на Scrapling, а если возможен язык с компиляцией — Go-библиотека Colly меняет рендеринг JavaScript на скорость и крошечный footprint. Любой вариант с управлением браузером, включая Botasaurus, наследует тот же профиль затрат, который описан в нашем сравнении Playwright и Puppeteer: реальные браузеры не дёшевы в эксплуатации, и именно поэтому окружающий их фреймворк весит столько, сколько весит.
Когда в цепочку входит managed API, это уже другой участок того же процесса. Botasaurus — это self-hosted стек для разработчика; Thunderbit продаёт управляемый вариант, ориентированный на тех же разработчиков. Open API состоит из двух endpoint’ов. POST /distill (1 кредит) возвращает страницу в виде чистого Markdown, готового для LLM, а рендеринг и anti-bot часть обрабатываются на сервере, так что браузер и дерево зависимостей тебе вообще не нужны. POST /extract (20 кредитов) возвращает структурированный JSON по JSON Schema, которую ты задаёшь сам, а renderMode можно выставить в none, basic или full в зависимости от того, сколько браузера реально требуется странице. У обоих есть batch-версии для обработки до ста URL за раз. Для агентов и coding assistants есть MCP server — thunderbit_suggest_fields бесплатен и покажет, какие поля есть на странице, прежде чем ты потратишь что-либо. Есть и CLI через npx @thunderbit/thunderbit-cli для cron и CI. Для тех, кто не хочет вообще ничего трогать руками, Chrome extension использует тот же движок как no-code инструмент, а пошаговые объяснения на YouTube-канале Thunderbit покрывают типовые сценарии.
Разница не в том, что «лучше», а в том, где находится работа. Botasaurus оставляет у тебя и фреймворк, и парк браузеров, и зависимости, и инфраструктуру, и обслуживание — без помесячной платы за запрос; но compute, bandwidth, proxies и operations всё равно стоят денег. Managed API забирает у тебя рендеринг и схематизированный вывод и берёт плату за вызов — это можно сравнить с self-hosted вариантами на странице тарифов.
Попробовать Thunderbit для извлечения веб-данных
Вердикт
Botasaurus — вполне разумный кандидат, если тебе нужен Python-фреймворк «всё в одном» и ты готов принять его footprint зависимостей. Дизайн с тремя декораторами аккуратный, поверхность драйвера широкая, а smoke-тесты установки и импорта он прошёл на версиях Python новее тех, что заявлены в classifiers. На моём локальном fixture его default snapshot также поймал контент, внедрённый через 300 мс после load, тогда как другие проверенные стеки пропустили его уже на 100 мс; это результат именно на fixture, а не общий рейтинг.
Но масштабировать заявления нужно правильно. Это установка на 122 МБ и 44 пакета, где драйвер занимает около 4 МБ, а остальное — numpy, lxml, gevent и компания; примерно в 7 раз тяжелее узкого драйвера, и эта тяжесть ложится на размер контейнера и время cold deploy. Верхнеуровневый импорт на 0,08 мс — пустая входная дверь, а не лёгкий фреймворк; реальные 135 мс импорта ядра — вот за что ты платишь. Более мягкое default-read окно съедает около 250 мс на каждую навигацию. А если говорить о дефолтном раскрытии данных, которое я реально смог проверить, картина уже более узкая, чем обещает маркетинг: от стандартного Puppeteer отличается только один булевый флаг, headless user-agent всё ещё говорит HeadlessChrome, а все остальные свойства, которые я измерял, совпали во всех четырёх стеках. Обещание антидетекта — это именно та часть, которую этот обзор не оценивает: я подтвердил наличие методов, прогнал драйвер на странице на своей машине и на этом остановился сознательно. Если знать footprint, не верить лестному числу импорта и относиться к stealth-маркетингу как к открытому вопросу, Botasaurus остаётся честным фреймворком, который делает именно то, что и должен делать фреймворк. Если ты ждёшь драйвер как пушинку, удивишься уже на этапе docker build.
Попробовать Thunderbit для извлечения веб-данных Get Started Free
Частые вопросы
Botasaurus бесплатный и под какой лицензией он распространяется?
Да, он бесплатный и под лицензией MIT — и метапакет botasaurus, и движок botasaurus-driver имеют классификатор OSI-approved MIT. MIT permissive, поэтому здесь нет copyleft-обязательств и она удобна для коммерческого использования, что заметно отличает Botasaurus от сопоставимых anti-detect драйверов под AGPL-3.0. Но есть оговорка: MIT покрывает только собственные пакеты Omkar Cloud, а не автоматически примерно 40 транзитивных зависимостей, которые ставятся вместе с ними, так что перед корпоративным внедрением всего дерева запусти собственный license scan.
Сколько весит Botasaurus и почему import botasaurus выглядит мгновенным?
Чистая установка pip install botasaurus на моей машине дала дерево site-packages объёмом 122,3 МБ и 44 пакета. Сам браузерный драйвер занимает примерно 4 МБ — вес создаёт метапакет, который подтягивает широкое дерево зависимостей, во главе с numpy (30,9 МБ), lxml (19,2 МБ), botasaurus_requests (12,6 МБ), gevent (11,3 МБ) и pygments (8,4 МБ). Это примерно в 7 раз тяжелее, чем узкий драйвер вроде nodriver на той же машине. Это не дефект; таков ценник за «батарейки в комплекте», и сильнее всего это влияет на размер контейнера. А вот время импорта прячет этот footprint: import botasaurus показывает около 0,08 мс, но только потому, что верхнеуровневый пакет почти пустой — без __version__ и почти без публичных объектов, поэтому импорт почти ничего не делает. Импорт, который действительно стоит денег, — это ядро from botasaurus_driver import Driver, примерно 135 мс, а resident memory после этого импорта и до запуска браузера — порядка 29–30 МБ. Если ты считаешь serverless cold start, измеряй импорт ядра, а не пустого верхнего пакета.
Что Botasaurus раскрывает о себе и тестировали ли его против реальных anti-bot систем?
Первая часть была измерена; вторая — сознательно нет. На странице, которую я отдал с 127.0.0.1, и при том же Chrome, что использовали контрольные стеки: navigator.webdriver возвращается как false, тогда как стандартные Playwright и Puppeteer оба показывают true. Это значение задаётся при запуске браузера, а не путём патча свойства — дескриптор остаётся нативным геттером Chrome. Кроме этого булева значения почти всё совпало с контрольными стеками: та же строка platform, пять плагинов, двенадцать ядер, 16 GB заявленной памяти устройства, та же форма window.chrome, без противоречий Permissions API и без остатков вида cdc_ в document или window. Headless-режим всё равно раскрывает HeadlessChrome/151.0.0.0 в user-agent, как и оба контроля — в конструкторе Driver есть параметр user_agent, но автоматически его никто не задаёт. Что касается эффективности: я ни разу не направлял драйвер на живой сайт, не обращался к anti-bot-сервису и не трогал CAPTCHA. В драйвере действительно есть набор методов с anti-detect-ориентированными названиями, и я подтвердил их существование, но я не вызывал их, не проверял их поведение на цели, не измерял процент успеха и не описывал механизм. Таблица раскрытия выше говорит только о том, что стек сообщает о себе, и ничего о том, кто это видит и как реагирует.
Botasaurus корректно обрабатывает JavaScript-рендеринг?
Да, и его поведение по умолчанию более мягкое, чем у многих. На fixture с тремя классами контента driver.get() + driver.page_html вернули 2 из 3 при задержке инъекции 800 мс — JavaScript он выполняет корректно, но читает страницу до того, как самый поздний контент успевает появиться, — а driver.wait_for_element() вернул 3 из 3. Отличие в том, где именно default-read сдаётся: Botasaurus всё ещё ловит контент, внедрённый через 300 мс после load, тогда как nodriver, Playwright и Puppeteer теряют его уже на 100 мс. Это связано с wait_for_complete_page_load=True в конструкторе и стоит примерно 250 мс на каждую навигацию.
Как импортировать и использовать Botasaurus после установки?
Не так, как можно было бы подумать. Верхнеуровневое пространство имён botasaurus почти пустое, поэтому реальный API находится в подмодулях: from botasaurus.browser import browser, Driver, from botasaurus.request import request, from botasaurus.task import task. Ты помечаешь обычную функцию декоратором @browser, @request или @task, а фреймворк сам обслуживает драйвер, кэш и вывод. Поскольку botasaurus.__version__ не существует, для логирования версии используй importlib.metadata.


