Se hai provato a fare got-scraping in Node.js con il solo modulo got o axios, probabilmente hai visto risposte 403, sfide CAPTCHA o TLS fingerprinting che bloccano le tue richieste. La causa raramente è un singolo header mancante: è la coerenza dell'intera firma del client, dall'ordine degli header al fingerprint TLS, fino all'indirizzo IP di origine. got-scraping, il client HTTP sviluppato da Apify sopra got, affronta esattamente questo problema generando set di header coerenti per browser reali e supportando HTTP/2 nativo.
In questa guida vedremo come usare got-scraping in Node.js con un got-scraping proxy residenziale, integrando la rotazione IP come middleware idiomatiko e coprendo i pattern di produzione: retry hooks, concorrenza limitata, cookie jar e passaggio a Crawlee quando serve un parser.
Nota legale. Raccolta solo di dati pubblici. Verifica i termini di servizio del sito, onora robots.txt e i limiti di frequenza, e considera il GDPR per dati personali. Preferisci sempre API ufficiali quando disponibili. Questo articolo è a scopo educativo e non costituisce consulenza legale.
Cos'è got-scraping in Node.js e perché esiste
got-scraping è un wrapper attorno a got, il popolare client HTTP per Node.js, pensato specificamente per lo scraping. Il suo vantaggio principale è l'integrazione di header-generator, una libreria che produce set di header coerenti con browser reali (Chrome, Firefox, Safari) su sistemi operativi e dispositivi realistici. Inoltre, supporta HTTP/2 out-of-the-box, riducendo la latenza e rendendo il fingerprint TLS più simile a quello di un browser moderno.
Il problema che risolve è concreto: i server anti-bot come Akamai, Cloudflare e Datadome non guardano solo il valore di User-Agent. Confrontano l'intero set di header, l'ordine in cui appaiono, i valori sec-ch-ua, accept-language, e il fingerprint TLS (JA3/JA4). Un client Node.js con un User-Agent Chrome ma header accept-encoding mancanti, o con un ordine anomalo, viene identificato come bot in millisecondi.
Perché got o axios non bastano
Con got puro devi costruire manualmente ogni header e mantenerli coerenti. Se aggiorni il User-Agent a Chrome 120, devi aggiornare anche sec-ch-ua, sec-ch-ua-platform e l'ordine. È fragile. got-scraping automatizza questo: genera un set completo e coerente a partire da un profilo browser, così ogni richiesta sembra provenire da un browser reale.
La superficie idiomatika: got.extend, useHeaderGenerator e proxyUrl
got-scraping espone una API idiomatika basata su got.extend(), il pattern standard di got per creare istanze personalizzate con opzioni predefinite. L'estensione avviene tramite middleware di hook, non con hack.
useHeaderGenerator e headerGeneratorOptions
Il middleware useHeaderGenerator inietta gli header generati in ogni richiesta. Le opzioni chiave sono browsers, devices e operatingSystems, che controllano il profilo del browser simulato.
import { gotScraping } from 'got-scraping';
import { useHeaderGenerator } from 'got-scraping';
import { HeaderGenerator } from 'header-generator';
const headerGenerator = new HeaderGenerator({
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows', 'macos'],
locales: ['en-US', 'en'],
});
const client = gotScraping.extend({
http2: true,
hooks: {
beforeRequest: [useHeaderGenerator(headerGenerator)],
},
});
Ogni richiesta riceve un set di header coerente: user-agent, sec-ch-ua, sec-ch-ua-platform, accept, accept-language, accept-encoding e altri, nell'ordine atteso dal browser scelto. Questo risolve il problema del got scraping header generator che molti sviluppatori cercano di reinventare manualmente.
L'opzione proxyUrl per HTTP/1 e HTTP/2
got-scraping accetta proxyUrl come opzione per-request o come default nell'estensione. Supporta sia proxy HTTP/1 che HTTP/2, e SOCKS5 con il prefisso socks5://. Questo rende l'integrazione di un nodejs scraping proxy una riga di configurazione.
const res = await client('https://example.com', {
proxyUrl: 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080',
});
console.log(res.statusCode);
Routing tramite proxy residenziali su gate.proxyhat.com:8080
Una volta che header e TLS sembrano reali, il punto debole rimane l'IP. Un datacenter IP è facilmente identificabile come hosting (AWS, DigitalOcean, OVH). I proxy residenziali usano IP assegnati a ISP reali, quindi il traffico risulta provenire da un utente domestico. Questo è il motivo per cui un got-scraping proxy residenziale è spesso la differenza tra successo e blocchi.
Con ProxyHat, il gateway HTTP è gate.proxyhat.com:8080. La geo-targeting e la sessione vanno nel username, non nella query string:
user-country-US— IP statunitensiuser-country-DE-city-berlin— IP di Berlinouser-session-abc123— sessione sticky per mantenere lo stesso IP
Per SOCKS5, la porta è 1080:
const res = await client('https://example.com', {
proxyUrl: 'socks5://user-country-US-session-abc123:pass@gate.proxyhat.com:1080',
});
Perché le sessioni sticky importano
Molti siti mantengono stato in cookie e token CSRF legati all'IP. Se ruoti IP a ogni richiesta, perdi la sessione e scateni sfide anti-bot. Con user-session-abc123 ProxyHat mantiene lo stesso IP residenziale per una finestra configurabile, permettendo login, navigazione multi-pagina e carrelli e-commerce senza perdere lo stato.
Esempio Node.js con rotazione e retry hooks
Vediamo un esempio completo: rotazione di sessioni residenziali con retry automatico su 403/429, usando un middleware ProxyHat che genera username per-request.
import { gotScraping } from 'got-scraping';
import { useHeaderGenerator } from 'got-scraping';
import { HeaderGenerator } from 'header-generator';
import { randomBytes } from 'crypto';
const PROXYHAT_USER = process.env.PROXYHAT_USER;
const PROXYHAT_PASS = process.env.PROXYHAT_PASS;
const GATE = 'gate.proxyhat.com';
const headerGenerator = new HeaderGenerator({
browsers: ['chrome'],
devices: ['desktop'],
operatingSystems: ['windows'],
locales: ['en-US', 'en'],
});
function proxyUrl(country = 'US', session = null) {
const sid = session ?? randomBytes(6).toString('hex');
const user = `user-country-${country}-session-${sid}`;
return `http://${user}:${PROXYHAT_PASS}@${GATE}:8080`;
}
const client = gotScraping.extend({
http2: true,
timeout: { request: 20000 },
retry: { limit: 3, statusCodes: [403, 429, 500, 502, 503] },
hooks: {
beforeRequest: [
useHeaderGenerator(headerGenerator),
(options) => {
// rotazione per-request: nuova sessione se non già impostata
if (!options.context?.keepSession) {
options.proxyUrl = proxyUrl('US');
}
},
],
beforeRetry: [
(error, retryCount) => {
console.warn(`Retry ${retryCount} after ${error.response?.statusCode}`);
},
],
afterResponse: [
(response, retryWithMergedOptions) => {
if (response.statusCode === 403) {
// ruota sessione e riproca
return retryWithMergedOptions({
proxyUrl: proxyUrl('US'),
});
}
return response;
},
],
},
});
// uso
const res = await client('https://example.com/api/products', {
responseType: 'json',
});
console.log(res.body.length);
Il pattern chiave: afterResponse intercetta i 403 e chiama retryWithMergedOptions con un nuovo proxyUrl generato da proxyUrl('US'). Questo è un middleware idiomatiko di got, non un wrapper esterno.
ProxyHat SDK per username per-request
Per progetti più grandi, puoi astrarre la generazione dell'username in un piccolo helper o SDK interno che gestisce pool di sessioni, rate limiting per-country e fallback. Consulta la documentazione ProxyHat per i parametri supportati e le best practice.
Pattern di produzione: concorrenza, cookie jar e Crawlee
Lo scraping a scala richiede più di una singola richiesta. Ecco i pattern essenziali.
Concorrenza limitata con p-limit
Senza un limite, apri centinaia di connessioni simultanee, saturi il pool di socket e ottieni errori di timeout. Usa p-limit per vincolare la concorrenza.
import pLimit from 'p-limit';
const limit = pLimit(20); // 20 richieste concorrenti
const urls = ['https://example.com/a', 'https://example.com/b', /* ... */];
const results = await Promise.all(
urls.map((url) => limit(() => client(url, { responseType: 'json' })))
);
Con 20 connessioni concorrenti e ~200ms per richiesta, puoi processare circa 100 richieste al secondo per worker. Scala orizzontalmente con container separati per superare i limiti di un singolo nodo.
Cookie jar per sessioni autenticate
got supporta tough-cookie nativamente. Usa un cookie jar per mantenere la sessione tra richieste consecutive con lo stesso IP sticky.
import { CookieJar } from 'tough-cookie';
const jar = new CookieJar();
const sessionClient = client.extend({
cookieJar: jar,
context: { keepSession: true },
proxyUrl: proxyUrl('US', 'persistent-session-1'),
});
await sessionClient('https://example.com/login', { method: 'POST', json: { user, pass } });
const dashboard = await sessionClient('https://example.com/dashboard');
Passare a Crawlee CheerioCrawler
Quando hai bisogno di parsing HTML strutturato, code di URL e gestione degli errori, Crawlee è il framework di Apify che usa got-scraping sotto il cofano. CheerioCrawler è ideale per HTML statico.
import { CheerioCrawler } from 'crawlee';
const crawler = new CheerioCrawler({
async requestHandler({ $, request }) {
const titles = $('h2.product-title').text();
console.log(request.url, titles);
},
maxConcurrency: 20,
proxyConfiguration: {
proxyUrls: [proxyUrl('US')],
},
});
await crawler.run(['https://example.com/products']);
Crawlee gestisce automaticamente retry, rotazione proxy e code. È il livello di astrazione successivo quando got-scraping da solo diventa troppo manuale.
Confronto: got-scraping vs got vs axios per scraping
| Feature | got-scraping | got | axios |
|---|---|---|---|
| Header generator integrato | Sì | No (manuale) | No (manuale) |
| HTTP/2 nativo | Sì | Sì (v12+) | Limitato |
| Supporto SOCKS5 proxy | Sì | Tramite agent | Tramite agent |
| Retry hooks idiomatiki | Sì | Sì | No (manuale) |
| Integrazione Crawlee | Nativa | Indiretta | No |
| Footprint browser-like | Alto | Basso | Basso |
Quando serve un browser headless
got-scraping è potente per HTML statico e API JSON, ma non esegue JavaScript. Se il sito renderizza contenuti client-side (React, Vue, Next.js SSR dinamico) o usa sfide Cloudflare/Datadome basate su esecuzione JS, serve un browser headless: Playwright o Puppeteer. Crawlee offre PlaywrightCrawler che combina il controllo browser con la rotazione proxy di got-scraping.
Regola pratica: se curl o got-scraping restituiscono HTML senza i dati cercati, il sito sta renderizzando lato client. A quel punto, passa a Playwright con lo stesso setup proxy.
Etica, conformità e limiti
Lo scraping responsabile non è opzionale. Alcuni principi:
- Dati pubblici solo. Non accedere ad aree autenticate senza permesso esplicito.
- Onora robots.txt. Verifica
/robots.txtprima di avviare una raccolta su larga scala. - Rate limiting. Mantieni una concorrenza ragionevole (es. 20 richieste concorrenti) e aggiungi delay tra le richieste per non impattare il server target.
- GDPR e CCPA. Dati personali (nomi, email, IP) sono regolamentati. Se raccogli dati personali di utenti UE, applica i principi del GDPR.
- Preferisci API ufficiali. Se il sito offre un'API pubblica o a pagamento, usala. È più stabile e legalmente più sicura.
- CFAA. Negli USA, il Computer Fraud and Abuse Act può applicarsi ad accessi non autorizzati. Consulta un avvocato per casi complessi.
Pattern di scaling: container e headless fleet
Per scala oltre un singolo worker, containerizza con Docker e scala orizzontalmente. Ogni container esegue un worker con il proprio pool di sessioni ProxyHat. Con 10 container a 20 connessioni ciascuno, raggiungi 200 sessioni concorrenti, sufficienti per la maggior parte dei job di monitoraggio prezzi o SERP.
Per browser headless, usa un'orchestrazione come browserless o un pool Playwright gestito. Mantieni i proxy residenziali per evitare che l'IP del container venga bloccato dopo poche richieste.
Key Takeaways
- got-scraping risolve il problema degli header coerenti con
header-generatore supporta HTTP/2 nativo.- Usa
got.extend()conuseHeaderGeneratorcome middleware idiomatiko, non hack manuali.- Proxy residenziali su
gate.proxyhat.com:8080(HTTP) o:1080(SOCKS5) sono essenziali una volta che header e TLS sono realistici.- Sessioni sticky (
user-session-xxx) per mantenere stato tra richieste; rotazione per-request per distribuire il carico.afterResponseebeforeRetryhooks per rotazione automatica su 403/429.- Limita concorrenza con
p-limit(es. 20), usa cookie jar per sessioni autenticate, passa a Crawlee per parsing complesso.- Per contenuti renderizzati lato client, usa Playwright con gli stessi proxy.
- Etica: dati pubblici, robots.txt, rate limit, GDPR, API ufficiali quando disponibili.
Pronto a iniziare? Esplora i piani ProxyHat, le locazioni disponibili e i casi d'uso per web scraping e SERP tracking. Per i dettagli tecnici del gateway, consulta la documentazione ufficiale.






