Le pare-feu d'application Web (WAF) de Cloudflare permet aux opérateurs de sites de créer des règles qui déclenchent des défis CAPTCHA en fonction d'attributs de requête spécifiques : adresse IP, pays, chemin d'URL, score du bot, en-têtes ou toute combinaison. Comprendre quelles règles déclenchent des défis vous aide à diagnostiquer pourquoi vous voyez un CAPTCHA et à choisir la bonne approche pour le gérer.
Actions de règle WAF qui produisent des CAPTCHA
Les règles Cloudflare WAF prennent en charge plusieurs actions. Trois d’entre eux présentent des défis résolubles :
| Action du WAF | Que se passe-t-il | Statut HTTP | Méthode CaptchaAI |
|---|---|---|---|
| Défi géré | Cloudflare décide : défi invisible, Turnstile ou JS | 503 | turnstile |
| Défi JS | Page de défi JavaScript de 5 secondes | 503 | cloudflare_challenge |
| Défi interactif | CAPTCHA traditionnel (ancien, obsolète) | 403 | turnstile |
| Bloquer | Difficile 403, pas de défi | 403 | N/A (non résoluble) |
| Autoriser | Passage, pas de contrôle | 200 | N/A |
| Passer | Ignorer les règles WAF restantes | 200 | N/A |
| Journal | Événement de journal, aucune action | 200 | N/A |
Défi géré (le plus courant)
Le défi géré est l'action recommandée par Cloudflare. Il décide de manière adaptative le type de défi par visiteur :
WAF rule matches → Managed Challenge triggered
↓
Cloudflare evaluates visitor:
├─ Low risk → Invisible pass (no visible challenge)
├─ Medium risk → Turnstile widget (click to verify)
└─ High risk → JavaScript challenge page
↓
Successful → cf_clearance cookie issued
Modèles de règles WAF courants
Les opérateurs de sites créent des règles WAF à l'aide du langage d'expression de Cloudflare. Voici les modèles les plus susceptibles de déclencher des CAPTCHA pour le trafic automatisé :
Règles de score des bots
# Challenge traffic with low bot scores
(cf.bot_management.score lt 30)
→ Action: Managed Challenge
# Challenge non-verified bots
(cf.bot_management.score lt 50 and not cf.bot_management.verified_bot)
→ Action: JS Challenge
Les règles de score des robots sont le déclencheur le plus courant pour les outils d'automatisation. Les solveurs API de CaptchaAI reçoivent des scores au niveau humain car ils utilisent de vrais navigateurs.
Règles basées sur les pays
# Challenge traffic from specific countries
(ip.geoip.country in {"CN" "RU" "VN" "IN"})
→ Action: Managed Challenge
# Block specific regions entirely
(ip.geoip.country eq "XX")
→ Action: Block
Règles basées sur le chemin
# Challenge login page access
(http.request.uri.path eq "/login" or http.request.uri.path eq "/signup")
→ Action: Managed Challenge
# Challenge API endpoints
(http.request.uri.path contains "/api/")
→ Action: JS Challenge
Règles basées sur les tarifs
# Challenge after high request rate
(cf.threat_score gt 10 and http.request.uri.path contains "/search")
→ Action: Managed Challenge
Règles basées sur l'en-tête
# Challenge requests with no Accept-Language header
(not http.request.headers["accept-language"])
→ Action: JS Challenge
# Challenge requests with suspicious UA
(http.user_agent contains "python" or http.user_agent contains "curl")
→ Action: Managed Challenge
Règles composées
# Multiple conditions
(cf.bot_management.score lt 30
and http.request.uri.path contains "/api/"
and ip.geoip.country ne "US")
→ Action: JS Challenge
Identifier la règle déclenchée
Lorsqu'un challenge CAPTCHA apparaît, vous pouvez identifier la règle de déclenchement à partir de la réponse :
À partir des en-têtes HTTP
import requests
def check_cloudflare_rule_info(url):
"""Extract WAF rule information from Cloudflare challenge response."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0",
"Accept": "text/html,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
response = requests.get(url, headers=headers, timeout=15, allow_redirects=False)
info = {
"status": response.status_code,
"cf_ray": response.headers.get("cf-ray", ""),
"cf_cache_status": response.headers.get("cf-cache-status", ""),
"server": response.headers.get("server", ""),
}
# Challenge-specific info
html = response.text
if response.status_code == 503:
if "jschl" in html:
info["challenge_type"] = "JS Challenge (IUAM or WAF rule)"
elif "challenge-platform" in html:
info["challenge_type"] = "Managed Challenge"
elif "cf-turnstile" in html:
info["challenge_type"] = "Turnstile (Managed Challenge)"
elif response.status_code == 403:
if "cf-ray" in str(response.headers):
info["challenge_type"] = "WAF Block (no challenge)"
else:
info["challenge_type"] = "Origin 403 (not Cloudflare)"
return info
Depuis l'identifiant Cloudflare Ray
Chaque réponse Cloudflare inclut un en-tête cf-ray. Les opérateurs de site peuvent utiliser ce Ray ID dans le tableau de bord de Cloudflare (Sécurité > Événements) pour voir exactement quelle règle s'est déclenchée et quelle action a été entreprise.
Résoudre les défis déclenchés par le WAF
Stratégie basée sur le type de défi
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_cloudflare_challenge(url, challenge_type):
"""Solve Cloudflare challenge based on WAF rule action."""
if challenge_type == "managed_challenge":
# Managed Challenge typically renders as Turnstile
method = "turnstile"
sitekey = extract_turnstile_sitekey(url)
elif challenge_type == "js_challenge":
# JavaScript Challenge page
method = "cloudflare_challenge"
sitekey = "managed"
else:
raise ValueError(f"Unknown challenge type: {challenge_type}")
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": method,
"sitekey": sitekey,
"pageurl": url,
"json": 1,
})
task_id = submit.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
}).json()
if result.get("status") == 1:
return result["request"]
raise TimeoutError("Challenge solve timed out")
def extract_turnstile_sitekey(url):
"""Fetch page and extract Turnstile sitekey."""
import re
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0",
}
response = requests.get(url, headers=headers, timeout=15)
match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', response.text)
return match.group(1) if match else None
Noeud.js
const axios = require("axios");
const API_KEY = "YOUR_API_KEY";
async function solveWAFChallenge(url, challengeType) {
const method =
challengeType === "js_challenge" ? "cloudflare_challenge" : "turnstile";
const sitekey =
challengeType === "js_challenge" ? "managed" : await extractSitekey(url);
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY,
method,
sitekey,
pageurl: url,
json: 1,
},
});
const taskId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: taskId, json: 1 },
});
if (result.data.status === 1) {
return result.data.request;
}
}
throw new Error("Challenge solve timed out");
}
async function extractSitekey(url) {
const response = await axios.get(url, {
headers: {
"User-Agent": "Mozilla/5.0 Chrome/120.0.0.0",
},
});
const match = response.data.match(/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/);
return match ? match[1] : null;
}
Modifications des règles WAF et leurs effets
Les opérateurs de sites ajustent fréquemment les règles WAF. Ces changements affectent l'automatisation :
| Changement | Effet sur l'automatisation | Comment détecter |
|---|---|---|
| Règle ajoutée | Un nouveau défi apparaît sur les chemins qui ont fonctionné | Surveiller les changements d'état de 503/403 |
| Règle supprimée | Le défi disparaît | 200 là où 503 était avant |
| Action signalée (bloc → géré) | Un défi résoluble devient un bloc difficile | 403 au lieu de 503 |
| Action détendue (Bloc → Géré) | Le bloc dur devient un défi résoluble | 503 avec page de défi |
| Seuil modifié (score du bot 30 → 50) | Plus de demandes contestées | Augmentation de la fréquence des défis |
| Portée du chemin modifiée | Différentes URL concernées | Les nouveaux chemins génèrent des défis |
Stratégie de surveillance
import requests
import time
def monitor_cloudflare_protection(urls, interval=3600):
"""Monitor protection changes across URLs."""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0",
"Accept": "text/html,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
last_status = {}
while True:
for url in urls:
try:
response = requests.get(
url, headers=headers, timeout=15, allow_redirects=False
)
status = response.status_code
has_challenge = status == 503 or "cf-turnstile" in response.text
current = {"status": status, "challenge": has_challenge}
previous = last_status.get(url)
if previous and current != previous:
print(f"[CHANGE] {url}")
print(f" Before: {previous}")
print(f" After: {current}")
last_status[url] = current
except requests.RequestException as e:
print(f"[ERROR] {url}: {e}")
time.sleep(interval)
Dépannage
| Symptôme | Règle WAF probable | Corriger |
|---|---|---|
Défi uniquement sur /login |
Règle basée sur le chemin | Résoudre le défi pour ce chemin |
| Défi provenant uniquement des adresses IP du centre de données | Score du bot ou règle de réputation IP | Utilisez des proxys résidentiels ou résolvez un défi |
| Le défi varie selon les pays | Règle basée sur le pays | Utilisez un proxy dans le pays autorisé ou résolvez |
| Défi après N requêtes | Règle basée sur le taux | Réduisez le taux de demandes ou résolvez chaque défi |
| Défiez toujours JS (jamais Turnstile) | Action JS Challenge (non gérée) | Utiliser la méthode cloudflare_challenge |
| 403 sans défi | Action de blocage (non résoluble) | Modifier l'adresse IP, les en-têtes ou le modèle de demande |
Questions fréquemment posées
Puis-je voir quelles règles WAF un site utilise ?
Non. Les règles WAF sont privées et appartiennent à l'opérateur du site. Vous ne pouvez déduire des règles qu'à partir du comportement : quels chemins déclenchent des défis, à partir de quelles adresses IP et quel type de défi apparaît.
Les règles WAF s'appliquent-elles à tous les forfaits Cloudflare ?
Les règles WAF personnalisées sont disponibles sur tous les forfaits payants (Pro, Business, Enterprise). Les forfaits gratuits ont des règles WAF limitées. Cependant, Managed Challenge est disponible sur tous les forfaits, y compris Free.
Les règles WAF peuvent-elles déclencher différents défis pour différents chemins ?
Oui. Chaque règle WAF peut avoir une action différente et correspondre à des chemins différents. Un site peut utiliser Managed Challenge pour /login et JS Challenge pour les points de terminaison /api/.
À quelle fréquence les sites modifient-ils leurs règles WAF ?
Cela varie. Les sites de commerce électronique ajustent souvent les règles lors des événements de vente. Les sites soucieux de leur sécurité peuvent mettre à jour leurs règles chaque semaine. La plupart des sites modifient rarement les règles après la configuration initiale.
La résolution d’un défi WAF affecte-t-elle les demandes futures ?
Oui. Après résolution, le cookie cf_clearance laisse passer les requêtes suivantes sans contestation pendant environ 30 minutes. Le cookie est lié à votre adresse IP et à votre agent utilisateur.
Résumé
Les règles Cloudflare WAF déclenchent des défis CAPTCHA en fonction de conditions configurables : score du bot, pays, chemin, en-têtes ou taux. L'action la plus courante est le défi géré, que Cloudflare restitue de manière adaptative sous la forme d'un défi invisible, Turnstile ou JS. Résolvez-les avecCaptchaAIen utilisant la méthode turnstile ou cloudflare_challenge selon ce qui est rendu. Les blocs durs (403) des règles WAF ne peuvent pas être résolus : modifiez plutôt votre modèle de requête ou votre adresse IP.
Articles connexes
- Cloudflare Challenge vs détection de tourniquet
- Comment fonctionne Cloudflare Challenge
- Procédure pas à pas du flux de session Cloudflare Challenge