Navigateurs headless + proxies : guide complet de configuration pour Puppeteer et Playwright

Guide étape par étape pour configurer Puppeteer et Playwright avec rotation de proxy, plugins furtifs, émulation de périphérique, et modèles de grattage simultanés en utilisant des procurations résidentielles.

Navigateurs headless + proxies : guide complet de configuration pour Puppeteer et Playwright

Pourquoi les navigateurs sans tête ont besoin de proxies

Les navigateurs sans tête — les instances de navigateur fonctionnant sans interface graphique visible — sont essentiels pour la suppression des sites Web en JavaScript. Cependant, exécuter plusieurs sessions de navigateur sans tête à partir d'une seule adresse IP est un signal d'automatisation évident. Combiner navigateurs sans tête avec rotation de proxy résout cela en distribuant des demandes sur des milliers d'IP résidentiels.

Ce guide couvre la configuration mandataire Puppeteer et Playwright, les plugins furtifs et les stratégies de rotation. Pour connaître le fonctionnement de la détection, consultez notre guide des systèmes de détection anti-bot.

Installation de proxy Puppeteer

Configuration de base

// Puppeteer: Basic proxy configuration
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
  headless: 'new',
  args: [
    '--proxy-server=http://gate.proxyhat.com:8080',
    '--no-sandbox',
    '--disable-setuid-sandbox'
  ]
});
const page = await browser.newPage();
// Authenticate with the proxy
await page.authenticate({
  username: 'USERNAME',
  password: 'PASSWORD'
});
await page.goto('https://example.com', {
  waitUntil: 'networkidle2',
  timeout: 30000
});
const content = await page.content();
console.log(content.substring(0, 200));
await browser.close();

SOCKS5 avec Puppeteer

// Puppeteer: SOCKS5 proxy configuration
const browser = await puppeteer.launch({
  headless: 'new',
  args: [
    '--proxy-server=socks5://gate.proxyhat.com:1080'
  ]
});
const page = await browser.newPage();
await page.authenticate({
  username: 'USERNAME',
  password: 'PASSWORD'
});

Plugin pour chiots

La configuration par défaut Puppeteer expose des dizaines de marqueurs d'automatisation que les systèmes anti-bot détectent. Les puppeteer-extra-plugin-stealth plugin corrige ces marqueurs automatiquement.

// Install: npm install puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
// Apply stealth plugin
puppeteer.use(StealthPlugin());
const browser = await puppeteer.launch({
  headless: 'new',
  args: [
    '--proxy-server=http://gate.proxyhat.com:8080',
    '--disable-blink-features=AutomationControlled',
    '--window-size=1920,1080',
    '--disable-dev-shm-usage'
  ]
});
const page = await browser.newPage();
await page.authenticate({
  username: 'USERNAME',
  password: 'PASSWORD'
});
// Set realistic viewport
await page.setViewport({ width: 1920, height: 1080 });
// Set extra headers for consistency
await page.setExtraHTTPHeaders({
  'Accept-Language': 'en-US,en;q=0.9'
});
await page.goto('https://example.com');

Le plugin furtif patchs:

  • navigator.webdriver — non défini au lieu de vrai
  • chrome.runtime — ajoute des objets spécifiques à Chrome manquants
  • WebGL fournisseur/render — chaînes GPU réalistes
  • Plugin et les tableaux d'autorisation — correspondent à Chrome réel
  • Cohérence de la langue et de la plateforme

Pour une meilleure compréhension de l'adresse de ces patchs, voir notre article sur empreintes digitales du navigateur.

Configuration de proxy de dramaturge

Playwright offre une configuration proxy plus élégante que Puppeteer, prenant en charge les proxies par contexte et l'émulation de périphérique intégrée.

Configuration de base

// Playwright: Basic proxy setup
const { chromium } = require('playwright');
const browser = await chromium.launch({
  proxy: {
    server: 'http://gate.proxyhat.com:8080',
    username: 'USERNAME',
    password: 'PASSWORD'
  }
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
const title = await page.title();
console.log(`Page title: ${title}`);
await browser.close();

Proxy par contexte (Différentes IP par onglet)

// Playwright: Different proxy per context
const { chromium } = require('playwright');
const browser = await chromium.launch();
// Context 1: US proxy session
const ctx1 = await browser.newContext({
  proxy: {
    server: 'http://gate.proxyhat.com:8080',
    username: 'USERNAME-country-us-session-abc1',
    password: 'PASSWORD'
  },
  locale: 'en-US',
  timezoneId: 'America/New_York'
});
// Context 2: UK proxy session
const ctx2 = await browser.newContext({
  proxy: {
    server: 'http://gate.proxyhat.com:8080',
    username: 'USERNAME-country-gb-session-abc2',
    password: 'PASSWORD'
  },
  locale: 'en-GB',
  timezoneId: 'Europe/London'
});
const page1 = await ctx1.newPage();
const page2 = await ctx2.newPage();
// Each page uses a different IP and locale
await page1.goto('https://example.com');
await page2.goto('https://example.com');

Emulation du périphérique avec Proxy

// Playwright: Realistic device emulation + proxy
const { chromium, devices } = require('playwright');
const browser = await chromium.launch({
  proxy: {
    server: 'http://gate.proxyhat.com:8080',
    username: 'USERNAME',
    password: 'PASSWORD'
  }
});
// Emulate a specific device with matching settings
const context = await browser.newContext({
  ...devices['Desktop Chrome'],
  locale: 'en-US',
  timezoneId: 'America/Chicago',
  geolocation: { latitude: 41.8781, longitude: -87.6298 },
  permissions: ['geolocation'],
  colorScheme: 'light'
});
const page = await context.newPage();
await page.goto('https://example.com');

Rotation par procuration avec navigateurs sans tête

Stratégie 1 : Nouveau contexte par demande

Créez un nouveau contexte de navigateur pour chaque URL. Cela donne une nouvelle IP et des cookies propres par demande.

// Playwright: Rotate proxy per request via new contexts
async function scrapeWithRotation(urls) {
  const browser = await chromium.launch();
  const results = [];
  for (const url of urls) {
    const sessionId = `sess-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    const context = await browser.newContext({
      proxy: {
        server: 'http://gate.proxyhat.com:8080',
        username: `USERNAME-session-${sessionId}`,
        password: 'PASSWORD'
      }
    });
    const page = await context.newPage();
    try {
      await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
      const data = await page.evaluate(() => document.title);
      results.push({ url, data });
    } catch (error) {
      console.error(`Failed: ${url} — ${error.message}`);
    } finally {
      await context.close();
    }
    // Natural delay between requests
    await new Promise(r => setTimeout(r, 1000 + Math.random() * 2000));
  }
  await browser.close();
  return results;
}

Stratégie 2: Sessions collantes pour les flux multi-pages

Utilisez des sessions collantes lorsque vous devez maintenir la même IP sur plusieurs pages (pagination, flux de connexion).

// Playwright: Sticky session for multi-page scraping
async function scrapeWithStickySession(baseUrl, pageCount) {
  const sessionId = `sticky-${Date.now()}`;
  const browser = await chromium.launch({
    proxy: {
      server: 'http://gate.proxyhat.com:8080',
      username: `USERNAME-session-${sessionId}`,
      password: 'PASSWORD'
    }
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  const results = [];
  for (let i = 1; i <= pageCount; i++) {
    await page.goto(`${baseUrl}?page=${i}`, { waitUntil: 'networkidle' });
    const items = await page.$$eval('.item', els =>
      els.map(el => el.textContent.trim())
    );
    results.push(...items);
    // Natural delay between pages
    await new Promise(r => setTimeout(r, 1500 + Math.random() * 1500));
  }
  await browser.close();
  return results;
}

Stratégie 3 : Scraping simultané avec piscine

// Playwright: Concurrent scraping with proxy pool
async function concurrentScrape(urls, concurrency = 5) {
  const browser = await chromium.launch();
  const results = [];
  // Process URLs in batches
  for (let i = 0; i < urls.length; i += concurrency) {
    const batch = urls.slice(i, i + concurrency);
    const promises = batch.map(async (url) => {
      const sessionId = `conc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
      const context = await browser.newContext({
        proxy: {
          server: 'http://gate.proxyhat.com:8080',
          username: `USERNAME-session-${sessionId}`,
          password: 'PASSWORD'
        }
      });
      const page = await context.newPage();
      try {
        await page.goto(url, { timeout: 30000, waitUntil: 'domcontentloaded' });
        return { url, title: await page.title(), status: 'ok' };
      } catch (e) {
        return { url, error: e.message, status: 'error' };
      } finally {
        await context.close();
      }
    });
    const batchResults = await Promise.all(promises);
    results.push(...batchResults);
    // Delay between batches
    await new Promise(r => setTimeout(r, 2000));
  }
  await browser.close();
  return results;
}

Puppeteer avec Python (Pyppeteer Alternative)

Pour les développeurs de Python, playwright pour Python fournit les mêmes capacités avec une syntaxe plus propre.

# Python: Playwright with proxy and stealth settings
# pip install playwright
# playwright install chromium
from playwright.async_api import async_playwright
import asyncio
async def scrape_with_proxy():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            proxy={
                "server": "http://gate.proxyhat.com:8080",
                "username": "USERNAME",
                "password": "PASSWORD"
            }
        )
        context = await browser.new_context(
            viewport={"width": 1920, "height": 1080},
            locale="en-US",
            timezone_id="America/New_York",
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        )
        page = await context.new_page()
        await page.goto("https://example.com")
        title = await page.title()
        print(f"Title: {title}")
        await browser.close()
asyncio.run(scrape_with_proxy())

Optimisation des ressources

Les navigateurs sans tête consomment une mémoire et un processeur importants. Optimiser les charges de production :

Bloc Ressources inutiles

// Playwright: Block images, fonts, and CSS to save bandwidth
const context = await browser.newContext({
  proxy: {
    server: 'http://gate.proxyhat.com:8080',
    username: 'USERNAME',
    password: 'PASSWORD'
  }
});
const page = await context.newPage();
// Block non-essential resources
await page.route('**/*.{png,jpg,jpeg,gif,svg,webp,woff,woff2,ttf,css}', route =>
  route.abort()
);
// Block tracking and analytics
await page.route('**/{google-analytics,gtag,facebook}**', route =>
  route.abort()
);
await page.goto('https://example.com');

Gestion de la mémoire

  • Fermer les contextes après utilisation: Chaque contexte ouvert consomme 50-150 Mo. Toujours des contextes proches quand c'est fait.
  • Limiter les contextes concurrents : Conservez 3-10 contextes par instance de navigateur basé sur RAM disponible.
  • Redémarrer périodiquement le navigateur : Après 100-200 cycles de contexte, redémarrez le navigateur pour éviter les fuites de mémoire.
  • Utiliser sans tête: 'nouveau' (Puppeteer): Le nouveau mode sans tête utilise moins de mémoire que l'ancien.

Traitement des questions communes

Défauts d'authentification par procuration

// Handle proxy auth errors gracefully
try {
  const response = await page.goto(url, { timeout: 30000 });
  if (response.status() === 407) {
    console.error('Proxy authentication failed — check credentials');
  }
} catch (error) {
  if (error.message.includes('net::ERR_PROXY_CONNECTION_FAILED')) {
    console.error('Proxy connection failed — check proxy server availability');
  }
}

Manipulation des délais

// Retry with exponential backoff
async function gotoWithRetry(page, url, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await page.goto(url, {
        waitUntil: 'domcontentloaded',
        timeout: 30000
      });
    } catch (error) {
      if (attempt === maxRetries) throw error;
      const delay = 1000 * Math.pow(2, attempt) + Math.random() * 1000;
      console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`);
      await new Promise(r => setTimeout(r, delay));
    }
  }
}

Liste de vérification des pratiques exemplaires

Liste de vérification des pratiques exemplaires
PratiquePuppéteurDramaturge
Proxy par contextePar lancement seulementSupport proxy par contexte
Plaquettes de volmarionnettiste-extra-plugin-stealthEmulation intégrée du dispositif
Blocage des ressourcespage.setRequestInterceptionpage.route
Multi-navigateursChromium seulementChrome, Firefox, WebKit
Isolation des séancesNouveau navigateur par sessionNouveau contexte par session
Pour la plupart des tâches de grattage, Playwright est le choix recommandé sur Puppeteer en raison de son support proxy supérieur (par contexte), l'émulation de périphérique intégré et le support multi-navigateur. Combinez-le avec Proxies résidentielles de ProxyHat pour les meilleurs résultats.

Pour la configuration proxy spécifique à la langue sans navigateurs sans tête, voir nos guides pour Python, Node.jset Allez. Pour des stratégies anti-détection complètes, lisez notre guide de réduction de détection. Toujours suivre les pratiques de grattage éthique et de respect politiques d'accès au site Web.

Foire aux questions

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