Guide got-scraping dans Node.js : proxies résidentiels et header generator en production

Apprenez à utiliser got-scraping dans Node.js avec des proxies résidentiels : header-generator, rotation d'IP, hooks de retry et patterns de production à grande échelle.

got-scraping in Node.js: A Developer's Guide to Headers, HTTP/2 & Residential Proxies

Si vous scrapez sérieusement en Node.js, vous avez probablement rencontré got-scraping, le client HTTP d'Apify basé sur got et conçu spécifiquement pour le web scraping. Ce guide pratique explique comment configurer got-scraping dans Node.js avec des proxies résidentiels, exploiter le header generator pour émettre des en-têtes cohérents, et déployer des patterns de production robustes. Avant d'aller plus loin, une mise au point : ne scrapez que des données publiques, respectez le robots.txt, les conditions d'utilisation des sites, et le RGPD/CCPA. Préférez toujours une API officielle quand elle existe.

Pourquoi got-scraping dans Node.js change la donne

Les requêtes HTTP brutes avec got ou axios finissent presque toujours par être bloquées sur les sites protégés. La raison tient à trois signaux que les systèmes anti-bot modernes — Cloudflare, Datadome, PerimeterX — analysent en quelques millisecondes :

  • Empreinte TLS/JA3 : Node.js utilise OpenSSL, dont la négociation TLS diffère de celle de Chrome ou Firefox. Un bot peut envoyer un User-Agent Chrome, mais son JA3 reste celui de Node.
  • Cohérence des en-têtes : un vrai navigateur envoie sec-ch-ua, sec-fetch-dest, accept-language dans un ordre précis. Un client HTTP générique les omet ou les désordonne.
  • Support HTTP/2 : de nombreux sites servent le HTTP/2 uniquement aux clients ALPN-négociés ; un client HTTP/1.1 pur est immédiatement suspect.

got-scraping adresse ces points. Il s'appuie sur header-generator, une librairie open-source d'Apify qui génère des ensembles d'en-têtes cohérents pour un navigateur, un appareil et un OS donnés — y compris les sec-ch-ua et l'ordre des en-têtes. De plus, il supporte nativement le HTTP/2 via http2-wrapper, ce qui rapproche l'empreinte réseau de celle d'un vrai navigateur. Voir la documentation officielle de got-scraping pour les détails.

Le contexte technique : pourquoi les en-têtes comptent autant que l'IP

Beaucoup de développeurs pensent qu'un proxy résidentiel suffit à passer les filtres. C'est faux. Un proxy résidentiel change votre IP source, mais si vos en-têtes et votre TLS trahissent Node.js, le système anti-bot vous classe comme bot avant même de regarder l'IP. La défense en profondeur exige :

  1. Des en-têtes navigateur cohérents (header-generator).
  2. Une empreinte TLS plausible (HTTP/2, ALPN, ordre des cipher suites).
  3. Une IP résidentielle ou mobile qui correspond à la géolocalisation déclarée dans accept-language.

Sans les deux premiers, le troisième ne sert à rien. C'est exactement le créneau de got scraping header generator : produire un ensemble d'en-têtes qui, combiné à un proxy résidentiel, rend votre trafic indiscernable d'un visiteur réel. Les benchmarks publics montrent que les sites protégés par Cloudflare bloquent 40 à 60 % des requêtes HTTP/1.1 avec en-têtes génériques, même derrière une IP résidentielle — contre moins de 10 % avec des en-têtes cohérents et HTTP/2.

Surface idiomatique de got-scraping

got-scraping expose une API compatible got. On l'étend via got.extend() avec un middleware qui injecte les en-têtes générés à chaque requête. Voici les points d'extension clés :

got.extend et useHeaderGenerator

La fonction useHeaderGenerator active le générateur d'en-têtes. On configure headerGeneratorOptions avec trois dimensions :

  • browsers : ['chrome', 'firefox'] — le navigateur à imiter.
  • devices : ['desktop'] ou ['mobile'] — desktop produit des en-têtes tablette/laptop, mobile ajoute sec-ch-ua-mobile.
  • operatingSystems : ['windows', 'macos', 'linux', 'android', 'ios'] — influence les sec-ch-ua-platform et user-agent.

Le générateur garantit la cohérence interne : si vous demandez Chrome sur macOS, vous obtenez un user-agent Chrome/macOS, un sec-ch-ua-platform macOS, et un accept-language plausible. L'ordre des en-têtes suit celui de Chrome réel.

proxyUrl : HTTP/1 et HTTP/2

got-scraping accepte une option proxyUrl pour HTTP/1.1 et HTTP/2. Pour HTTP/2 via proxy, got-scraping utilise http2-wrapper avec support CONNECT. Le format est l'URL standard :

http://user-country-US:password@gate.proxyhat.com:8080
socks5://user-country-DE:password@gate.proxyhat.com:1080

Routing via proxies résidentiels ProxyHat

Une fois les en-têtes et le TLS maîtrisés, l'IP source devient le facteur discriminant. Les proxies datacenter sont dans des plages ASN identifiées (OVH, DigitalOcean, AWS) que les anti-bots filtrent agressivement. Les proxies résidentiels utilisent des IPs attribuées par des FAI à de vrais foyers — leur réputation est celle d'un utilisateur normal.

Avec ProxyHat, le gateway est gate.proxyhat.com, port 8080 pour HTTP, 1080 pour SOCKS5. Le pays et la session se passent dans le nom d'utilisateur, ce qui permet une rotation par requête sans réauthentification :

  • user-country-US — IP résidentielle aux États-Unis.
  • user-country-DE-city-berlin — ciblage ville.
  • user-session-abc123 — session sticky (même IP pendant la durée de la session).
  • user-country-US-session-abc123 — combinaison pays + session.

Consultez la documentation ProxyHat et la page des locations pour la liste complète des géos disponibles.

Exemple Node.js : rotation résidentielle avec retry hooks

Voici un exemple complet et exécutable. Il crée une instance got-scraping étendue, génère un nom d'utilisateur par requête avec rotation de pays et de session, et implémente un hook de retry sur les erreurs 429/503.

import gotScraping from 'got-scraping';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { SocksProxyAgent } from 'socks-proxy-agent';

const PROXYHAT_HOST = 'gate.proxyhat.com';
const PROXYHAT_HTTP_PORT = 8080;
const PROXYHAT_SOCKS_PORT = 1080;
const PROXY_USER = 'youruser';
const PROXY_PASS = 'yourpass';

// Génère un nom d'utilisateur avec pays + session uniques par requête
function buildUsername({ country = 'US', sessionId = null } = {}) {
  const parts = [`country-${country}`];
  if (sessionId) parts.push(`session-${sessionId}`);
  return `${PROXY_USER}-${parts.join('-')}`;
}

function buildProxyUrl({ country, sessionId, socks5 = false }) {
  const username = buildUsername({ country, sessionId });
  const scheme = socks5 ? 'socks5' : 'http';
  const port = socks5 ? PROXYHAT_SOCKS_PORT : PROXYHAT_HTTP_PORT;
  return `${scheme}://${username}:${PROXY_PASS}@${PROXYHAT_HOST}:${port}`;
}

const client = gotScraping.extend({
  headerGeneratorOptions: {
    browsers: [{ name: 'chrome', minVersion: 120 }],
    devices: ['desktop'],
    operatingSystems: ['windows', 'macos'],
  },
  retry: {
    limit: 4,
    statusCodes: [429, 503, 504],
    backoffLimit: 8000,
  },
  hooks: {
    beforeRequest: [
      (options) => {
        const sessionId = Math.random().toString(36).slice(2, 10);
        const proxyUrl = buildProxyUrl({
          country: 'US',
          sessionId,
          socks5: false,
        });
        options.proxyUrl = proxyUrl;
      },
    ],
    afterResponse: [
      (response, retryWithMergedOptions) => {
        if (response.statusCode === 403) {
          // Rotation de session et retry
          return retryWithMergedOptions({
            hooks: {
              beforeRequest: [
                (opts) => {
                  opts.proxyUrl = buildProxyUrl({
                    country: 'US',
                    sessionId: Math.random().toString(36).slice(2, 10),
                  });
                },
              ],
            },
          });
        }
        return response;
      },
    ],
  },
});

// Utilisation
const res = await client('https://httpbin.org/headers', {
  timeout: { request: 15000 },
});
console.log(res.body);

Ce pattern est idiomatique : got.extend crée un client réutilisable, beforeRequest injecte le proxy par requête, et afterResponse gère les retries avec rotation. La session change à chaque retry, ce qui évite de retomber sur la même IP bloquée.

Variante SOCKS5

Pour SOCKS5, changez le port vers 1080 et le schéma vers socks5 :

const proxyUrl = buildProxyUrl({
  country: 'DE',
  sessionId: 'order-9871',
  socks5: true,
});
// => socks5://youruser-country-DE-session-order-9871:yourpass@gate.proxyhat.com:1080

SOCKS5 est utile quand le site cible bloque les proxies HTTP transparents ou quand vous avez besoin d'un tunnel TCP de bout en bout (par exemple pour des websockets scraping).

Patterns de production

Retry et afterResponse hooks

got fournit un système de retry intégré configurable via retry.limit, retry.statusCodes, et retry.backoffLimit. Pour le scraping, on étend généralement les statusCodes à [429, 503, 504] et on ajoute un backoff exponentiel avec jitter. Le hook afterResponse permet de détecter les CAPTCHAs (souvent renvoyés en 200 avec un body spécifique) et de déclencher une rotation de proxy + retry :

hooks: {
  afterResponse: [
    (response, retryWithMergedOptions) => {
      const isCaptcha = response.statusCode === 200
        && response.body.includes('cf-challenge-running');
      if (isCaptcha) {
        return retryWithMergedOptions({
          proxyUrl: buildProxyUrl({
            country: 'US',
            sessionId: Math.random().toString(36).slice(2, 10),
          }),
        });
      }
      return response;
    },
  ],
},

Concurrency bornée avec p-limit

Lancer 10 000 requêtes en parallèle saturera votre bande passante, déclenchera des rate limits, et fera flagger votre trafic. Utilisez p-limit pour borner la concurrence :

import pLimit from 'p-limit';

const limit = pLimit(20); // 20 requêtes simultanées max

const urls = ['https://example.com/page/1', /* ... */];

const results = await Promise.all(
  urls.map((url) => limit(() => client(url, { timeout: { request: 15000 } })))
);

20 connexions concurrentes est un bon point de départ pour un proxy résidentiel. Au-delà, augmentez progressivement en surveillant le taux de succès. ProxyHat supporte 100 sessions concurrentes par plan standard — adaptez en conséquence.

Cookie jars

Les sites e-commerce et les plateformes social utilisent des cookies de session pour valider la séquence de navigation. got-scraping supporte tough-cookie via l'option cookieJar. Pour les sessions stickies avec proxy résidentiel, associez un cookie jar par session :

import { CookieJar } from 'tough-cookie';

const sessionJar = new CookieJar();

const res = await client('https://example.com/login', {
  cookieJar: sessionJar,
  proxyUrl: buildProxyUrl({ country: 'US', sessionId: 'sess-001' }),
});
// Requête suivante avec même session => même IP + mêmes cookies
const res2 = await client('https://example.com/dashboard', {
  cookieJar: sessionJar,
  proxyUrl: buildProxyUrl({ country: 'US', sessionId: 'sess-001' }),
});

Migration vers Crawlee (CheerioCrawler)

Quand votre pipeline grandit au-delà de quelques centaines d'URLs, orchestrez avec Crawlee, le framework d'Apify qui enveloppe got-scraping. CheerioCrawler parse le HTML avec cheerio et gère automatiquement la rotation, les retries, et la file d'attente :

import { CheerioCrawler } from 'crawlee';

const crawler = new CheerioCrawler({
  requestHandler: async ({ $, request }) => {
    const title = $('title').text();
    console.log(request.url, title);
  },
  maxRequestsPerCrawl: 5000,
  maxConcurrency: 20,
  proxyConfiguration: {
    newUrlFunction: () => buildProxyUrl({
      country: 'US',
      sessionId: Math.random().toString(36).slice(2, 10),
    }),
  },
});

await crawler.run(['https://example.com/page/1', 'https://example.com/page/2']);

Crawlee s'intègre nativement avec les proxies ProxyHat via proxyConfiguration. Pour des cas d'usage spécifiques, consultez web scraping et SERP tracking.

Quand un navigateur headless devient inévitable

got-scraping suffit pour 80 à 90 % des sites. Mais certains flux exigent une exécution JavaScript réelle : SPA rendues côté client, challenges Cloudflare Turnstile interactifs, ou pages qui chargent les données via XHR après le DOM initial. Dans ces cas, passez à PlaywrightCrawler dans Crawlee, ou à Playwright directement avec un proxy résidentiel.

Le coût est réel : un headless Chrome consomme ~150-200 Mo de RAM par instance et ~300 ms de startup. Pour une flotte de 100 onglets concurrents, prévoyez 16-20 Go de RAM. Containerisez avec Docker et scalez horizontalement. Utilisez playwright-extra avec stealth plugin pour réduire la détectabilité.

Approche RAM / instance Latence Détectabilité Coût relatif
got-scraping + proxy résidentiel ~30 Mo 200-500 ms Faible
Playwright headless + proxy ~150-200 Mo 1-3 s Très faible 5-10×
Playwright + stealth + proxy résidentiel ~200-250 Mo 2-5 s Minimale 8-15×

Éthique et limites légales

Le web scraping opère dans une zone grise légale. Aux États-Unis, le Computer Fraud and Abuse Act (CFAA) a été utilisé contre des scrapers, bien que l'arrêt Van Buren v. United States (2021) ait restreint sa portée. En UE, le RGPD s'applique aux données personnelles que vous pourriez collecter, même indirectement. Règles de bon sens :

  • Respectez robots.txt — c'est un signal de bonne foi devant un tribunal.
  • Limitez le débit — ne saturz pas l'infrastructure cible. 1-2 req/s par domaine est raisonnable.
  • Ne contournez pas d'authentification — accéder à du contenu derrière login sans autorisation est une violation claire.
  • Préférez les APIs officielles — Twitter, Reddit, Google proposent des APIs ; utilisez-les quand elles couvrent votre besoin.
  • Ne stockez pas de données personnelles au-delà du nécessaire.

Erreurs courantes et edge cases

Oublier le cookie jar en mode sticky session

Si vous utilisez user-session-abc123 sans cookie jar, chaque requête part avec une session serveur vierge. Les sites qui valident la séquence (login → browse → checkout) renverront 403. Associez systématiquement un cookie jar à un sessionId fixe.

Mélanger devices et operatingSystems incompatibles

Demander devices: ['mobile'] avec operatingSystems: ['macos'] produit un user-agent incohérent (macOS n'existe pas sur mobile). header-generator ne le détecte pas toujours. Restez sur des combinaisons réelles : mobile + android/ios, desktop + windows/macos/linux.

Ne pas gérer le backoff exponentiel

Sur un 429, relancer immédiatement aggrave le rate limit. Utilisez retry.backoffLimit: 8000 et laissez got appliquer le backoff. Ajoutez du jitter pour éviter le thundering herd si vous avez plusieurs workers.

Ignorer l'ordre des en-têtes

header-generator gère l'ordre, mais si vous ajoutez manuellement des en-têtes via headers: { ... }, ils s'ajoutent après les en-têtes générés. Les anti-bots vérifient que user-agent arrive avant accept-encoding. Évitez les surcharges manuelles sauf nécessité absolue.

Key Takeaways

  • got-scraping génère des en-têtes navigateur cohérents (ordre, sec-ch-ua, accept-language) et supporte HTTP/2 — c'est la base avant tout proxy.
  • Les proxies résidentiels deviennent efficaces uniquement quand les en-têtes et le TLS sont plausibles. Sans header-generator, un proxy résidentiel ne suffit pas.
  • ProxyHat : gateway gate.proxyhat.com, port 8080 HTTP, 1080 SOCKS5. Pays et session dans le nom d'utilisateur.
  • Production : got.extend + hooks beforeRequest/afterResponse, p-limit pour la concurrence, cookie jars pour les sessions stickies.
  • Au-delà de ~500 URLs, migrez vers Crawlee CheerioCrawler pour l'orchestration.
  • Respectez robots.txt, le RGPD/CCPA, et préférez les APIs officielles.

FAQ

Qu'est-ce que got-scraping dans Node.js ?

got-scraping est un client HTTP pour Node.js basé sur got, développé par Apify. Il intègre un générateur d'en-têtes navigateur cohérents, le support HTTP/2, et des options de proxy pensées pour le scraping. Il s'utilise comme got standard, via gotScraping.extend(), avec des middlewares pour injecter en-têtes et proxies par requête.

Pourquoi got-scraping dans Node.js compte-t-il pour les utilisateurs de proxies ?

Parce qu'un proxy résidentiel seul ne suffit pas : les anti-bots analysent les en-têtes et l'empreinte TLS avant l'IP. got-scraping génère des en-têtes cohérents (ordre, sec-ch-ua, accept-language) et négocie le HTTP/2, ce qui rend le trafic plausible. Combiné à un proxy résidentiel, il maximise le taux de succès sur les sites protégés.

Quel type de proxy fonctionne le mieux avec got-scraping ?

Les proxies résidentiels sont le meilleur choix : ils utilisent des IPs de FAI réels avec une réputation neutre. Les proxies datacenter sont filtrés par ASN. Les proxies mobiles offrent la meilleure réputation mais sont plus chers. Avec ProxyHat, utilisez le port 8080 pour HTTP et 1080 pour SOCKS5, en passant le pays et la session dans le nom d'utilisateur.

Comment éviter les blocages avec got-scraping dans Node.js ?

Combinez header-generator (en-têtes cohérents), proxies résidentiels rotatifs, retry hooks avec backoff exponentiel, concurrence bornée (p-limit à 20), et cookie jars pour les sessions stickies. Respectez le robots.txt, limitez à 1-2 req/s par domaine, et faites tourner les sessions à chaque 403/429. Surveillez le taux de succès et ajustez.

Quand passer de got-scraping à un navigateur headless ?

Quand le site exige une exécution JavaScript réelle (SPA rendues côté client, challenges interactifs Cloudflare Turnstile, données chargées via XHR post-DOM). got-scraping couvre 80-90 % des cas. Pour le reste, migrez vers PlaywrightCrawler dans Crawlee avec un proxy résidentiel, en comptant ~200 Mo de RAM par instance headless.

Prêt à commencer ?

Accédez à plus de 50M d'IPs résidentielles dans plus de 148 pays avec filtrage IA.

Voir les tarifsProxies résidentiels
← Retour au Blog