Если вы когда-либо пытались скрейпить веб-сайты через Node.js и получали 403 Forbidden после десятого запроса — вы не одиноки. Библиотека got-scraping в Node.js от Apify решает две главные проблемы: генерацию правдоподобных браузерных заголовков и нативную поддержку HTTP/2. В этом руководстве мы разберём, как интегрировать got-scraping с резидентными прокси, настроить ротацию IP и построить надёжную инфраструктуру для сбора данных.
Что такое got-scraping в Node.js и почему обычные запросы блокируются
Антибот-системы современных сайтов анализируют не только IP-адрес, но и сигнатуру HTTP-клиента. Когда вы отправляете запрос через got или axios без настроенных заголовков, сервер видит несоответствие: TLS-отпечаток говорит «это Node.js», а заголовки отсутствуют или идут в неправильном порядке. Результат — блокировка, часто с первого запроса.
Проблема усугубляется тем, что браузеры отправляют заголовки в строго определённом порядке. Согласно документации MDN, такие заголовки, как Accept, Accept-Language, Accept-Encoding и Sec-CH-UA, должны идти до Cookie и Referer. Обычные HTTP-клиенты не гарантируют порядок заголовков, что сразу выдаёт автоматизированный клиент.
Библиотека got-scraping — это расширение got, созданное специально для веб-скрейпинга. Она интегрирует пакет header-generator, который создаёт связные наборы заголовков, имитирующие реальные браузеры на конкретных операционных системах и устройствах. Кроме того, got-scraping поддерживает HTTP/2, что критически важно: многие антибот-системы проверяют версию протокола и ALPN-согласование.
Сравнение HTTP-клиентов для скрейпинга
| Возможность | got | axios | got-scraping |
|---|---|---|---|
| Генерация браузерных заголовков | Нет | Нет | Да (header-generator) |
| HTTP/2 | Через плагин | Нет | Нативно |
| Порядок заголовков как в браузере | Нет | Нет | Да |
| Поддержка proxyUrl (HTTP/2) | Ограниченная | Нет | Да |
| Retry hooks | Да | Через interceptors | Да (расширенные) |
Генератор заголовков got scraping: как это работает
Пакет header-generator — ядро got-scraping. Он не просто подставляет случайные значения, а создаёт связные наборы заголовков. Если вы указываете браузер Chrome 120 на Windows 11, генератор выдаст именно те заголовки, которые отправляет реальный Chrome 120 на Windows 11 — включая Sec-CH-UA, Sec-CH-UA-Platform, Accept-Language и правильный порядок.
Это критически важно, потому что антибот-системы, такие как Cloudflare и Akamai, проверяют связность набора. Если User-Agent говорит «Chrome на Windows», а Sec-CH-UA-Platform отсутствует или содержит «macOS» — запрос помечается как подозрительный. got scraping header generator решает эту проблему, создавая комбинации, которые проходят даже глубокие проверки связности.
Генератор поддерживает три категории параметров:
- browsers —
chrome,firefox,safari,edge - devices —
desktop,mobile - operatingSystems —
windows,macos,linux,android,ios
Каждый сгенерированный набор включает около 15–20 заголовков, что соответствует реальному браузерному запросу. Сравните это с типичным axios.get(), который отправляет 3–4 заголовка — этого достаточно для блокировки на любом защищённом сайте.
Идиоматичный API: got.extend, useHeaderGenerator и proxyUrl
got-scraping построен на паттерне got.extend() — идиоматичном способе создания кастомных инстансов got с предустановленными опциями. Вместо того чтобы передавать заголовки и прокси при каждом запросе, вы создаёте расширенный клиент один раз. Это особенно удобно для got-scraping proxy конфигураций, где параметры прокси и заголовков нужно держать в одном месте.
Функция useHeaderGenerator — это got-плагин, который подключает генератор заголовков к каждому запросу. Она принимает headerGeneratorOptions с теми же параметрами браузеров, устройств и ОС.
const { gotScraping } = require('got-scraping');
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome', 'edge'],
devices: ['desktop'],
operatingSystems: ['windows', 'macos'],
},
http2: true,
timeout: { request: 30000 },
retry: { limit: 3 },
});
const response = await client.get('https://example.com/data');
console.log(response.body);
Опция proxyUrl поддерживает как HTTP/1.1, так и HTTP/2 прокси. Это важно, потому что многие прокси-провайдеры работают только по HTTP/1.1, что может вызвать несоответствие между HTTP/2 запросом и HTTP/1.1 прокси-туннелем. got-scraping корректно обрабатывает оба сценария.
Маршрутизация через резидентные прокси ProxyHat
Когда заголовки и TLS-отпечаток выглядят правдоподобно, следующим фильтром становится IP-адрес. Дата-центр IP-адреса легко определяются по ASN: если запрос приходит из диапазона AWS или DigitalOcean, антибот-система немедленно повышает риск-скор, даже при идеальных заголовках.
Резидентные прокси используют IP-адреса реальных интернет-провайдеров, что делает их неотличимыми от обычных пользователей. ProxyHat предоставляет резидентные, мобильные и дата-центр прокси через единый шлюз gate.proxyhat.com. Для nodejs scraping proxy конфигураций это означает единый эндпоинт с гибким гео-таргетингом.
Для HTTP-подключения используйте порт 8080:
const proxyUrl = 'http://user-country-US:password@gate.proxyhat.com:8080';
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows'],
},
proxyUrl,
http2: true,
});
const res = await client.get('https://httpbin.org/ip');
console.log(res.body);
Для SOCKS5-подключения используйте порт 1080:
const socksProxyUrl = 'socks5://user-country-DE:password@gate.proxyhat.com:1080';
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['firefox'],
devices: ['desktop'],
operatingSystems: ['linux'],
},
proxyUrl: socksProxyUrl,
});
Geo-таргетинг и сессионные флаги передаются в имени пользователя. Например, user-country-US-session-abc123 направляет запрос через резидентный IP в США с закреплённой сессией. Это позволяет поддерживать cookies и состояние между запросами. Подробнее о доступных локациях — на странице локаций ProxyHat.
Рабочий пример: ротация резидентных прокси с retry hooks
В продакшене недостаточно одного прокси — нужна ротация. got-scraping предоставляет хуки beforeRequest, beforeRetry и afterResponse, которые позволяют динамически менять прокси между запросами и при ошибках. Это идиоматичный способ реализации got-scraping proxy ротации без внешних библиотек.
Следующий пример создаёт клиент got-scraping, который генерирует уникальный идентификатор сессии для каждого запроса, маршрутизирует через резидентные прокси ProxyHat и автоматически ретраит при 403 и 429.
const { gotScraping } = require('got-scraping');
const crypto = require('crypto');
const PROXYHAT_USER = 'your-username';
const PROXYHAT_PASS = 'your-password';
const GATEWAY = 'gate.proxyhat.com';
function makeProxyUrl(country = 'US') {
const session = crypto.randomBytes(6).toString('hex');
const username = `${PROXYHAT_USER}-country-${country}-session-${session}`;
return `http://${username}:${PROXYHAT_PASS}@${GATEWAY}:8080`;
}
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome', 'edge'],
devices: ['desktop'],
operatingSystems: ['windows', 'macos'],
},
http2: true,
timeout: { request: 30000 },
retry: {
limit: 4,
statusCodes: [403, 429, 500, 502, 503],
backoffLimit: 5000,
},
hooks: {
beforeRequest: [
(options) => {
options.proxyUrl = makeProxyUrl('US');
},
],
beforeRetry: [
(error, retryCount, options) => {
console.log(`Retry ${retryCount}: ${error.message}`);
options.proxyUrl = makeProxyUrl('US');
},
],
afterResponse: [
(response, retryWithMergedOptions) => {
if (response.statusCode === 403) {
console.log('403 — ротация прокси и ретрай');
return retryWithMergedOptions({
proxyUrl: makeProxyUrl('US'),
});
}
return response;
},
],
},
});
async function scrape(urls) {
const results = [];
for (const url of urls) {
try {
const res = await client.get(url);
results.push({ url, status: res.statusCode, body: res.body });
} catch (err) {
console.error(`Failed: ${url} — ${err.message}`);
}
}
return results;
}
const targets = [
'https://httpbin.org/ip',
'https://httpbin.org/headers',
'https://httpbin.org/user-agent',
];
scrape(targets).then(console.log);
Ключевые моменты этого примера:
- Уникальная сессия на запрос — каждый запрос получает свежий IP через
crypto.randomBytes - Retry с ротацией — при 403/429 меняется не только задержка, но и прокси
- afterResponse-хук — перехватывает 403 даже без исключения, позволяя ретрай с новым прокси
- backoffLimit: 5000 — максимальная задержка 5 секунд между ретраями
Продакшн-паттерны: конкурентность, cookie jars и Crawlee
Ограничение конкурентности с p-limit
При скрейпинге сотен URL важно ограничить параллельность, чтобы не перегружать целевой сервер и не исчерпать лимиты прокси. Пакет p-limit — стандартный способ контроля конкурентности в Node.js.
const pLimit = require('p-limit');
const limit = pLimit(10); // максимум 10 одновременных запросов
async function scrapeConcurrent(urls) {
const tasks = urls.map(url =>
limit(() => client.get(url).then(res => ({
url,
status: res.statusCode,
})))
);
return Promise.allSettled(tasks);
}
Лимит 10–20 одновременных соединений — хороший баланс между скоростью и блокировками. При использовании резидентных прокси ProxyHat можно увеличить конкурентность до 50–100, в зависимости от пула доступных IP. Но помните: агрессивная конкурентность повышает риск триггера антибот-систем, даже с резидентными IP.
Cookie jars для поддержания сессий
Некоторые сайты требуют cookies для прохождения антибот-проверок. got-scraping поддерживает tough-cookie через опцию cookieJar. Это особенно полезно при многошаговом скрейпинге: первый запрос получает cookies, последующие используют их автоматически.
const { CookieJar } = require('tough-cookie');
const jar = new CookieJar();
const sessionClient = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows'],
},
proxyUrl: makeProxyUrl('US'),
cookieJar: jar,
});
// Первый запрос — получает cookies
await sessionClient.get('https://example.com/');
// Второй — использует cookies из jar
await sessionClient.get('https://example.com/dashboard');
При использовании cookie jar важно закрепить сессию прокси через -session-abc123 в имени пользователя, чтобы cookies соответствовали одному IP. Если IP меняется между запросами, а cookies остаются — это может вызвать подозрение.
Масштабирование: переход на Crawlee и CheerioCrawler
Когда логика скрейпинга усложняется — очередь URL растёт до тысяч, нужны парсинг HTML, дедупликация и хранение результатов — стоит перейти на Crawlee, фреймворк от Apify, построенный поверх got-scraping. CheerioCrawler использует got-scraping под капотом и добавляет:
- Очередь запросов с дедупликацией
- Автоматический retry с экспоненциальной задержкой
- Управление cookies и сессиями
- Интеграцию с прокси через
ProxyConfiguration - Контроль конкурентности из коробки
const { CheerioCrawler, ProxyConfiguration } = require('crawlee');
const proxyConfiguration = new ProxyConfiguration({
proxyUrls: [
'http://user-country-US-session-s1:pass@gate.proxyhat.com:8080',
'http://user-country-US-session-s2:pass@gate.proxyhat.com:8080',
'http://user-country-US-session-s3:pass@gate.proxyhat.com:8080',
],
});
const crawler = new CheerioCrawler({
proxyConfiguration,
maxConcurrency: 10,
maxRequestRetries: 3,
requestHandler: async ({ $, request }) => {
const title = $('title').text();
console.log(`${request.url}: ${title}`);
},
});
await crawler.run([
'https://example.com/page1',
'https://example.com/page2',
]);
Crawlee автоматически ротирует прокси из ProxyConfiguration между запросами, что снимает необходимость ручного управления в хуках. Для больших проектов это значительно упрощает код и повышает надёжность.
Когда без headless-браузера не обойтись
got-scraping эффективен для сайтов, где контент приходит в HTML-ответе. Но если сайт рендерит контент через JavaScript (SPA на React/Vue), или использует продвинутые антибот-проверки (Cloudflare Turnstile, Akamai Bot Manager с canvas-фингерпринтингом), HTTP-клиент не справится.
В таких случаях переходите на Playwright или Puppeteer через Crawlee's PlaywrightCrawler. Но помните: headless-браузер потребляет в 10–20 раз больше ресурсов — один инстанс Chrome требует около 150–300 МБ RAM. Для контейнеризации используйте Docker с образами на базе Debian, а для горизонтального масштабирования — Kubernetes или аналогичные оркестраторы. Типичная конфигурация: 4–8 браузеров на ядро CPU, 512 МБ RAM на инстанс.
Этика и правовые аспекты
Прежде чем начать скрейпинг, учитывайте правовые рамки. В США сбор публичных данных обычно не нарушает Computer Fraud and Abuse Act (CFAA) после прецедента hiQ Labs v. LinkedIn (2022), но Terms of Service конкретного сайта могут запрещать автоматизированный доступ. В ЕС на сбор персональных данных распространяется GDPR, даже если данные получены из публичного источника.
Практические принципы:
- Собирайте только публичные данные — не пытайтесь обходить аутентификацию или paywall
- Уважайте
robots.txt— это не просто рекомендация, а сигнал добросовестности - Соблюдайте рейт-лимиты — не отправляйте больше запросов, чем необходимо
- Предпочитайте официальные API, когда они доступны
- Не храните персональные данные дольше, чем необходимо для вашей задачи
Подробнее о вариантах использования прокси — на странице веб-скрейпинга и SERP-трекинга. Тарифы ProxyHat — на странице цен. Документация по подключению — на docs.proxyhat.com.
Ключевые выводы
- Заголовки решают половину проблемы — got-scraping с header-generator создаёт связные наборы заголовков, неотличимые от реальных браузеров
- Резидентные прокси закрывают вторую половину — даже с идеальными заголовками дата-центр IP выдаёт автоматизацию по ASN
- Ротация сессий — ключ к масштабированию — уникальная сессия на запрос через
-session-xxxв имени пользователя ProxyHat- Retry hooks — не опция, а необходимость — перехват 403/429 с автоматической сменой прокси повышает success rate до 95%+
- Ограничивайте конкурентность — p-limit с 10–20 одновременными запросами балансирует скорость и блокировки
- Масштабируйте через Crawlee — при росте очереди URL переход на CheerioCrawler добавляет очередь, дедупликацию и управление сессиями






