Большинство знакомится с Crawlee, когда пытается ответить на другой вопрос: «какой headless-браузер мне выбрать?» Но это неправильный вопрос — и как раз в этом суть Crawlee. Это не браузер. Это фреймворк для Node/TypeScript, который подключает браузер, когда он нужен, и обходится без него, когда он не нужен.
Я потратил пару дней на тестирование Crawlee 3.17.0 на наборе контролируемых фикстур и нескольких публичных демо-сайтах, используя Node v22.22.3 и macOS. Главная идея — одна библиотека, один API, а внутри либо HTTP-краулер, либо полноценный браузер — как раз то, что хотелось проверить особенно тщательно. Ведь именно это решает, стоит ли добавлять Crawlee в свой стек или проще сразу использовать Playwright. Коротко: история с двумя движками действительно работает, хотя с несколькими оговорками, к которым я ещё вернусь.
Что такое Crawlee на самом деле — и чем он не является
Crawlee описывает себя как библиотеку для веб-скрапинга и автоматизации браузера в Node.js, созданную для надёжных краулеров. Официальная позиция довольно широкая: извлечение данных для AI, LLM, RAG или GPT; загрузка HTML, PDF, JPG, PNG и других файлов; поддержка Puppeteer, Playwright, Cheerio, JSDOM и обычного HTTP; работа в headful- и headless-режиме; ротация прокси включена. Область применения очень большая, поэтому полезно сразу сказать, чем Crawlee не является.
Это не движок рендеринга. У него нет собственного браузера. Если нужно выполнять JavaScript, Crawlee управляет Playwright или Puppeteer, а те, в свою очередь, запускают Chromium (или другой браузер). Это также не облачный сервис, к которому вы обращаетесь по сети — это зависимость, которую вы устанавливаете и запускаете сами. А вот чем Crawlee является — так это надстройкой над получением страниц: классами краулеров, очередью запросов, хранилищем, логикой перехода по ссылкам. Проще говоря, это каркас для обхода сайтов, внутри которого можно подставить нужный движок.
Для справки: тестируемая мной версия — 3.17.0 (выпущена 2026-06-04), язык — TypeScript, лицензия — Apache-2.0, а репозиторий apify/crawlee к 2026-07-09 имел примерно 24,6k звёзд. Количество звёзд меняется — за те два дня, пока я следил, репозиторий набрал ещё 53 — так что воспринимайте это как снимок на момент времени, а не как неизменный факт.
Два движка: CheerioCrawler и PlaywrightCrawler
Вот здесь архитектура Crawlee действительно раскрывается, и именно на этом я провёл большую часть времени.
CheerioCrawler — это HTTP-путь. Он забирает сырой HTML по сети и разбирает его с помощью Cheerio — без браузера, без выполнения JavaScript, без рендеринга. Это быстро и дёшево. PlaywrightCrawler — это путь через браузер. Он запускает настоящий Chromium, рендерит страницу вместе со всем JavaScript, который строит DOM, и даже умеет делать скриншоты.
Два разных движка с действительно разными возможностями. При этом Crawlee делает важную ставку: снаружи они выглядят почти одинаково. Оба принимают requestHandler. У обоих есть run(). Оба обходят ссылки через enqueueLinks. Переход с одного движка на другой — это замена класса, а не переписывание логики. Я проверил это, оставив код извлечения данных байт-в-байт одинаковым и меняя только класс краулера-обёртки.

Здесь важно быть точным, потому что именно на этом месте заканчивается полное совпадение: объект для доступа к контенту отличается. В обработчике CheerioCrawler вы получаете $ — статичную уже распарсенную DOM-структуру, с которой можно работать как с jQuery. В браузерном обработчике вы получаете живой объект page. То есть очередь, маршрутизация, логика «записать данные и перейти по этим ссылкам» остаются одинаковыми, но там, где вы реально читаете страницу, форма объекта меняется. В документации Crawlee это и так сказано — общий интерфейс касается операций краулинга, а доступ к контенту зависит от движка.
| Движок | Как получает страницу | Выполняет JavaScript? | Мой тест (1 динамическая страница) | Лучше всего подходит для |
|---|---|---|---|---|
CheerioCrawler | Обычный HTTP + парсинг Cheerio | Нет | ~0,035 с | Статичный HTML, JSON API, скорость |
PlaywrightCrawler | Настоящий Chromium через Playwright | Да | ~4,967 с | Страницы, рендерящиеся JS, скриншоты |
Эти цифры получены на одном компьютере и в одном прогоне — это не бенчмарк, а лишь наглядная демонстрация компромисса. Браузерный путь оказался примерно на два порядка медленнее на том же URL. Это и есть цена рендеринга, поэтому использовать его по умолчанию не стоит.
Тест: один и тот же URL, результат 0 против 8/8
Обещания — вещь дешёвая. Причина, по которой я доверяю истории с двумя движками, в том, что мне удалось заставить её «сломаться», а затем исправить всё простой заменой класса.
Я сделал локальную динамическую фикстуру — страницу каталога, где карточки товаров подгружаются JavaScript после загрузки, то есть типичный современный сайт. Я направил на неё CheerioCrawler. Он вернул 0 карточек товаров. Это не баг, а физика: Cheerio не выполнял JavaScript, поэтому карточек просто не было в HTML, который он разбирал. Затем я направил на тот же URL PlaywrightCrawler, ничего больше не меняя, и он отрендерил 8 из 8 товаров и сделал скриншот в подтверждение.

Чтобы убедиться, что это не особенность моей собственной фикстуры, я повторил тот же сценарий на публичном сайте — демо-странице Quotes to Scrape, где цитаты собираются на стороне клиента. Результат был тем же: CheerioCrawler увидел 0 цитат, PlaywrightCrawler восстановил 10.

Важно уточнить, что именно это доказывает. По сути, это аккуратное подтверждение того, что Crawlee уже документирует: с версии 3.0 у всех типов краулеров общий базовый класс и единый интерфейс. Так что это не открытие, а проверка. Но именно в этом и ценность: рекламный тезис «один интерфейс, HTTP или браузер» действительно работает, и вот вам наглядное подтверждение 0 → полные данные и на моей фикстуре, и на внешнем сайте.
Где HTTP-путь выигрывает
Легко после предыдущего раздела подумать: «значит, всегда нужен браузер». Нет. Смысл двух движков как раз в том, что браузер — это дорогой запасной вариант, а не стандартный режим.
На статичном контенте CheerioCrawler оказался и точным, и быстрым. Моя статическая каталоговая фикстура вернула 12 из 12 товаров с полной полнотой, переходя по страницам через enqueueLinks({ selector: '.next-page' }), примерно за 0,155 секунды. Страница статьи отдала заголовок и все 3 из 3 абзаца, при этом служебные блоки вроде логина, подписки и копирайта были аккуратно отделены от основного текста.
Самый полезный вывод такой: страница, данные которой подгружаются через JavaScript, часто имеет рядом JSON API. Данные моей динамической фикстуры лежали в отдельном endpoint’е, и когда я направил CheerioCrawler прямо туда, он восстановил 8 из 8 товаров — без браузера, примерно за 0,035 секунды. Те же данные браузерный путь рендерил почти пять секунд. Урок старый, но по-прежнему верный: если можно воспроизвести исходный запрос, лучше сделать именно это, а не запускать Chromium. Crawlee позволяет выбирать этот путь на уровне конкретного краулера без смены фреймворка.
Зачем вообще нужен crawl-фреймворк (и почему Crawlee лучше голого browser lib)
Если бы вам нужно было просто отрендерить одну страницу, Crawlee был бы избыточен — хватило бы Playwright или Puppeteer. Но «голая» библиотека браузера не даёт главное: полноценный обход сайта, очередь, дедупликацию, контроль глубины, повторные попытки. Именно эта часть Crawlee и делает его не просто оболочкой над браузером.
Я запустил обход внутри одного домена, начиная с корня фикстуры, с enqueueLinks и отслеживанием глубины. Crawlee обошёл 11 страниц на глубинах {0:1, 1:3, 2:7} — одна корневая, три страницы на один переход и семь страниц на два перехода — и корректно соблюдал maxRequestsPerCrawl как ограничение остановки. Учёт запросов вёл RequestQueue. Когда я направил запрос на страницу, возвращавшую HTTP 500, Crawlee повторил попытку и затем передал ошибку через failedRequestHandler, а не проглотил её молча и не уронил весь запуск.

Это самый сильный аргумент в пользу Crawlee по сравнению с отдельной browser-библиотекой: вся оркестрация обхода уже встроена, и, что особенно важно, она одинаковая независимо от того, HTTP-движок или браузер стоит под капотом. Логику очереди и переходов вы пишете один раз. А решение о том, рендерить ли JavaScript для конкретного краулера, принимаете отдельно.
Установка и скрытая загрузка браузера
Установка прошла в целом безболезненно, но есть одна ловушка, на которой часто спотыкаются новички.
npm install crawlee playwright прошёл чисто — уязвимостей не было. Но PlaywrightCrawler не запустится, пока вы отдельно не выполните npx playwright install chromium, а это загрузит бинарник Chromium размером около 81,7 MiB. Установка только пакета crawlee браузер не скачивает. Если пропустить этот шаг и сразу перейти к браузерному краулеру, вы получите ошибку запуска, которая неочевидна, если вы не знакомы с моделью поставки Playwright. Это наследуемое поведение Playwright, а не дефект Crawlee, но в первый запуск оно реально мешает и о нём стоит помнить.

Ещё один практический момент: по умолчанию Crawlee пишет данные в локальную папку storage/. Мой тестовый стенд перенаправлял это во временный каталог и отключал сохранение, чтобы не оставлять мусор, но обычный запуск всё равно создаст у вас storage/ в проекте. Это не проблема, просто вещь, о которой лучше знать заранее, прежде чем она появится в git status.
Коротко о третьем движке
История с паритетом в Crawlee не ограничивается Cheerio и Playwright. Есть ещё PuppeteerCrawler, и я проверил, насколько далеко простирается тезис об «одинаковом интерфейсе» — на уровне классов и публичного API, но без полноценного live-краула.
Все три класса краулеров наследуются от одного и того же BasicCrawler. CheerioCrawler идёт через HttpCrawler; PlaywrightCrawler и PuppeteerCrawler оба используют общий BrowserCrawler. При анализе установленного пакета я обнаружил 24 общих публичных метода у всех трёх движков, включая операции очереди и хранилища, на которых и держится вся архитектура, — run, addRequests, pushData, getData, getDataset, exportData, getRequestQueue, useState, stop. У PuppeteerCrawler и PlaywrightCrawler набор публичных методов вообще идентичен. Единственные различия между движками находятся как раз на границе HTTP и браузера — там, где они и должны быть.
Но есть важная граница: я не запускал полноценный crawl через PuppeteerCrawler. Peer dependency puppeteer необязательна и в мой тестовый набор не входила, а её использование потребовало бы ещё одной загрузки браузера. Поэтому паритет Puppeteer здесь подтверждён структурно — одинаковый базовый класс, общие методы, одинаковая форма контекста обработчика — но не выполненным запуском. И даже когда API совпадает, поведение под капотом не полностью одинаковое: в документации Crawlee отмечено, что Playwright умеет автоматически ждать элементы, а Puppeteer требует явного ожидания. Это особенность движка, а не ошибка Crawlee, но она означает, что «одинаковый API» не равен «одинаковый код внутри любого обработчика».
Что я не тестировал
Ниже — то, что я сознательно оставил за скобками, чтобы мои выводы не казались шире, чем они есть.
- Масштаб. Всё запускалось на небольших фикстурах и коротких публичных обходах. Не было длинного прогона на 100–1000 страниц, поэтому я не могу судить об autoscaling или стабильности под реальной нагрузкой.
- Персистентность очереди и возобновление. Я ни разу не прерывал обход посередине, чтобы проверить, действительно ли
RequestQueueкорректно продолжает работу после сбоя. Для долгих задач это важная функция, но здесь она не проверялась. - Экспорт Dataset и KeyValueStore. Экспорт JSON/CSV я писал вручную в тестовом harness’е. Встроенную удобство
Dataset/KeyValueStore— одну из главных причин использовать фреймворк — я не тестировал. - Прокси и пул сессий. В Crawlee есть ротация прокси и fingerprinting. Я рассматриваю это строго как тему соответствия и эксплуатации, а не как «обход антибота», и специально не проводил стресс-тесты в эту сторону.
И ещё раз: все замеры времени — это один компьютер и один прогон. Они показывают форму различия между HTTP и браузером, но это не бенчмарк, и я бы не стал цитировать их как таковой.
Плюсы и минусы
Плюсы
- Единый API для HTTP- и browser-краулинга — переключение движка действительно сводится к смене класса, что я подтвердил переходом с 0 до полных данных и на локальной фикстуре, и на публичном сайте.
- Настоящий crawl-фреймворк:
RequestQueue,enqueueLinksс контролем глубины, повторные попытки иfailedRequestHandler, а не просто рендерер страниц. - Точное извлечение через HTTP (12/12 на статике, 3/3 абзаца статьи, 8/8 через JSON API), когда JavaScript не мешает.
- Браузерный путь получает контент, который HTTP-метод физически не видит, и умеет делать скриншоты.
- Apache-2.0, TypeScript, активно поддерживается.
Минусы
- Для браузерных краулеров нужен отдельный
npx playwright install chromium(~81,7 MiB), которыйnpm install crawleeне делает автоматически — это легко пропустить. - Рендеринг в браузере даёт реальную цену на каждую страницу (~5 с против долей секунды в моём одностраничном тесте).
- На обычном запуске по умолчанию создаётся папка
storage/. - Масштабирование, возобновление после сбоя и удобство встроенного экспорта Dataset в моих тестах не подтверждены.
- Функции прокси и fingerprinting нужно использовать строго в рамках правил сайта и закона — это ответственность, а не «фича для обхода ограничений».
Когда выбирать Crawlee, а когда — управляемый API
Crawlee — это инструмент в стиле «собери сам», и для многих команд это как раз правильный выбор. Он подходит, если вы хотите держать краулер в собственном Node-коде, смешивать HTTP и browser-обход в одном проекте без смены фреймворка и самостоятельно управлять очередью и хранилищем. Если вы готовы запускать и со временем масштабировать собственный браузерный флот, Crawlee даёт для этого чистый и хорошо спроектированный каркас.
Но есть и другой путь — вообще не заниматься всей этой инфраструктурой. Если вам не хочется обслуживать инстансы Chromium, ротацию прокси и антибот-логику, альтернативой становится управляемый API — и именно сюда вписывается наш собственный стек для разработчиков в Thunderbit. Для технических пользователей Thunderbit — это не Chrome-расширение, а AI scraping API, MCP server и CLI. Вы вызываете POST /distill, чтобы превратить страницу в чистый Markdown, готовый для LLM, или POST /extract со схемой JSON, чтобы получить структурированные данные назад; параметр renderMode может быть none, basic или full, так что вы сами решаете, когда нужен полноценный браузерный рендер. MCP server позволяет AI-агенту (Claude, Cursor и другим MCP-клиентам) выполнять скрапинг прямо в процессе задачи, а CLI работает из терминала или CI:
Попробовать Thunderbit для извлечения веб-данных
npx -y @thunderbit/thunderbit-cli distill "<url>" -f markdown > out.md
Ключевая разница для разработчиков такова: Crawlee отдаёт вам сырьё — отрендеренный HTML и распарсенные узлы, а весь пайплайн вы строите сами; управляемый API возвращает готовый структурированный JSON, соответствующий схеме, а рендеринг, CAPTCHA и антибот-защиту обрабатывает на своей стороне. Это разные задачи. Нужен максимальный контроль и вы не против операционных расходов — берите Crawlee. Нужны данные без собственного парка браузеров — берите управляемый API. Многие команды в итоге используют оба подхода: один для кастомных обходов, другой — для случаев «просто дайте мне структурированные данные». Разницу по стоимости можно посмотреть в ценах Thunderbit.
Вердикт
Стоит ли использовать Crawlee? Да — если вы разработчик на Node или TypeScript и хотите один фреймворк, который объединяет HTTP- и browser-краулинг с полноценной очередью обхода внутри. Обещание двух движков — главная причина выбрать его, и на моих фикстурах оно подтвердилось без проблем: тот же URL переходил от 0 к полным данным простой заменой класса, статическое извлечение было точным и быстрым, а обход по очереди и глубине работал так, как заявлено.
Но есть два важных момента. Заложите в бюджет скрытую загрузку браузера при первом использовании PlaywrightCrawler, и не считайте, что то, что я не тестировал — масштабирование, восстановление после падения, встроенный экспорт — работает так же хорошо, как проверенные мной части, пока не прогоните это на своей реальной нагрузке. Как основа для собственного краулера Crawlee — сильное и хорошо спроектированное решение. Как готовый полностью автономный конвейер данных — это отправная точка, а не конечный пункт.
Попробовать Thunderbit для извлечения веб-данных Get Started Free
Часто задаваемые вопросы
Crawlee бесплатный? Какая у него лицензия?
Да. Crawlee — open source под лицензией Apache-2.0 и устанавливается через npm (npm install crawlee). Версия, которую я тестировал, — 3.17.0. Для браузерных краулеров требуется отдельная загрузка Chromium через Playwright; это тоже бесплатно, но добавляет к установке около 81,7 MiB.
CheerioCrawler или PlaywrightCrawler — что выбрать?
Используйте CheerioCrawler, когда данные уже есть в сыром HTML или в лежащем под ним JSON API — он значительно быстрее и не запускает браузер. Используйте PlaywrightCrawler, когда контент рендерится JavaScript, что обычно видно по пустому результату в HTTP-режиме. В моих тестах HTTP-движок вернул 0 элементов на JS-странице, а браузерный — всё содержимое. Поскольку у них общий API, переход — это смена класса, а не переписывание кода.
Нужен ли Crawlee браузер для работы?
Только для браузерных краулеров. CheerioCrawler браузер вообще не требует. PlaywrightCrawler (и PuppeteerCrawler) нуждаются в бинарнике браузера — его нужно установить через npx playwright install chromium. Обратите внимание: один только npm install crawlee браузер не скачает, и это самая частая проблема при первом запуске.
Умеет ли Crawlee работать с пагинацией и многостраничными обходами?
Да, и это одна из главных причин выбрать его вместо отдельной browser-библиотеки. enqueueLinks переходит по ссылкам, включая селекторы пагинации вроде .next-page, RequestQueue дедуплицирует запросы и управляет обходом, а также доступны контроль глубины и лимит maxRequestsPerCrawl. В тесте обход внутри одного домена прошёл 11 страниц на глубинах 0–2, а ошибки запросов были переданы через failedRequestHandler.
Чем Crawlee отличается от managed scraping API?
Crawlee работает у вас: вы пишете и запускаете краулер сами и сами отвечаете за масштабирование, прокси и антибот-логику. Managed API, например endpoints Thunderbit distill/extract, возвращает чистый Markdown или структурированный JSON по схеме, а рендеринг и антибот-защита обрабатываются на сервере. Доступ возможен через API, MCP server и CLI. Выбирайте Crawlee, если вам нужен максимальный контроль над собственным пайплайном; выбирайте managed API, если не хотите сами запускать и масштабировать браузерную инфраструктуру.


