Jeśli scrapujesz w Node.js od dłuższego czasu, pewnie spotkałeś się z sytuacją: żądanie got lub axios działa lokalnie, a na produkcji dostaje 403 Forbidden albo 429 Too Many Requests po kilkudziesięciu odpytaniach. Biblioteka got-scraping w Node.js powstała właśnie po to, aby rozwiązać ten problem — to rozszerzenie got z wbudowanym generatorem nagłówków przeglądarki, obsługą HTTP/2 i prostą konfiguracją proxy. W tym przewodniku pokazujemy, jak zintegrować ją z residential proxy ProxyHat i zbudować pipeline scrapingu, który działa na dużą skalę.
Zanim jednak przejdziemy do kodu, ważna uwaga prawna: ten artykuł dotyczy wyłącznie danych publicznie dostępnych. Scraping może naruszać Computer Fraud and Abuse Act (CFAA) oraz RODO/GDPR, jeśli dotyczy danych osobowych. Zawsze sprawdzaj robots.txt, regulaminy serwisów i preferuj oficjalne API, gdy jest dostępne.
Dlaczego zwykłe żądania got/axios zostają zablokowane
Systemy anty-bot nie opierają się już tylko na sprawdzaniu pojedynczych nagłówków. Nowoczesne rozwiązania jak Cloudflare, Akamai czy PerimeterX analizują cały zestaw nagłówków, ich kolejność, spójność oraz sygnaturę TLS. Dlatego zwykłe żądanie got z nagłówkiem User-Agent: Mozilla/5.0... łatwo wykryć — brakuje mu nagłówków sec-ch-ua, accept-language, sec-fetch-dest, a kolejność nagłówków różni się od tej, którą wysyła prawdziwa przeglądarka.
Ponadto biblioteki HTTP w Node.js domyślnie używają TLS opartego na OpenSSL, którego sygnatura (JA3/JA4) różni się od przeglądarek Chrome czy Firefox. Nawet jeśli nagłówki wyglądają poprawnie, fingerprint TLS zdradza, że żądanie pochodzi z aplikacji, a nie z przeglądarki. got-scraping adresuje pierwszy problem — spójne nagłówki — a residential proxy adresuje drugi: realny adres IP z ISP.
Dokumentacja MDN o nagłówkach HTTP dobrze opisuje, jak przeglądarki konstruują żądania. Zrozumienie tego mechanizmu to pierwszy krok do unikania blokad.
Kluczowe sygnały, które analizują systemy anty-bot
- Kolejność nagłówków — przeglądarki mają powtarzalny porządek; biblioteki HTTP nie zawsze.
- Nagłówki sec-ch-ua — Client Hints ujawniające wersję przeglądarki i platformę.
- accept-language — musi pasować do geo IP i nagłówków sec-ch-ua.
- Fingerprint TLS (JA3/JA4) — sygnatura handshake TLS różni się między OpenSSL a przeglądarkami.
- Adres IP — datacenter IP (AWS, DigitalOcean) są na wielu listach blokad; residential IP nie.
Czym jest got-scraping w Node.js i jak działa header generator
got-scraping to pakiet npm od Apify, zbudowany na bazie got v11. Dodaje dwie kluczowe funkcje dla scrapingu: useHeaderGenerator — middleware, który dla każdego żądania generuje spójny zestaw nagłówków przeglądarki — oraz obsługę proxy HTTP/2. Kod źródłowy dostępny jest na GitHubie Apify.
got scraping header generator korzysta z biblioteki header-generator, która utrzymuje bazy danych nagłówków dla Chrome, Firefox i Safari w różnych wersjach, systemach operacyjnych i urządzeniach. Zamiast ręcznie ustawiać User-Agent, przekazujesz opcje takie jak browsers: ['chrome'], devices: ['desktop'], operatingSystems: ['windows', 'macos'], a generator dobiera pasujące nagłówki — w odpowiedniej kolejności.
Dlaczego to ma znaczenie dla użytkowników proxy
Nagłówki muszą być spójne z adresem IP. Jeśli wysyłasz żądanie z residential IP w Niemczech, ale accept-language to en-US, system anty-bot to zauważy. got-scraping z header generatorem i residential proxy ProxyHat z geo-targetingiem tworzy spójną tożsamość: nagłówki przeglądarki + język + IP z tego samego kraju.
Idiomatyczne API got-scraping: got.extend, useHeaderGenerator, proxyUrl
got-scraping jest zaprojektowane jako rozszerzenie got, więc używa tych samych wzorców co biblioteka bazowa. Zamiast pisać hacky middleware, korzystasz z got.extend(), aby utworzyć instancję z prekonfigurowanymi opcjami. To idiomatyczne podejście got — opcje są merge'owane na poziomie instancji i pojedynczego żądania.
Podstawowy przykład z useHeaderGenerator
import { gotScraping } from 'got-scraping';
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows'],
},
});
const response = await client('https://example.com', {
headerGeneratorOptions: {
locales: ['de-DE', 'de'], // nadpisz dla żądania do Niemiec
},
});
console.log(response.statusCode);
Zauważ, że headerGeneratorOptions można ustawić zarówno na poziomie instancji (w got.extend), jak i na poziomie pojedynczego żądania. To idiomatyczne podejście got — opcje są merge'owane.
Opcja proxyUrl dla HTTP/1 i HTTP/2 proxy
got-scraping obsługuje proxyUrl w formacie standardowym: http://user:pass@host:port lub socks5://user:pass@host:port. Dla proxy HTTP/2 got-scraping używa natywnego klienta HTTP/2, co jest istotne dla stron, które wymagają HTTP/2 — niektóre CDN-y odrzucają żądania HTTP/1.1.
Integracja residential proxy ProxyHat z got-scraping
Gdy nagłówki i TLS wyglądają poprawnie, ostatnim sygnałem jest adres IP. Residential proxy to adresy IP przypisane do realnych ISP — wyglądają jak ruch zwykłego użytkownika, a nie serwera w chmurze. ProxyHat oferuje residential, mobile i datacenter proxy z geo-targetingiem na poziomie kraju i miasta.
| Typ proxy | Poziom wykrywalności | Średnia latencja | Najlepsze zastosowanie |
|---|---|---|---|
| Datacenter | Wysoki — IP na listach blokad | ~50ms | API bez weryfikacji IP, testowanie |
| Residential | Niski — wygląda jak zwykły ISP | ~200–500ms | Scraping stron, SERP, e-commerce |
| Mobile | Bardzo niski — IP operatorów komórkowych | ~300–800ms | Trudne cele, social media |
Dla got-scraping w Node.js, residential proxy ProxyHat to naturalny wybór. Konfiguracja sprowadza się do ustawienia proxyUrl z odpowiednim username zawierającym flagi geo i sesji.
Format połączenia ProxyHat
// HTTP proxy — domyślny port 8080
const proxyUrl = 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080';
// HTTP proxy z sesją sticky i geo na poziomie miasta
const proxyUrlDE = 'http://user-country-DE-city-berlin-session-abc123:PASSWORD@gate.proxyhat.com:8080';
// SOCKS5 proxy — port 1080
const socks5Url = 'socks5://user-country-US-session-abc123:PASSWORD@gate.proxyhat.com:1080';
Flagi w username pozwalają kontrolować rotację i geo-targeting: country-XX wybiera kraj, city-xxx miasto, a session-xxx utrzymuje ten sam IP dla kolejnych żądań w ramach sesji. Pełną listę lokalizacji znajdziesz na stronie lokalizacji ProxyHat.
Przykład Node.js: rotacja sesji residential z hookami retry
Poniższy przykład pokazuje pełny, uruchomieniowy pipeline: generator nagłówków, rotacja sesji per żądanie, hooki retry i obsługa błędów. To wzorzec, który możesz skopiować do projektu.
import { gotScraping } from 'got-scraping';
import { randomUUID } from 'crypto';
import pLimit from 'p-limit';
const PROXYHAT_GATEWAY = 'gate.proxyhat.com';
const PROXYHAT_PORT = 8080;
const PROXYHAT_USER = 'user';
const PROXYHAT_PASS = 'twoje_haslo';
function buildProxyUrl(country = 'US', session = randomUUID()) {
const username = `${PROXYHAT_USER}-country-${country}-session-${session}`;
return `http://${username}:${PROXYHAT_PASS}@${PROXYHAT_GATEWAY}:${PROXYHAT_PORT}`;
}
const client = gotScraping.extend({
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows', 'macos'],
},
retry: {
limit: 3,
statusCodes: [403, 429, 500, 502, 503],
},
hooks: {
beforeRequest: [
(options) => {
// Rotacja sesji per żądanie — nowy IP
options.proxyUrl = buildProxyUrl('US');
},
],
beforeRetry: [
(options, error, retryCount) => {
console.log(`Retry ${retryCount} po ${error.code} — nowa sesja proxy`);
options.proxyUrl = buildProxyUrl('US');
},
],
},
timeout: { request: 30000 },
});
async function scrape(urls) {
const limit = pLimit(10); // max 10 równoległych żądań
const results = await Promise.allSettled(
urls.map((url) => limit(() => client(url).then((r) => r.body)))
);
return results;
}
const urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
];
const results = await scrape(urls);
results.forEach((r, i) => {
if (r.status === 'fulfilled') {
console.log(`URL ${i}: ${r.value.length} bajtów`);
} else {
console.error(`URL ${i}: ${r.reason.message}`);
}
});
Kluczowe elementy tego przykładu:
- beforeRequest hook — ustawia nowy
proxyUrlz unikalną sesją dla każdego żądania, co wymusza rotację IP. - beforeRetry hook — przy ponowieniu generuje nową sesję, aby ominąć IP, które zostało zablokowane.
- p-limit — ogranicza współbieżność do 10 żądań, zapobiegając przeciążeniu proxy i celu.
- retry — konfiguracja
gotz kodami statusów typowymi dla blokad anty-bot.
Wzorce produkcyjne: retry, afterResponse, cookie jars, Crawlee
Cookie jar dla sesji logowania
Jeśli strona wymaga sesji (koszyk, logowanie), użyj tough-cookie z got. got-scraping obsługuje cookie jar natywnie:
import { gotScraping } from 'got-scraping';
import { CookieJar } from 'tough-cookie';
const cookieJar = new CookieJar();
const client = gotScraping.extend({
cookieJar,
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['macos'],
},
hooks: {
beforeRequest: [
(options) => {
options.proxyUrl = buildProxyUrl('US', 'persistent-session-001');
},
],
},
});
// Pierwsze żądanie — strona ustawia cookies
await client('https://example.com/login');
// Drugie żądanie — cookies są wysyłane automatycznie
const dashboard = await client('https://example.com/dashboard');
console.log(dashboard.body);
W tym przypadku używamy sticky session (session-persistent-session-001), aby utrzymać ten sam IP przez całą sesję logowania. Rotacja IP w trakcie sesji może wywołać flagę bezpieczeństwa.
afterResponse hook do logowania i metryk
const client = gotScraping.extend({
hooks: {
afterResponse: [
(response, retryWithMergedOptions) => {
const url = response.url;
const status = response.statusCode;
const elapsed = response.timings?.phases?.total ?? 0;
console.log(`${status} ${url} — ${elapsed}ms`);
// Jeśli 403, spróbuj z nowym proxy i nagłówkami
if (status === 403) {
return retryWithMergedOptions({
proxyUrl: buildProxyUrl('US'),
headerGeneratorOptions: {
browsers: ['firefox'],
devices: ['desktop'],
operatingSystems: ['windows'],
},
});
}
return response;
},
],
},
});
Skalowanie z Crawlee CheerioCrawler
Dla większych projektów rozważ Crawlee — framework Apify, który integruje got-scraping z kolejką żądań, routerem i automatycznym retry. CheerioCrawler używa got-scraping pod spodem:
import { CheerioCrawler } from 'crawlee';
const crawler = new CheerioCrawler({
requestHandler: async ({ $, request }) => {
const title = $('title').text();
console.log(`${request.url}: ${title}`);
},
proxyConfiguration: {
proxyUrls: [
'http://user-country-US-session-s1:pass@gate.proxyhat.com:8080',
],
},
maxConcurrency: 20,
maxRequestRetries: 3,
useHeaderGenerator: true,
headerGeneratorOptions: {
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows', 'macos'],
},
});
await crawler.run(['https://example.com']);
Crawlee automatycznie zarządza kolejką, retry, współbieżnością i proxy rotation. To najbardziej produkcyjne podejście do scrapingu w Node.js. Więcej o przypadkach użycia przeczytasz na stronie web scraping ProxyHat.
Kiedy headless browser jest niezbędny i etyka scrapingu
got-scraping rozwiązuje problem nagłówków i proxy, ale nie wykonuje JavaScript. Strony, które renderują treść przez SPA (React, Vue) lub używają zaawansowanych skryptów anty-bot (Arkose Labs, reCAPTCHA v3), mogą wymagać headless browser — Playwright lub Puppeteer. Crawlee oferuje PlaywrightCrawler jako następny krok, gdy CheerioCrawler nie wystarcza.
Koszt jest jednak realny: headless Chrome zużywa ~150–300 MB RAM na instancję i jest 10–50x wolniejszy niż żądanie HTTP. Dlatego warto zacząć od got-scraping i przejść na browser tylko gdy konieczne.
Etyka i legalność
- Publiczne dane tylko — nie scrapuj treści za loginem bez zgody.
- Honoruj robots.txt — sprawdź
/robots.txti respektuj dyrektywy. - Stosuj rate limiting — nie wysyłaj więcej niż 1 żądania/sekundę do małych serwisów.
- Preferuj API — wiele serwisów oferuje oficjalne API z dokumentacją.
- RODO/GDPR — dane osobowe podlegają regulacji; zapoznaj się z przewodnikiem GDPR.eu.
Więcej o strategiach scrapingu SERP znajdziesz na stronie SERP tracking, a cennik residential proxy na stronie cennika ProxyHat. Dokumentację techniczną ProxyHat znajdziesz na docs.proxyhat.com.
Najważniejsze wnioski
got-scraping w Node.js rozwiązuje problem nagłówków przeglądarki i obsługi proxy HTTP/2, a residential proxy ProxyHat rozwiązuje problem adresu IP. Razem tworzą pipeline scrapingu, który jest trudny do wykrycia i łatwy do skalowania.
- Header generator — używaj
headerGeneratorOptionswgot.extendzamiast ręcznych nagłówków. - Residential proxy — ustaw
proxyUrlzgate.proxyhat.com:8080i flagami geo/sesji w username. - Rotacja sesji — generuj unikalne
session-xxxw hookubeforeRequestdla per-request IP rotation. - Retry — konfiguruj
retry.statusCodesz 403, 429 i hookbeforeRetryz nowym proxy. - Współbieżność — używaj
p-limitlubmaxConcurrencyw Crawlee, aby uniknąć przeciążenia. - Skalowanie — dla dużych projektów przejdź na Crawlee
CheerioCrawler.






