đ·ïž Senior Web Scraping (Architecture & Evasion)
Guide expert : Contournement WAF (Cloudflare/Akamai), Fingerprinting (TLS/Canvas), Reverse Engineering d'API, Architecture distribuée et Proxy Management.
Fundamentals & Strategy
DiffĂ©rence Junior vs Senior. Ăthique, Legal (CMA/GDPR) et Analyse de cible.
Strategy LegalProxies & Network
Datacenter vs Residential vs 4G/5G. Rotation intelligente, Sticky IP, ASN Trust score.
Residential IP ISPTLS & Fingerprinting
JA3/JA4 Signatures, HTTP/2 frames, cURL-impersonate, TLS Handshake mimicry.
JA3 Cypher SuitesHeadless Browsers
Playwright vs Puppeteer. Patching CDP (Chrome DevTools Protocol). Stealth plugins.
Playwright CDPAnti-Bot Evasion
Contourner Cloudflare Turnstile, Akamai, Datadome, PerimeterX. Behavioral analysis.
WAF BypassReverse Engineering
Interception App Mobile (Frida, Cert pinning), APIs cachées, Protobuf/gRPC decoding.
MITM ProtobufCaptcha Solving
OCR local, AI Solvers (YOLO/CNN), API Services (2Captcha, CapSolver), Human farms.
ReCaptcha Computer VisionParsing & Cleaning
Robust Xpath/CSS selectors, Schema validation (Pydantic), Deduplication.
lxml JSON-LDScaling & Architecture
Scraping distribué (Celery/Kafka/Redis). Gestion des queues, Rate limiting global.
Scrapy Cluster RedisDevOps for Scrapers
Monitoring (Grafana/Prometheus), Logging, CI/CD, Containerisation, Ban management.
ObservabilityToolbox & Languages
Python (Scrapy) vs Node (Puppeteer) vs Go (Colly/Rod). Outils GUI.
StackCheatsheet
Commandes cURL, Snippets Python, Headers essentiels, Liste de User-Agents.
MemoL'Ăchelle de CompĂ©tence (The Scraping Ladder)
- Level 1 (Script Kiddie) :
- Stack : Python
requests,BeautifulSoup. - Limite : Bloqué instantanément par Cloudflare/Akamai (403). Ne gÚre pas le JS.
- Détection : User-Agent par défaut, pas de cookies, IP datacenter.
- Stack : Python
- Level 2 (Browser User) :
- Stack : Selenium, Puppeteer (Vanilla).
- Limite : Lent, gourmand en RAM. Détecté par
navigator.webdriver = true. - Avantage : Rend le JS, passe les sites basiques.
- Level 3 (Browser Expert) :
- Stack : Playwright + Stealth Plugins + CDP Patching.
- Technique : Masquage des fingerprints (Canvas, WebGL, Fonts).
- Infra : Rotation de proxies résidentiels basique.
- Level 4 (Protocol Engineer) :
- Stack : TLS Spoofing (cURL-impersonate, Go, Rust).
- Technique : Imite le handshake TLS et l'ordre des frames HTTP/2 de Chrome au bit prĂšs.
- Avantage : Performance extrĂȘme (pas de GUI), passe les WAFs silencieusement.
- Level 5 (Architect) :
- Stack : Distribué (Kafka/Redis), Reverse Engineering d'APIs Mobiles (gRPC/Protobuf), AI Solvers.
- Vision : Capacité à extraire 100M+ pages/jour sans trigger les alarmes.
Le Paradigme "Senior"
Un senior ne cherche pas à "contourner" un blocage, il cherche à se fondre dans la masse. L'objectif est l'indiscernabilité statistique entre votre bot et un utilisateur humain légitime sur une connexion résidentielle (FAI).
Identifier l'Adversaire (WAF Fingerprinting)
Avant d'écrire une ligne de code, inspectez les Headers HTTP et les Cookies de la cible.
| WAF / Bot Protection | Indicateurs (Headers/Cookies) | Difficulté |
|---|---|---|
| Cloudflare | Header server: cloudflare, cf-ray. Cookie __cf_bm. | Moyen (TLS Spoofing requis) |
| Akamai | Header server: AkamaiGHost. Cookie _abck, bm_sz. Sensor data payload. | Difficile (Behavioral analysis) |
| Datadome | Cookie datadome. Réponse 403 avec Captcha spécifique. | TrÚs Difficile (AI detection) |
| PerimeterX (Human) | Script _px.js, Cookie _px3. | Moyen |
| Shape (F5) | Headers commençant par X-. Obfuscation JS lourde. | ExtrĂȘme (Target Banking/Airline) |
Surface d'Attaque (Data Sources)
- API Cachées : Filtrer DevTools par
XHRouFetch. Rechercher des endpoints/api/v1,/graphql. - SSR Data (Hydration) : Sur les sites Next.js/Nuxt, chercher la balise
<script id="__NEXT_DATA__" type="application/json">. Elle contient tout l'état de la page en JSON pur (plus besoin de parser le HTML !). - Mobile App Endpoints : Installer l'app, configurer un Proxy MITM (Charles/HTTP Toolkit) + SSL Pinning Bypass (Frida). Les APIs mobiles sont souvent moins protégées que le Web (pas de Captcha, rate limit plus souple).
- Sitemaps & Feeds : Toujours vérifier
/sitemap.xmlou/robots.txtpour découvrir l'arborescence complÚte sans crawler.
Le Cadre Légal (Grey Area)
Disclaimer: Ceci n'est pas un conseil juridique. Le scraping de données publiques est généralement légal (cf. hiQ vs LinkedIn aux US), mais sujet à conditions.
- PII (GDPR/RGPD) : Ne JAMAIS stocker de donnĂ©es personnelles identifiables (Nom, Email, Tel) sans consentement ou intĂ©rĂȘt lĂ©gitime prouvĂ©. Anonymiser Ă la source.
- Copyright : Les faits (prix, horaires, météo) ne sont pas copyrightables. La structure créative d'une base de données ou les images/textes le sont.
- CFA / Trespass : Ne pas causer de déni de service (DoS). Respecter un "Rate Limit" raisonnable. Ne pas scraper derriÚre un login (Auth Wall) si les CGU l'interdisent explicitement (BrÚche contractuelle).
Ethical Scraping Manifesto
- Identification : Idéalement, mettre un contact dans le User-Agent (
Bot/1.0 (+https://my-company.com)). - Respect : Scraper pendant les heures creuses de la cible.
- Cache : Ne jamais re-télécharger une ressource inchangée (utiliser
If-Modified-Sinceou hasher l'URL).
L'Ăconomie du Scraping (ROI)
Le scraping coûte cher. Il faut optimiser le coût par page réussie (Cost Per Success - CPS).
| Ressource | Coût Est. | Impact |
|---|---|---|
| Dev Time | $$$$ | Maintenance des sélecteurs et bypass WAF constants. |
| Proxies DC | $ | Pas cher, mais taux d'échec élevé sur cibles premium. |
| Proxies Resi | $$$ | ~$10/GB. Ă utiliser uniquement pour les requĂȘtes finales (HTML). Ne jamais tĂ©lĂ©charger d'images via Resi ! |
| Captcha Solving | $$ | ~$0.5 - $2 / 1000 résolutions. Peut vite exploser. |
Stratégie d'Optimisation des Coûts
- Bandwidth Saving : Bloquer le chargement des images, fonts, CSS et trackers publicitaires dans le navigateur Headless (
page.route('**/*.{png,jpg,woff}', route => route.abort())). - Tiered Proxying :
- Tenter d'abord avec une IP Datacenter (Cheap).
- Si échec (403/Captcha), retry avec IP Résidentielle (Premium).
- Headless vs HTTP : Une requĂȘte HTTP (TLS spoofed) coĂ»te 100x moins de CPU/RAM qu'une instance Chrome Headless. Toujours privilĂ©gier le protocole pur.
Le Handshake TLS (Client Hello)
Avant mĂȘme d'envoyer un header HTTP, votre client nĂ©gocie le chiffrement. Les WAFs (Cloudflare, Akamai) analysent ce paquet binaire pour identifier le client.
- JA3 Hash : Concaténation hachée de :
SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats. - Le piĂšge Python :
requestsutilise OpenSSL par défaut. Chrome utilise BoringSSL. Leurs listes de Ciphers et l'ordre des Extensions sont radicalement différents. - JA4 : Nouvelle norme plus granulaire qui inclut le protocole (QUIC/TCP) et le ALPN.
Analyse Différentielle
Si vous envoyez un User-Agent "Chrome" avec un TLS "Python", c'est un flag immédiat (403 Forbidden).
HTTP/2 Frames Analysis (Akamai)
Contrairement à HTTP/1.1 (texte), HTTP/2 est binaire. L'implémentation du protocole trahit la librairie sous-jacente.
| Vecteur | Détail Technique |
|---|---|
| SETTINGS Frame | Chrome envoie des paramÚtres spécifiques (`HEADER_TABLE_SIZE`, `MAX_CONCURRENT_STREAMS`). Golang/Node en envoient d'autres. |
| WINDOW_UPDATE | La taille de fenĂȘtre initiale et les incrĂ©ments sont uniques Ă chaque navigateur. |
| Pseudo-Headers | L'ordre est strict : :method, :authority, :scheme, :path (m,a,s,p). Modifier cet ordre = Bot. |
Passive Fingerprinting
- Les WAFs écoutent passivement.
- Si votre scraper utilise `http2` en Python sans configurer finement les frames SETTINGS et PRIORITY, il sera détecté comme "nghttp2" ou "hyper", pas comme Chrome.
Canvas & WebGL
- Canvas Fingerprint : Le navigateur dessine une image cachée. Le rendu dépend du GPU, des drivers et de l'OS.
- Risque : Si vous utilisez Docker (Linux) et spoofez un User-Agent Windows, le rendu de police (Anti-aliasing) ne correspondra pas.
- WebGL : `renderer` et `vendor` strings. (Ex: "Mesa Intel Graphics" vs "Apple M1").
JS Runtime Consistency
Incohérences fatales :
navigator.platform= "Linux x86_64" alors que UA = "Windows".navigator.hardwareConcurrencyincompatible avec le profil.
Picasso / CreepJS Score
HTTP Clients (Niveau 4)
Outils capables de modifier le handshake TLS et les frames HTTP/2 pour imiter Chrome/Safari.
- curl-impersonate : Build custom de cURL compilé avec les librairies BoringSSL de Chrome.
- curl_cffi (Python) : Binding Python pour curl-impersonate. Le standard actuel.
- tls-client (Go/Python) : Librairie trÚs utilisée, basée sur utls (Go).
Code Snippet (curl_cffi)
from curl_cffi import requests
# Imitation parfaite de Chrome 110 (TLS + HTTP/2 + Headers Order)
r = requests.get(
"https://tls.peet.ws/api/all",
impersonate="chrome110",
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."
}
)
# Le serveur voit : JA3 de Chrome, HTTP/2 frames de Chrome.
print(r.json())
Comment ils vous détectent ?
| Vecteur | Détail |
|---|---|
| IP Reputation | Datacenter IPs (AWS, GCP) sont flaggées. Usage de proxy résidentiel obligatoire. |
| Browser Consistency | User-Agent dit "Mac" mais `navigator.platform` dit "Win32". Incohérence = Bot. |
| Automation Flags | `navigator.webdriver = true`. Attributs Selenium ($cdc_...). |
| Behavioral | Mouvement souris linéaire parfait. Clics instantanés (0ms). Pas de scroll. |
Les "Big Boss" WAF
- Cloudflare : Challenges JS (Turnstile), analyse TLS, IP rep.
- Datadome : TrÚs agressif. Analyse les événements souris/clavier cÎté client + Fingerprint serveur.
- Akamai : Analyse comportementale avancée et senseurs mobiles.
- PerimeterX (Human) : Détection d'automatisation lourde.
Patching du Navigateur (Playwright/Puppeteer)
Par défaut, un navigateur automatisé "fuit" son identité de bot via des variables JS spécifiques.
- Stealth Plugin :
puppeteer-extra-plugin-stealth. Masque `navigator.webdriver`, mock les plugins, override les langues. - Arguments de lancement :
args: [ '--disable-blink-features=AutomationControlled', '--no-sandbox' ]
CDP (Chrome DevTools Protocol)
Utiliser CDP pour modifier le navigateur Ă un niveau bas.
# Playwright (Python) : Changer le User-Agent et la Géoloc au niveau CDP
context = browser.new_context(
user_agent='Mozilla/5.0 ...',
locale='fr-FR',
timezone_id='Europe/Paris'
)
await context.add_init_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
Hidden APIs discovery
Le Web Scraping moderne n'est pas parser du HTML, c'est taper les APIs JSON non documentées.
- Intercept XHR/Fetch : Utiliser l'onglet Network. Filtrer par "XHR".
- GraphQL : Chercher les endpoints `/graphql`. Introspection souvent désactivée, mais les queries sont visibles.
- Mobile APIs : Souvent plus légÚres et moins protégées que le Web.
- Utiliser un émulateur (Android Studio / Genymotion).
- Proxy via HTTP Toolkit ou Charles Proxy.
- SSL Pinning Bypass : Utiliser Frida et des scripts comme `Universal Android SSL Pinning Bypass`.
Binary Data (Protobuf / gRPC)
Certains sites (Google Maps, Play Store) utilisent Protobuf pour réduire la bande passante. Illisible en brut.
De-obfuscation JS
- Les sites calculent souvent des tokens de signature en JS (ex: `X-Signature`).
- Il faut extraire l'algo JS, le nettoyer (AST de-obfuscation) et l'exécuter via un moteur JS (Node VM2) ou le réécrire en Python.
Pattern Producer-Consumer
- Producer (Seeder) : Script léger qui trouve les URLs à scraper (pagination, catégories) et les pousse dans une Queue.
- Queue (Broker) : Redis ou Kafka. Stocke les URLs, gÚre la priorité (FIFO/LIFO), dédoublonne.
- Consumers (Workers) : N instances de scrapers (stateless). Ils prennent une URL, scrapent, et poussent la donnée.
Infrastructure
[ Cron Job ] --> [ Redis Queue ] --> [ Worker Pool (K8s/Docker) ]
|
v
[ Proxy Rotator ]
|
v
[ Target Website ]
|
v
[ Data Lake S3 ] <---- [ Validation ] <---- [ Raw HTML ]
Redis as a Queue
Utilisation de Redis Sets pour la dĂ©duplication (ne pas scraper 2x la mĂȘme URL) et Redis Lists pour la queue.
- Sadd : `visited_urls`. Vérifier existence avant push.
- Lpush/Rpop : Gestion de la file d'attente.
- Scrapy-Redis : Librairie standard pour connecter Scrapy Ă Redis directement.
Proxy Rotation Architecture
- Ne jamais gérer la rotation dans le code du scraper si possible.
- Utiliser un Proxy Gateway (ex: ProxyRack, Smartproxy endpoint) ou un middleware local (ProxyChains, HAProxy) qui round-robin sur une liste.
- Sticky Session : Garder la mĂȘme IP pour une session de login, changer d'IP pour le scraping de catalogue public.
Common Headers (To mimic real browser)
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9...",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1"
}
Note : L'ordre des headers est important pour certains WAF (Akamai).
Useful Snippets
# Xpath : Sélectionner texte excluant enfants
//div[@class='content']/text()
# Xpath : Contient classe
//div[contains(@class, 'product')]
# Pandas : Nettoyage rapide
df.drop_duplicates(subset=['id'], keep='last')
df['price'] = df['price'].replace('[$,]', '', regex=True).astype(float)
# Docker : Lancer un headless chrome
docker run -d -p 9222:9222 --cap-add=SYS_ADMIN zenika/alpine-chrome
La Hiérarchie des IPs
| Type | Performance | Trust Score | Usage Idéal |
|---|---|---|---|
| Datacenter (DC) | ExtrĂȘme (< 50ms) | Nul (ASN AWS/GCP) | Sites sans protection, APIs publiques, Mass crawling. |
| ISP (Static Resi) | Haute (Fibre) | ĂlevĂ© | Le Graal. IP hĂ©bergĂ©e en DC mais annoncĂ©e comme RĂ©sidentielle (Verizon, Orange). Account Management. |
| Residential (P2P) | Variable (Latence) | Maximum | Contournement WAF strict. IP de vrais utilisateurs (botnets éthiques). |
| Mobile (4G/5G) | Moyenne | Intouchable | Création de comptes (Gmail/IG). CGNAT rend le ban impossible sans dommage collatéral. |
IPv4 vs IPv6
- IPv4 : Cher ($$), rare. Subnet banning frĂ©quent (si 1.2.3.4 est ban, tout le /24 risque de l'ĂȘtre).
- IPv6 : Quasi gratuit, quantité infinie.
- ProblÚme : Beaucoup de cibles (sites vieux ou mal configurés) ne supportent pas l'IPv6.
- Stratégie : Utiliser IPv6 pour scraper les GAFAM (Google/FB/LinkedIn) qui le supportent nativement.
Comment les WAF jugent votre IP ?
Ce n'est pas juste "IP bannie ou non". C'est un score de fraude probabiliste.
- ASN (Autonomous System Number) : Si ASN = "DigitalOcean" ou "Hetzner" -> Score de risque +50. Si ASN = "Comcast Cable" -> Score +0.
- Usage Type : Bases de données comme MaxMind ou IP2Location classifient les IPs (DCH=Data Center, ISP=Fixed Line, MOB=Mobile).
- Open Ports : Les WAF scannent votre IP. Ports 22/80/443/8080 ouverts ? -> C'est un proxy -> Ban.
- Neighbor Noise : Si vos voisins de subnet ("noisy neighbors") spammennt, vous coulez avec eux.
Passive OS Fingerprinting (p0f)
- Solution : Utiliser des proxies SOCKS5 avec réécriture de header TCP, ou s'assurer que l'OS du scraper matche l'OS simulé.
Architecture de Rotation (HAProxy)
Ne configurez jamais 1000 proxies dans votre code. Utilisez un Load Balancer local.
# haproxy.cfg (Rotation Round-Robin)
listen scraping_gateway
bind 127.0.0.1:8000
mode http
balance roundrobin
option http_proxy
server proxy1 1.2.3.4:8000 check
server proxy2 1.2.3.5:8000 check
...
Votre code tape uniquement localhost:8000. HAProxy gĂšre la distribution et le health-check.
Gestion des Sessions (Sticky vs Rotating)
- Rotating (Stateless) : Chaque requĂȘte HTTP = Nouvelle IP.
- Usage : Scraper des pages produits (PDP), Search Results (SERP).
- Sticky (Stateful) : L'IP reste la mĂȘme pour X minutes ou via un ID de session.
- Usage : Tunnel de commande, Login, Scenarios multi-étapes.
DIY 4G Proxy Farm
Construire sa propre infra mobile pour un coût dérisoire vs BrightData.
- Hardware : Hub USB alimenté + Dongles 4G Huawei (E3372) + Raspberry Pi / Mini PC.
- SIM Cards : Forfaits Data illimités grand public (Free Mobile, etc.).
- Rotation : Script Python qui interagit avec l'API du dongle pour rebooter la radio (Mode avion ON/OFF) -> Nouvelle IP assignée par l'opérateur.
Avantages du CGNAT (Carrier-Grade NAT)
Sur mobile, une IP publique est partagĂ©e par des milliers d'utilisateurs simultanĂ©ment. Si Cloudflare bannit cette IP, il bloque 5000 clients lĂ©gitimes de SFR/Orange dans la mĂȘme ville. Ils ne le feront pas.
Playwright vs Puppeteer vs Selenium
- Selenium : Legacy. Lent, détectable facilement (WebDriver flags), synchrone. à éviter pour du scraping moderne.
- Puppeteer : Node.js uniquement. ContrÎle Chrome via CDP. Excellent mais limité à l'écosystÚme JS.
- Playwright : Le standard moderne (Microsoft). Supporte Python/Node/Go. Moteur patché pour le stealth. Contextes isolés trÚs rapides.
Anti-Detect Browsers (ADB)
Pour les cas extrĂȘmes oĂč Playwright Stealth ne suffit pas.
- Outils comme GoLogin, Dolphin{anty}, AdsPower.
- Ils modifient le binaire Chrome pour falsifier le Canvas, WebGL, AudioContext, Font enumeration au niveau natif.
- Pilotables via API locale (Selenium/Puppeteer se connecte dessus via CDP).
Services de Résolution (API)
- 2Captcha / Anti-Captcha : Fermes humaines. Lent (10-30s) mais résout tout. Coût élevé.
- CapSolver / CapMonster : Résolution par IA. TrÚs rapide (<2s), moins cher. Idéal pour ReCaptcha v2/v3, hCaptcha.
- Méthode : On envoie la
sitekeyà l'API, on reçoit un token, on l'injecte dans le HTML (textareag-recaptcha-response) et on submit le form.
Computer Vision (Local Solving)
Pour les captchas simples (texte, sliders), inutile de payer une API.
- OCR : Tesseract ou modÚles CNN simples pour lire du texte déformé.
- Sliders (Puzzle) : Utiliser OpenCV pour détecter les bords (`Canny edge detection`) et calculer l'offset de glissement.
- YOLO : ModĂšles Object Detection pour cliquer sur "tous les feux rouges".
Selectors Robustness
- Ăviter les Xpath absolus fragiles :
/html/body/div[2]/div[3]/span. - Privilégier les attributs data :
//div[@data-testid='price']. - Utiliser la recherche de texte :
//*[contains(text(), 'Total:')]. - JSON-LD : Toujours vérifier si la page contient du JSON structuré (Schema.org) dans une balise
<script type="application/ld+json">. C'est de la donnée structurée offerte !
Validation (Pydantic)
from pydantic import BaseModel, HttpUrl, validator
class Product(BaseModel):
title: str
price: float
url: HttpUrl
@validator('price')
def check_positive(cls, v):
if v < 0: raise ValueError('Prix négatif')
return v
Monitoring Metrics
Un scraper en prod doit ĂȘtre monitorĂ© comme une usine.
- Success Rate : Ratio 200 OK vs (403 Forbidden + 503 Service Unavailable). Si < 90%, alerte.
- Item Coverage : "J'ai scrapé 100 pages mais obtenu 0 items". Signe de changement de DOM.
- Ban Rate per Proxy : Identifier les plages IP grillées.
Stack Technique
- Docker : Indispensable. Utiliser des images de base légÚres (Alpine) mais attention aux dépendances Chromium pour Playwright.
- CI/CD : Tests d'intégration quotidiens sur une URL témoin pour détecter les changements de layout.
- Logging : ELK ou Loki. Loguer le HTML des pages en erreur (sur S3) pour debug post-mortem.
| Langage | Lib | Usage |
|---|---|---|
| Python | Scrapy | Le framework industriel. Pipeline, middlewares, concurrence asynchrone (Twisted). |
| Python | curl_cffi | RequĂȘtes HTTP rapides avec impersonation TLS (Chrome/Safari). |
| Node.js | Crawlee | Framework moderne par Apify. Gestion auto des proxies et fingerprinting. |
| Go | Colly | Performance extrĂȘme, binaire unique, concurrence native. |
GUI Tools
- ScrapeOps : Dashboard de monitoring spécialisé scraping.
- Postman : Pour tester les APIs et générer les code snippets.
