Node.js
Официальный клиент Node.js для платформы Crawlbase. Один пакет, все API, полная поддержка async/await с корректным отклонением Promise при ошибках транспорта и структурированными объектами ответа при успехе.
Как устроен SDK
Node SDK - это тонкая обёртка над тем же HTTP API, описанным в API Reference. Каждый параметр Crawling API, который вы добавили бы как query string в сыром HTTP-вызове, доступен в SDK как ключ объекта options - имена, значения по умолчанию и поведение совпадают один к одному. SDK не добавляет ни одного параметра и не скрывает ни одного.
Что вы получаете, используя его вместо fetch / axios напрямую:
- URL-кодирование, валидация параметров и разбор ответов работают из коробки - код читается как продуктовый код, а не как HTTP-обвязка.
- Поддерживаются и ESM (
import { CrawlingAPI } from 'crawlbase'), и CommonJS (const { CrawlingAPI } = require('crawlbase')). - Один клиентский класс на каждый Crawlbase API, все с одинаковой формой конструктора и вызовов.
- Разумные значения по умолчанию (90-секундный таймаут, автоматический парсинг JSON для ответов
format=json, декодирование UTF-8) — то, что большинство команд настраивают вручную при первой интеграции.
SDK имеет открытый исходный код, лицензию MIT и принимает PR от сообщества на github.com/crawlbase/crawlbase-node.
Установка
Последняя версия в npm. Работает с Node.js 16+ во всех основных пакетных менеджерах.
npm install crawlbase
# Or via pnpm / yarn / bun
pnpm add crawlbase
yarn add crawlbase
bun add crawlbaseИсходный код на GitHub. Issues и PR приветствуются.
Аутентификация
Каждый Crawlbase API использует одну и ту же модель токенов. На одном аккаунте сосуществуют два типа токенов:
- Normal Token (TCP) - для статического HTML, JSON-эндпоинтов, всего, что не требует браузера. Быстрее и дешевле.
- JavaScript Token
- для SPA, лениво загружаемых лент, всего, что скрывает контент за клиентским рендерингом. Требуется для использования
page_wait,ajax_wait,scrollиcss_click_selector.
В продакшене используйте переменные окружения. SDK сам не читает env-переменные - это сделано намеренно, чтобы вы контролировали, откуда берутся учётные данные, - но идиоматичный паттерн такой:
import { CrawlingAPI } from 'crawlbase';
// Pick the right token at instantiation; the SDK doesn't switch
// tokens per-call, so keep two clients if you alternate.
const api = new CrawlingAPI({ token: process.env.CRAWLBASE_TOKEN });
const js = new CrawlingAPI({ token: process.env.CRAWLBASE_JS_TOKEN });
await api.get('https://github.com/anthropic');
await js.get('https://feed.example.com', { page_wait: 2000 });Полная модель токенов и их расположение в дашборде — на странице Authentication.
Быстрый старт
Три строки от импорта до получения HTML. Работают и ESM, и CommonJS:
// ESM
import { CrawlingAPI } from 'crawlbase';
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
const res = await api.get('https://github.com/anthropic');
if (res.statusCode === 200) {
console.log(res.body);
}
// CommonJS - same shape
// const { CrawlingAPI } = require('crawlbase');Ветвите по response.statusCode (HTTP-статус SDK к Crawlbase) и response.headers.pc_status (вердикт Crawlbase - см. Ошибки ниже), принимая решение о повторной попытке. Передайте { format: 'json' }, чтобы получить JSON-конверт вместо сырого содержимого страницы.
Все API в одном пакете
У каждого Crawlbase API есть соответствующий клиентский класс. Тот же конструктор, те же глаголы get / post.
import {
CrawlingAPI, // general-purpose page fetch
ScraperAPI, // parsed JSON for supported sites
LeadsAPI, // domain-scoped email extraction (legacy)
ScreenshotsAPI, // screenshots of any URL
} from 'crawlbase';
const token = { token: 'YOUR_TOKEN' };
const crawl = new CrawlingAPI(token);
const scraper = new ScraperAPI(token);
const leads = new LeadsAPI(token);
const shots = new ScreenshotsAPI(token);
// Push high-volume async jobs to the Enterprise Crawler via the
// Crawling API: api.get(url, { async: true, callback: '...',
// crawler: 'YourCrawler' }). See /docs/crawler for the queue
// workflow.Распространённые паттерны
JavaScript-рендеринг
Для SPA, лениво подгружаемых лент и страниц, где исходный HTML пуст, создавайте экземпляр с JavaScript token и передавайте любую комбинацию page_wait, ajax_wait, scroll и css_click_selector. Порядок, о котором стоит подумать: сначала фиксированное ожидание, затем network-idle, затем скролл для ленивой подгрузки, затем клик по любому блокирующему UI-элементу.
const api = new CrawlingAPI({ token: 'YOUR_JS_TOKEN' });
const res = await api.get('https://spa.example.com', {
page_wait: 2000,
ajax_wait: true,
scroll: true,
});Использование встроенного скрапера
На поддерживаемых сайтах можно полностью пропустить парсер. Передайте scraper: 'NAME', и тело ответа станет JSON-строкой со структурированными полями, описанными на странице соответствующего скрапера.
import { ScraperAPI } from 'crawlbase';
const api = new ScraperAPI({ token: 'YOUR_TOKEN' });
const res = await api.get(
'https://www.amazon.com/dp/1098145356',
{ scraper: 'amazon-product-details' }
);
const data = JSON.parse(res.body);
console.log(data.name, data.price);Гео-маршрутизация
Передайте country: 'ISO', чтобы направить запрос через выходные узлы выбранной страны. Используйте всякий раз, когда целевой сайт отдаёт локализованный контент на основе IP.
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
// Hit the German Amazon catalog from a German residential IP
const res = await api.get(
'https://www.amazon.com/dp/1098145356',
{ country: 'DE' }
);Повторные попытки с backoff
Рекомендуемая форма ретраев: экспоненциальный backoff с лимитом 3–5 попыток, повторять только при временных ошибках (5xx или пустое тело), не повторять при 4xx.
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function crawl(url, attempts = 5) {
for (let i = 0; i < attempts; i++) {
const res = await api.get(url);
if (res.statusCode === 200 && Number(res.headers.pc_status) === 200) {
return res;
}
if (res.statusCode >= 400 && res.statusCode < 500) {
throw new Error(`client error ${res.statusCode}: ${url}`);
}
await sleep(Math.random() * (2 ** i) * 1000);
}
throw new Error(`Failed: ${url}`);
}Асинхронные краулы и вебхуки
Режим fire-and-forget. Вызов SDK сразу возвращает rid; Crawlbase отправляет POST с результатом на ваш callback URL, как только страница готова. Удобно для пакетных задач и медленных целей.
const api = new CrawlingAPI({ token: 'YOUR_TOKEN' });
const res = await api.get('https://example.com', {
async: true,
callback: 'https://your-app.com/webhook',
});
const rid = res.rid; // correlate the eventual webhook delivery
// Your Express / Fastify / Hono webhook receives a POST with:
// { rid, url, original_status, pc_status, body }Для очень больших объёмов (миллионы URL) используйте Enterprise Crawler, который располагается перед этим же асинхронным пайплайном с ретраями, управлением скоростью и доставкой результатов.
Sticky-сессии
Некоторым сценариям нужен один и тот же резидентный IP в нескольких вызовах - оформление заказа, постраничный поиск, авторизованная сессия. Передайте cookies_session со стабильным идентификатором, и Crawlbase будет переиспользовать тот же exit-нод около 30 минут.
const api = new CrawlingAPI({ token: 'YOUR_JS_TOKEN' });
const session = `checkout-${userId}`;
await api.get('https://shop.example.com/cart', { cookies_session: session });
await api.get('https://shop.example.com/checkout', { cookies_session: session });
await api.get('https://shop.example.com/confirm', { cookies_session: session });Ошибки и повторные попытки
Платформа Crawlbase возвращает два кода состояния в каждом ответе: собственный response.statusCode SDK (HTTP-статус запроса к самому Crawlbase) и заголовок ответа pc_status (вердикт Crawlbase по целевому ресурсу - полный список см. в таблице ошибок Crawling API). Node SDK предоставляет заголовки ответа как обычный объект в response.headers, поэтому вердикт читается как response.headers.pc_status. Всегда ветвите по нему, принимая решение о повторной попытке: целевой ресурс может вернуть 200 с пустым телом, и тогда response.statusCode будет 200, а response.headers.pc_status - 520.
const res = await api.get(url);
const pc = Number(res.headers.pc_status);
if (pc === 200) {
use(res.body);
} else if (pc === 520 || pc === 525) {
// 520 = empty body, 525 = anti-bot couldn't be solved.
// Switch to JS token and retry.
await retryWithJsToken(url);
} else if ([521, 522, 523].includes(pc)) {
// Target unreachable or timed out. Retry with backoff.
schedule_retry(url);
} else {
logger.error('crawl failed', { url, pc_status: pc });
}Все повторные попытки к платформе бесплатны - в квоту засчитываются только успешные ответы (pc_status: 200). Это делает агрессивный backoff дешёвым; единственная реальная цена повторов - дополнительная задержка.
Производительность и лучшие практики
- Переиспользуйте один клиент на токен. Конструктор недорогой, но каждый экземпляр открывает свой пул соединений. Создайте его один раз на уровне модуля и используйте во всех вызовах.
- Используйте самый дешёвый токен, который работает. Не используйте JavaScript token «на всякий случай» по умолчанию - запросы с Normal token быстрее и потребляют меньше параллелизма. Переходите на JS, только когда ответ Normal пуст или заблокирован антиботом.
- Предпочитайте
ajax_waitвместоpage_wait. Фиксированные задержки расходуют конкурентность на каждом запросе, даже на быстрых. - Для пакетных задач: async + вебхук или отправка в Enterprise Crawler. Синхронный режим — правильный выбор по умолчанию для разовых и интерактивных сценариев; для устойчиво высокого объёма переключайтесь на async, чтобы слот конкурентности освобождался сразу после постановки запроса в очередь.
- Следите за заголовком ответа
remaining. Он содержит число оставшихся у вас слотов параллелизма - здоровый клиент проактивно сбавляет темп, прежде чем упереться в лимит.
Справочник методов
У всех клиентских классов одна и та же поверхность. Конструктор принимает единственный объект опций; глаголы зеркалят соответствующие HTTP-методы. Каждый метод возвращает Promise.
timeout в миллисекундах (по умолчанию 90000).options сопоставляет любой параметр Crawling API с его значением.data - это body: передайте объект для form-encoded, строку для raw.Форма ответа (объект, все свойства присутствуют, даже если пустые):
format=json / scraper=). По умолчанию декодируется в UTF-8.response.headers.pc_status- вердикт Crawlbase по целевому ресурсу (ветвите по нему для решений о повторной попытке).response.headers.original_status- HTTP-статус, который целевой сайт вернул Crawlbase.response.headers.rid- Request ID (когда вызов содержалasync: trueилиstore: true).