La plupart des tutoriels "comment contourner Cloudflare" que l'on trouve sur internet ont cessé de fonctionner fin 2024. La raison n'est pas que Cloudflare a ajouté de nouvelles défenses. C'est que les anciennes défenses, le fingerprinting JA3 et les vérifications basiques d'en-têtes, ont été remplacées par une nouvelle génération qui brise tous les raccourcis. Ce guide explique ce que Cloudflare vérifie réellement en 2026, pourquoi cloudscraper, undetected-chromedriver et la plupart des plugins "stealth" échouent, et la recette en quatre couches qui fonctionne encore en production.
Le résumé honnête d'emblée : il n'existe pas d'astuce unique. Contourner Cloudflare de façon fiable exige la bonne IP, la bonne empreinte TLS, le bon ordre des frames HTTP/2 et (pour le niveau Bot Management) un vrai navigateur. Ratez l'un de ces points et vous échouez au filtre de l'edge avant même que votre requête n'atteigne le serveur d'origine.
La détection de bots de Cloudflare fonctionne comme un pipeline de filtres au niveau de l'edge. Chaque requête les traverse dans l'ordre. Le premier filtre qui rejette l'emporte, ce qui signifie qu'une requête peut échouer sur la seule réputation d'IP avant que la moindre empreinte ou le moindre en-tête ne soit examiné.
C'est la première vérification, et la moins coûteuse. Cloudflare maintient une base de données indexée par ASN (Autonomous System Number). Les ASN appartenant à des fournisseurs cloud bien connus (AWS AS16509, GCP AS15169, Azure AS8075, OVH AS16276, DigitalOcean AS14061, Hetzner AS24940, Vultr AS20473) font l'objet de la plus grande méfiance. Même avec une empreinte parfaite de niveau navigateur, une requête provenant de ces ASN est traitée comme coupable jusqu'à preuve du contraire.
Les ASN résidentiels (Comcast AS7922, Verizon AS701, China Telecom AS4134, BT AS2856) sont présumés légitimes. Une requête depuis une IP résidentielle avec une empreinte Python maladroite peut tout de même passer, tandis qu'une requête depuis une IP de datacenter avec une empreinte Chrome parfaite sera défiée ou bloquée.
JA4 est le successeur de 2023 de JA3, publié par FoxIO. Il hache des champs spécifiques du ClientHello TLS : version de TLS, suites de chiffrement (dans l'ordre), extensions (dans l'ordre), protocoles ALPN, algorithmes de signature et groupes supportés. La sortie est une empreinte déterministe comme t13d1516h2_8daaf6152771_b1ff8ab2d16f.
Le vrai Chrome 124 produit une JA4 spécifique. Le vrai Firefox 124 en produit une différente. La bibliothèque requests de Python (qui utilise urllib3 et OpenSSL) produit une JA4 qu'aucun vrai navigateur n'émet jamais, parce que l'ordre des chiffrements et la liste des extensions ne correspondent ni à Chrome ni à Firefox. Cloudflare repère ce motif avant d'analyser le moindre en-tête HTTP.
L'implication : toute bibliothèque qui utilise l'OpenSSL du système ou le TLS standard de Python est détectable. Cela inclut requests, aiohttp, httpx (configuration par défaut) et tout wrapper de "bypass" construit par-dessus.
Les connexions HTTP/2 transportent des frames de settings, des window updates, des frames de priorité et des frames d'en-têtes. Les navigateurs les envoient dans un ordre spécifique avec des valeurs spécifiques. Chrome 124 envoie un frame SETTINGS initial avec ces valeurs exactes, puis un WINDOW_UPDATE, puis HEADERS. Le httpx de Python avec HTTP/2 activé envoie une charge de settings différente et omet les frames de priorité que Chrome inclut.
L'ordre des pseudo-en-têtes HTTP/2 trahit aussi l'identité. Chrome envoie :method, :authority, :scheme, :path dans cet ordre. Firefox envoie :method, :path, :authority, :scheme. La plupart des bibliothèques Python et Go les sérialisent par ordre alphabétique. Cloudflare compare l'ordre au motif attendu pour le User-Agent déclaré et signale les divergences.
Les en-têtes HTTP/1.1 préservent l'ordre d'insertion. Le vrai Chrome envoie les en-têtes dans un ordre fixe : Host, Connection, Cache-Control, sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform, Upgrade-Insecure-Requests, User-Agent, Accept, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-User, Sec-Fetch-Dest, Accept-Encoding, Accept-Language. Le requests de Python les réordonne et utilise parfois une casse différente. Même fixer les en-têtes manuellement dans le bon ordre n'aide pas, car la bibliothèque sous-jacente les retrie.
Si les filtres précédents passent mais que le score reste suspect, Cloudflare sert un défi JavaScript. Le script calcule un token à partir de valeurs de l'environnement du navigateur (hash du canvas, renderer WebGL, audio context, propriétés de navigator, mesures de timing) et le soumet via XHR. Aucun client HTTP ne peut résoudre cela. Il vous faut un vrai navigateur, et le navigateur doit paraître réel (pas de navigator.webdriver = true, pas de propriétés manquantes).
Au niveau Bot Management, Cloudflare collecte les mouvements de la souris, la vitesse de scroll, le timing des clics et la dynamique de frappe au clavier via un script qui s'exécute en continu. Un navigateur headless qui charge la page et la scrape immédiatement sans jamais bouger la souris est détecté en quelques secondes. Les vrais utilisateurs se déplacent de façon erratique, font des pauses et relisent. Les bots scrollent de façon linéaire et cliquent au pixel près.
Les outils-raccourcis qui ont alimenté le scraping de 2021-2024 partagent tous un même mode de défaillance : ils corrigent la surface visible mais pas la pile TLS sous-jacente.
| Outil | Ce qu'il corrige | Pourquoi il échoue en 2026 |
|---|---|---|
cloudscraper | Solveur de défis JS (legacy) | Cloudflare est passé à Turnstile en 2023 ; les défis legacy sont obsolètes |
undetected-chromedriver | Corrige les flags qui trahissent Selenium | La JA4 fuit toujours du TLS sous-jacent de chromedriver ; navigator.webdriver n'est qu'un signal parmi plus de 40 |
selenium-stealth | Injecte des propriétés JS falsifiées | Cloudflare lit depuis la couche C++, pas depuis JS ; la falsification est détectable comme incohérente |
FlareSolverr | Enveloppe Chromium pour résoudre un défi ponctuel | cf_clearance est lié à l'IP du solveur ; un nouveau proxy invalide le token immédiatement |
puppeteer-extra-plugin-stealth standard | Corrige ~17 points de détection | Cloudflare a ajouté ~12 nouvelles vérifications en 2024-2025 que le plugin ne couvre pas |
Le motif est clair : les outils qui enveloppent un vrai navigateur et corrigent les fuites connues perdent la course aux armements en quelques mois. Les outils qui simulent la pile TLS d'un navigateur (curl_cffi, tls-client) ont survécu parce qu'ils se situent plus près du fil.
Un bypass qui fonctionne en 2026 a besoin des quatre couches. En sauter une seule fait chuter le taux de succès à un seul chiffre.
C'est non négociable pour tout site utilisant Cloudflare Pro ou supérieur. Le filtre de réputation d'IP rejette les ASN de datacenter avant même la fin du handshake TLS. Utilisez un proxy résidentiel avec une session sticky d'au moins 10 minutes pour que le cookie cf_clearance survive.
Utilisez curl_cffi (Python) ou tls-client (Go/Python). Tous deux se lient à un BoringSSL modifié qui embarque l'ordre de chiffrement exact de Chrome, sa liste d'extensions et ses valeurs ALPN.
from curl_cffi import requests
response = requests.get(
"https://target.com/api/products",
impersonate="chrome124",
proxies={"https": "http://user-session-abc123:pass@gate.jibaoproxy.com:10001"},
timeout=30,
)
print(response.status_code, len(response.text))
Le paramètre impersonate="chrome124" remplace la pile TLS pour que le ClientHello corresponde à Chrome 124 octet par octet. Le hash JA4 sera identique à celui d'une vraie installation de Chrome 124. Combinez-le avec un proxy résidentiel et vous passez les deux premiers filtres.
curl_cffi fixe les en-têtes dans l'ordre de Chrome automatiquement lorsque vous utilisez impersonate. Si vous ajoutez des en-têtes personnalisés, ajoutez-les à la fin plutôt que de les insérer au milieu. Évitez de fixer des en-têtes que le vrai Chrome n'enverrait pas (p. ex. X-Requested-With lors d'une navigation normale).
Pour Accept-Language, faites-le correspondre à la localisation géographique du proxy. Une IP résidentielle des États-Unis envoyant Accept-Language: zh-CN,zh;q=0.9 est un signal faible mais réel. Utilisez en-US,en;q=0.9 pour les IP américaines, de-DE,de;q=0.9 pour les IP allemandes, et ainsi de suite. C'est l'un des rares signaux que vous pouvez corriger gratuitement.
Si la cible déclenche un Managed Challenge (vous voyez une page de défi CF dans le corps de la réponse), curl_cffi seul ne peut pas le résoudre. Passez à Playwright avec Chromium patché.
from playwright.sync_api import sync_playwright
from rebrowser_playwright.sync_api import sync_playwright as rebrowser_sync
with rebrowser_sync() as p:
browser = p.chromium.launch(
headless=True,
proxy={
"server": "http://gate.jibaoproxy.com:10001",
"username": "user-session-abc123",
"password": "pass",
},
)
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
viewport={"width": 1920, "height": 1080},
locale="en-US",
timezone_id="America/New_York",
)
page = context.new_page()
page.goto("https://target.com/", wait_until="networkidle")
# cf_clearance is now in context.cookies()
cookies = context.cookies()
cf_clearance = next((c for c in cookies if c["name"] == "cf_clearance"), None)
browser.close()
Utilisez rebrowser-playwright au lieu du playwright standard. Il corrige les fuites du runtime CDP (Runtime.enable, l'exposition des commandes CDP à la page) que Cloudflare lit pour détecter l'automatisation headless. Une fois le défi passé, extrayez cf_clearance des cookies et repassez-le à curl_cffi pour la véritable boucle de scraping. Le navigateur n'est nécessaire qu'une fois par session, pas par requête.
L'instinct d'utiliser le proxy le moins cher est presque toujours erroné sur les sites protégés par Cloudflare. Reprenons le calcul avec des chiffres réels.
Hypothèses : page HTML moyenne de 500KB, scraping de 100,000 pages au total, la cible utilise Cloudflare Pro avec Bot Fight Mode activé.
| Configuration | Coût de bande passante | Taux de succès | Requêtes par succès | Coût total | Coût par page |
|---|---|---|---|---|---|
| Datacenter $0.8/GB + requests | $0.0005 / req | 0.5% | 200 | $10,000 | $0.10 |
| Datacenter $0.8/GB + curl_cffi | $0.0005 / req | 3% | 33 | $1,650 | $0.0165 |
| Résidentiel $2/GB + requests | $0.0033 / req | 40% | 2.5 | $825 | $0.0083 |
| Résidentiel $2/GB + curl_cffi | $0.0033 / req | 92% | 1.09 | $360 | $0.0036 |
| Résidentiel $2/GB + Playwright (rebrowser) | $0.017 / req (assets + JS) | 96% | 1.04 | $1,700 | $0.017 |
Deux constats qui méritent d'être soulignés :
Voici le motif que nous recommandons aux clients qui scrapent à grande échelle des cibles protégées par Cloudflare. Il minimise l'usage de Playwright (lent et cher) et maximise l'usage de curl_cffi (rapide et bon marché).
from curl_cffi import requests as cf_requests
from rebrowser_playwright.sync_api import sync_playwright
PROXY_USER_FMT = "user-session-{sid}"
PROXY_HOST = "http://gate.jibaoproxy.com:10001"
PROXY_PASS = "your_password"
def get_cf_clearance(target_url, session_id):
"""One-shot Playwright call to solve the challenge and extract cf_clearance."""
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={"server": PROXY_HOST,
"username": PROXY_USER_FMT.format(sid=session_id),
"password": PROXY_PASS},
)
ctx = browser.new_context(user_agent="Mozilla/5.0 ... Chrome/124.0.0.0 Safari/537.36")
page = ctx.new_page()
page.goto(target_url, wait_until="networkidle", timeout=45000)
cookies = ctx.cookies()
browser.close()
return {c["name"]: c["value"] for c in cookies}
def scrape_with_clearance(urls, session_id, cookies):
"""Reuse the same session_id (sticky IP) for all requests."""
proxy = f"http://{PROXY_USER_FMT.format(sid=session_id)}:{PROXY_PASS}@gate.jibaoproxy.com:10001"
out = []
for url in urls:
r = cf_requests.get(
url,
impersonate="chrome124",
proxies={"https": proxy},
cookies=cookies,
timeout=30,
)
if r.status_code == 200:
out.append((url, r.text))
elif r.status_code in (403, 503) and "challenge" in r.text.lower():
# cf_clearance expired; re-solve
cookies = get_cf_clearance(url, session_id)
r = cf_requests.get(url, impersonate="chrome124",
proxies={"https": proxy}, cookies=cookies)
out.append((url, r.text))
return out, cookies
# Usage
session_id = "scrape-job-2026-05-27"
cookies = get_cf_clearance("https://target.com/", session_id)
results, cookies = scrape_with_clearance(target_urls, session_id, cookies)
Points clés de cette recette :
Certains déploiements de Cloudflare ne peuvent être contournés à aucun coût raisonnable. Si vous voyez ces signaux, changez de stratégie (utilisez une API, associez-vous au propriétaire du site ou achetez les données) au lieu de cramer votre budget sur un bypass qui ne se stabilisera jamais.
| Niveau de la cible | Recette | Taux de succès attendu |
|---|---|---|
| CF Free / Pro (sans Bot Fight) | Datacenter + curl_cffi | 60-75% |
| CF Free / Pro + Bot Fight Mode | Résidentiel + curl_cffi | 85-93% |
| CF Business | Résidentiel + curl_cffi + Playwright occasionnel | 80-90% |
| CF Business + Turnstile | Résidentiel + rebrowser-playwright (chaque requête) | 70-85% |
| CF Enterprise + Bot Management | Résidentiel mobile + rebrowser + simulation comportementale | 30-60% |
| CF Enterprise + Bot Management + WAF personnalisé | Ne pas scraper ; viser une API ou un partenariat | <10% |
JIBAO Proxy propose des proxys résidentiels dynamiques avec plus de 90M d'IP dans plus de 240 pays, des sessions sticky jusqu'à 60 minutes et un ciblage au niveau du pays à partir de $2/GB. Pour les IP mobiles, consultez les proxys mobiles dynamiques. Les deux fonctionnent immédiatement avec curl_cffi, tls-client, Playwright, Puppeteer, Selenium et tout client HTTP supportant les proxys HTTP/SOCKS5.
Lecture associée : Sessions de Proxy Sticky vs Rotatives couvre en profondeur la configuration des sessions. Proxys pour Agents IA explique le cas d'usage des agents IA qui recoupe fortement le flux de travail de contournement de Cloudflare.
Obtenez 500 Mo de trafic gratuit. Lancez la combinaison curl_cffi + résidentiel sticky contre votre cible avant de vous engager.
Démarrer l'Essai GratuitLes nouveaux utilisateurs reçoivent 500 Mo à l'inscription, plus un bonus sur la première recharge. Offre à durée limitée.