Le statut HTTP renvoyé par la page vous dit presque tout : un 503 pointe vers un Managed Challenge, un 403 vers un Interactive Challenge. Ce sont les deux actions de défi que Cloudflare expose dans les règles WAF, et elles se pilotent différemment. Le Managed Challenge est l'option moderne et adaptative — Cloudflare choisit la difficulté visiteur par visiteur, et environ 90 % des requêtes légitimes passent sans rien afficher. L'Interactive Challenge est l'option héritée : il montre toujours un CAPTCHA visible. Savoir lequel vous avez en face détermine la méthode CaptchaAI à appeler — turnstile ou cloudflare_challenge.
En pratique, deux réflexes suffisent pour démarrer :
503→ Managed Challenge → méthodeturnstile(oucloudflare_challengequand aucun widget n'apparaît).403→ Interactive Challenge → méthodeturnstile.
Comparaison rapide : Managed vs Interactive Challenge
| Caractéristique | Managed Challenge | Interactive Challenge |
|---|---|---|
| Année d'apparition | 2021 | Hérité (avant 2021) |
| Adaptatif ? | Oui — Cloudflare décide visiteur par visiteur | Non — toujours interactif |
| Passage invisible possible ? | Oui (~90 % des visiteurs passent sans widget) | Non — affiche toujours un CAPTCHA |
| Types de défis mobilisés | Invisible → Turnstile → défi JS | CAPTCHA toujours visible |
| Recommandé par Cloudflare ? | Oui — défaut des nouvelles règles | Non — conservé pour la rétrocompatibilité |
| Friction utilisateur | Faible — la plupart ne voient rien | Élevée — interaction systématique |
| Statut HTTP | 503 | 403 |
| Méthode CaptchaAI | turnstile ou cloudflare_challenge |
turnstile |
Reconnaître le défi au premier coup d'œil
Quelques signaux permettent de deviner le type avant même de lire le HTML.
| Signal observé | Plutôt Managed Challenge | Plutôt Interactive Challenge |
|---|---|---|
| Expérience utilisateur | Une partie des visiteurs passe sans voir de widget | Chaque visiteur voit un défi explicite |
| Type de page | Page de vérification adaptative ou widget Turnstile contextuel | Page de défi pleine page avec interaction obligatoire |
| Code HTTP | Souvent 503 ou flux intermédiaire |
Souvent 403 avec défi visible |
| Logique à coder | Gérer parfois un passage invisible ou un défi non interactif | Résoudre presque toujours un widget visible |
Managed Challenge : le défi adaptatif moderne
Le Managed Challenge est l'action de défi que Cloudflare recommande. Plutôt que d'imposer une épreuve à tout le monde, il évalue chaque visiteur et présente le défi le moins gênant possible — souvent aucun.
Le flux de décision de Cloudflare
Cloudflare combine plusieurs signaux avant de choisir le niveau de défi :
WAF rule triggers Managed Challenge
↓
Cloudflare evaluates visitor signals:
├─ Browser fingerprint quality
├─ IP reputation score
├─ TLS fingerprint (JA3/JA4)
├─ Request history
├─ Behavioral signals
└─ Device capabilities
↓
Risk assessment → Challenge level selected:
├─ LOW risk → Invisible pass (no visible UI)
├─ MEDIUM risk → Non-interactive Turnstile (background PoW)
├─ HIGH risk → Interactive Turnstile (checkbox/widget)
└─ VERY HIGH risk → JavaScript challenge page (5s wait)
↓
Challenge completed
↓
cf_clearance cookie issued
Ce que voient réellement les visiteurs
La difficulté suit le profil de risque estimé ; dans la grande majorité des cas, rien ne s'affiche.
- Navigateur classique, bonne IP : rien du tout, passage invisible (~90 % des visiteurs).
- Nouveau navigateur, IP neutre : un bref indicateur de chargement (~5 %).
- Signaux suspects : une case à cocher Turnstile (~4 %).
- Signaux à haut risque : la page « Checking your browser… » (~1 %).
À quoi ressemble le HTML
Quand il devient visible, le défi s'appuie sur la plateforme de Cloudflare :
<!-- Managed Challenge page (when visible) -->
<body>
<div id="challenge-stage">
<div id="challenge-body-text">
Verifying you are human. This may take a few seconds.
</div>
<!-- Turnstile widget (when rendered) -->
<div class="cf-turnstile"
data-sitekey="0x4AAAAAAAC3DHQhMMQ_Rxrg">
</div>
</div>
<!-- Challenge platform script -->
<script src="/cdn-cgi/challenge-platform/h/g/orchestrate/managed/v1?ray=...">
</script>
</body>
Interactive Challenge : le défi hérité toujours visible
L'Interactive Challenge montre toujours un CAPTCHA visible : aucun passage invisible, chaque visiteur doit le résoudre pour continuer.
Le déroulé côté visiteur
WAF rule triggers Interactive Challenge
↓
Full-page CAPTCHA served (HTTP 403)
↓
Visitor must interact with CAPTCHA widget
↓
CAPTCHA solved
↓
cf_clearance cookie issued
Le HTML de la page
Chaque visiteur reçoit une page complète avec un widget de type Turnstile :
<!-- Interactive Challenge page -->
<body>
<div id="challenge-running">
<div class="main-wrapper">
<h2>Please verify you are human</h2>
<!-- Always-visible challenge widget -->
<div class="challenge-widget">
<!-- Checkbox + verification -->
</div>
</div>
</div>
</body>
Pourquoi Cloudflare le déconseille
- Toujours visible : tous les visiteurs voient le défi, sans exception.
- Friction accrue : chaque visiteur doit interagir avant de continuer.
- Taux de rebond plus élevé : une partie des utilisateurs abandonnent au lieu de terminer.
- Aucune adaptation au risque : même les visiteurs de confiance sont défiés.
- Accessibilité : l'interaction est imposée à tout le monde.
Migration d'Interactive vers Managed
Cloudflare pousse à migrer d'Interactive vers Managed. Si un site que vous automatisez bascule, voici ce qui change :
| Changement observé | Effet sur votre automatisation |
|---|---|
| Interactive → Managed | Peut se mettre à passer sans défi visible (~90 % des cas) |
| HTTP 403 → 503 | Mettez à jour vos contrôles de code de statut |
| Toujours visible → adaptatif | Le widget peut ne plus figurer dans le HTML |
| Même sitekey | Votre code de résolution CaptchaAI reste identique |
| Même sortie cf_clearance | La gestion du cookie ne change pas |
Scénario concret : un portail passe de 403 à 503
Une équipe QA à Lyon surveille chaque nuit la disponibilité d'un espace partenaire hébergé derrière Cloudflare, avec des workers sur Scaleway (région Paris). Pendant des mois, le portail renvoie un 403 avec widget visible : un Interactive Challenge, résolu via turnstile. Un matin, les logs montrent des 503 et le widget a disparu. Rien n'est cassé : l'opérateur a migré vers un Managed Challenge, et une bonne partie des requêtes passe désormais sans défi visible.
Le bon réflexe : ne traitez pas le 503 comme une erreur. Vérifiez d'abord si la réponse contient déjà le contenu attendu (passage invisible), et ne relancez une résolution que si une page de vérification s'affiche. Côté conformité, limitez la journalisation aux métadonnées techniques utiles (statut, cf-ray, horodatage) : un réflexe RGPD sain en Europe.
Identifier le défi rencontré par le code
Pour trancher automatiquement le type avant de lancer une résolution, le statut HTTP et quelques marqueurs dans le HTML suffisent le plus souvent :
import requests
import re
def identify_challenge_type(url):
"""Determine if a URL uses Managed or Interactive Challenge."""
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)
html = response.text
status = response.status_code
result = {
"url": url,
"status": status,
"challenge_type": None,
"cf_ray": response.headers.get("cf-ray", ""),
"solve_method": None,
}
if status == 200:
# Check for inline Turnstile widget (not a challenge page)
if "cf-turnstile" in html:
result["challenge_type"] = "turnstile_widget"
result["solve_method"] = "turnstile"
else:
result["challenge_type"] = "none"
return result
if status == 503:
# 503 indicates Managed Challenge or IUAM
if "managed" in html or "challenge-platform" in html:
result["challenge_type"] = "managed_challenge"
result["solve_method"] = "turnstile" # Managed renders as Turnstile
elif "jschl" in html:
result["challenge_type"] = "iuam_js_challenge"
result["solve_method"] = "cloudflare_challenge"
else:
result["challenge_type"] = "unknown_503"
return result
if status == 403:
if "challenge" in html.lower():
result["challenge_type"] = "interactive_challenge"
result["solve_method"] = "turnstile"
else:
result["challenge_type"] = "waf_block"
result["solve_method"] = None # Hard block, not solvable
return result
return result
# Usage
info = identify_challenge_type("https://protected-site.com/login")
print(f"Challenge: {info['challenge_type']}")
print(f"Solve with: {info['solve_method']}")
Table de signaux de détection
| Signal | Managed Challenge | Interactive Challenge | IUAM | Blocage WAF |
|---|---|---|---|---|
| Statut HTTP | 503 | 403 | 503 | 403 |
challenge-platform dans le HTML |
✅ | ✅ | ❌ | ❌ |
Chemin managed dans le script |
✅ | ❌ | ❌ | ❌ |
jschl dans le HTML |
❌ | ❌ | ✅ | ❌ |
| Widget toujours affiché | ❌ | ✅ | ❌ | ❌ |
| Passage invisible possible | ✅ | ❌ | ❌ | ❌ |
Dépannage
Ces symptômes se lisent d'abord au statut HTTP, puis au contenu de la page ; le tableau relie chaque cas à la méthode à appeler juste après.
| Symptôme | Cause probable | Correctif |
|---|---|---|
| 503 sans widget visible | Managed Challenge passé sans défi visible | Aucune action : la requête est passée |
| 503 avec « Checking your browser » | Managed élevé en défi JavaScript | Utilisez la méthode cloudflare_challenge |
| 403 avec CAPTCHA visible | Interactive Challenge (hérité) | Utilisez la méthode turnstile |
| 403 sans défi | Blocage WAF, pas un défi | Changez d'IP ou de schéma de requêtes |
| Le type de défi varie aléatoirement | Managed Challenge s'adapte aux signaux | Gérez à la fois Turnstile et défi JS |
| cf_clearance d'un type refusé pour un autre | Flux de défis distincts sur le même domaine | Résolvez le défi effectivement présenté |
Résoudre chaque type avec CaptchaAI
Une fois le type identifié, la résolution passe par l'API CaptchaAI : vous soumettez la tâche sur in.php, puis vous interrogez le résultat sur res.php jusqu'à récupérer le token.
Résoudre un Managed Challenge
Les Managed Challenges s'affichent le plus souvent comme des widgets Turnstile. Utilisez turnstile ; sans widget, basculez sur cloudflare_challenge :
import requests
import time
API_KEY = "YOUR_API_KEY"
def solve_managed_challenge(url, sitekey=None):
"""Solve Cloudflare Managed Challenge."""
# If sitekey not provided, extract from page
if not sitekey:
import re
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/120.0.0.0",
}
page = requests.get(url, headers=headers, timeout=15)
match = re.search(
r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', page.text
)
sitekey = match.group(1) if match else None
if not sitekey:
# No visible Turnstile — try cloudflare_challenge method
return solve_js_challenge(url)
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"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("Solve timed out")
def solve_js_challenge(url):
"""Fallback to cloudflare_challenge method."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "cloudflare_challenge",
"sitekey": "managed",
"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("Solve timed out")
Résoudre un Interactive Challenge
L'Interactive Challenge expose toujours un widget visible. La même méthode turnstile s'applique :
def solve_interactive_challenge(url, sitekey):
"""Solve Cloudflare Interactive Challenge (legacy)."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile",
"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("Solve timed out")
En Node.js pour les deux types
En Node.js, la logique tient dans une fonction qui choisit la méthode selon le type :
const axios = require("axios");
const API_KEY = "YOUR_API_KEY";
async function solveCloudflareChallenge(url, type = "managed") {
const method = type === "js_challenge" ? "cloudflare_challenge" : "turnstile";
const sitekey =
type === "js_challenge" ? "managed" : await extractSitekey(url);
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: {
key: API_KEY,
method,
sitekey: sitekey || "managed",
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("Solve timed out");
}
async function extractSitekey(url) {
try {
const response = await axios.get(url, {
headers: { "User-Agent": "Mozilla/5.0 Chrome/120.0.0.0" },
validateStatus: () => true,
});
const match = response.data.match(
/data-sitekey=["']([0-9x][A-Za-z0-9_-]+)["']/
);
return match ? match[1] : null;
} catch {
return null;
}
}
Questions fréquentes
CaptchaAI peut-il résoudre un Managed Challenge sans widget Turnstile visible ?
Oui, dans la plupart des cas. Sans widget dans le HTML, basculez sur cloudflare_challenge avec sitekey réglé sur managed : c'est le chemin prévu pour les pages de défi JavaScript (503 « Checking your browser »). Avec un data-sitekey présent, restez sur turnstile.
Dois-je changer mon code après une migration Interactive → Managed ?
Non, votre code de résolution reste identique. La méthode turnstile, le sitekey et la gestion du cookie cf_clearance ne changent pas. Adaptez seulement vos contrôles de statut HTTP : le code passe généralement de 403 à 503, et le widget peut disparaître du HTML.
Quels défis Cloudflare CaptchaAI prend-il en charge ?
CaptchaAI prend en charge Cloudflare Turnstile et Cloudflare Challenge, via les méthodes turnstile et cloudflare_challenge. Ces deux méthodes couvrent l'essentiel des Managed et Interactive Challenges. hCaptcha et FunCaptcha, en revanche, ne sont pas pris en charge.
En résumé
Le Managed Challenge choisit la difficulté visiteur par visiteur — de l'invisible au défi JavaScript complet — tandis que l'Interactive Challenge affiche systématiquement un CAPTCHA. Les deux produisent le même cookie cf_clearance et se résolvent avec CaptchaAI : turnstile pour la majorité des cas, cloudflare_challenge pour les pages de défi JavaScript. Le Managed Challenge est le défaut moderne ; l'Interactive Challenge relève de l'héritage.