Se um endpoint que sempre respondia com HTTP 403 e um CAPTCHA visível começa, do nada, a devolver 503 sem nenhum widget na tela, é bem provável que o site tenha trocado o Desafio Interativo pelo Desafio Gerenciado da Cloudflare. São as duas ações de desafio que qualquer regra de WAF da Cloudflare pode disparar — e a diferença entre elas decide se a sua automação recebe um turnstile para resolver ou passa direto sem fazer nada.
O Desafio Gerenciado é a opção adaptativa: a Cloudflare avalia cada visitante e decide, caso a caso, entre deixar passar, mostrar um Turnstile leve ou exigir um desafio JavaScript completo. O Desafio Interativo é a opção legada — sempre mostra um CAPTCHA, para todo mundo, sem exceção. Este guia mostra como reconhecer cada um pelo código HTTP e pelo HTML da página, e qual método da CaptchaAI usar em cada caso.
Gerenciado x Interativo: a diferença em uma tabela
| Aspecto | Desafio Gerenciado | Desafio Interativo |
|---|---|---|
| Chegou em | 2021 | Legado (anterior a 2021) |
| É adaptativo? | Sim — a Cloudflare decide por visitante | Não — sempre interativo |
| Passagem invisível? | Sim (~90% dos visitantes passam sem ver nada) | Não (CAPTCHA sempre visível) |
| Desafios que pode usar | Invisível → Cloudflare Turnstile → desafio JS | CAPTCHA sempre visível |
| Recomendado pela Cloudflare? | Sim (padrão para regras novas) | Não (mantido por compatibilidade) |
| Fricção para o usuário | Baixa (a maioria nem percebe) | Alta (interação obrigatória) |
| Código HTTP | 503 | 403 |
| Método na CaptchaAI | turnstile ou turnstile_staging |
turnstile |
Como funciona o Desafio Gerenciado
O Desafio Gerenciado é a ação recomendada pela própria Cloudflare. Ele usa um mecanismo de decisão para aplicar o desafio menos invasivo possível a cada visitante:
Fluxo de decisão
WAF rule triggers Managed Challenge
↓
Cloudflare evaluates visitor signals:
├─ Browser sinal de navegador quality
├─ IP reputation score
├─ TLS sinal de navegador (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
↓
cookie_qa_validacao cookie issued
O que o visitante vê
O que aparece na tela depende só do risco calculado para aquele visitante:
- Navegador comum, IP com boa reputação — nada acontece, passagem invisível (~90% dos casos).
- Navegador novo, IP neutro — um spinner rápido aparece e some (~5%).
- Sinais suspeitos — checkbox do Turnstile precisa ser marcado (~4%).
- Sinais de alto risco — página "Verificando seu navegador..." com espera de alguns segundos (~1%).
Saída em HTML
As páginas de Desafio Gerenciado usam a plataforma de desafio da 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>
Como funciona o Desafio Interativo (o modelo legado)
O Desafio Interativo sempre mostra um CAPTCHA visível que o visitante precisa resolver manualmente. Não existe passagem invisível: todo visitante vê e precisa concluir o desafio.
Como funciona
WAF rule triggers Interactive Challenge
↓
Full-page CAPTCHA served (HTTP 403)
↓
Visitor must interact with CAPTCHA widget
↓
CAPTCHA solved
↓
cookie_qa_validacao cookie issued
O que o visitante vê
Todo visitante recebe uma página inteira de desafio com um widget parecido com o 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>
Por que a Cloudflare desaconselha o uso
O próprio fornecedor lista o Desafio Interativo como opção de última instância, pelos motivos abaixo:
- Sempre visível — 100% dos visitantes veem o desafio, sem exceção.
- Mais fricção — todo mundo precisa interagir, mesmo quem já é conhecido do site.
- Mais abandono — parte dos visitantes sai em vez de completar o CAPTCHA.
- Sem adaptação a risco — visitantes de baixo risco são desafiados do mesmo jeito que os suspeitos.
- Questões de acessibilidade — a interação manual é obrigatória para todo mundo, sem alternativa.
Detecção: qual desafio essa página está usando?
Antes de decidir qual método da CaptchaAI chamar, o código precisa identificar o tipo de desafio pelo código HTTP e pelo HTML retornado:
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"] = "turnstile_staging"
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']}")
Como ler os sinais
Cruzando código HTTP e HTML, dá para separar os quatro casos sem ambiguidade:
- Código HTTP — 503 no Gerenciado e no IUAM; 403 no Interativo e no bloqueio de WAF.
challenge-platformno HTML — presente no Gerenciado e no Interativo; ausente no IUAM e no bloqueio.- Caminho
managedno script — só aparece no Gerenciado. jschlno HTML — só aparece no IUAM, o desafio JS legado.- Widget sempre visível — só no Interativo.
- Passagem invisível possível — só no Gerenciado.
Checklist antes de automatizar
- Confirme se a página é um interstitial de desafio completo ou se o widget aparece embutido no fluxo normal do app.
- Procure marcadores como
cf-chl, contêineres do Turnstile e qualquer callback de retorno antes de decidir o caminho de tratamento. - Registre o resultado da detecção com a URL e o proxy usados — ajuda a perceber rápido quando o alvo muda de comportamento. Log com dados de visitantes reais? Considere a LGPD (ou o RGPD, em Portugal).
Como resolver cada tipo de desafio
Resolvendo o Desafio Gerenciado
Na maioria dos casos, o Desafio Gerenciado renderiza como um widget Turnstile. Use o método turnstile da CaptchaAI:
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 turnstile_staging 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 turnstile_staging method."""
submit = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "turnstile_staging",
"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")
Resolvendo o Desafio Interativo
O Desafio Interativo sempre mostra um widget visível. O método é o mesmo turnstile:
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")
Node.js (os dois tipos)
const axios = require("axios");
const API_KEY = "YOUR_API_KEY";
async function solveCloudflareChallenge(url, type = "managed") {
const method = type === "js_challenge" ? "turnstile_staging" : "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;
}
}
Com workers na região sa-east-1 da AWS (São Paulo), a passagem invisível do Gerenciado não adiciona latência perceptível. Já uma resolução via CaptchaAI soma o round-trip até o endpoint ao tempo de resolução do Turnstile — meça no seu ambiente antes de fixar um timeout curto no polling do res.php.
Sintomas e correções rápidas
Um guia rápido para o que cada combinação de código HTTP e HTML costuma significar:
- 503 sem nenhum widget visível → o Desafio Gerenciado passou você de forma invisível; nenhuma ação necessária, a requisição já foi aprovada.
- 503 com "Verificando seu navegador" → o Gerenciado foi elevado a desafio JS; use o método
turnstile_staging. - 403 com CAPTCHA visível → é o Desafio Interativo (legado); use o método
turnstile. - 403 sem nenhum desafio → bloqueio de WAF, não é um desafio solucionável; troque o IP ou o padrão de requisição.
- O tipo de desafio muda sem padrão aparente → o Desafio Gerenciado está reagindo aos sinais do visitante; trate tanto Turnstile quanto desafio JS no código.
- cookie_qa_validacao de um tipo rejeitado pelo outro → são fluxos de desafio diferentes no mesmo domínio; resolva o desafio que for apresentado, seja qual for.
Depois de cobrir esses seis sintomas, o que sobra quase sempre é migração de configuração — é o que a seção seguinte resume.
O que muda quando o site migra para o Gerenciado
A Cloudflare recomenda migrar do Desafio Interativo para o Desafio Gerenciado. Se um site que você automatiza fizer essa troca, cinco coisas mudam no seu código:
- Interativo → Gerenciado: a automação pode começar a passar de forma invisível (~90% de chance).
- HTTP 403 → 503: atualize a verificação de código de status.
- Sempre visível → adaptativo: o widget Turnstile pode simplesmente não aparecer no HTML.
- Mesma sitekey: o código de resolução na CaptchaAI continua igual.
- Mesma saída cookie_qa_validacao: o tratamento do cookie não muda.
Perguntas frequentes
- Como sei se um site trocou o Desafio Interativo pelo Gerenciado? Compare o código HTTP: 403 com CAPTCHA sempre visível é Interativo; 503 — às vezes sem nenhum widget na tela — é Gerenciado. O script de detecção deste guia automatiza essa checagem.
- Preciso mudar meu código quando a resposta passa de 403 para 503? Sim. Atualize a verificação de status e trate o caso em que o Gerenciado passa o visitante de forma invisível — a resposta chega como 200 normal, sem CAPTCHA para resolver.
- O Desafio Gerenciado também gera o cookie_qa_validacao? Sim. Os dois tipos produzem o mesmo cookie
cookie_qa_validacao, e o tratamento no código é idêntico, não importa qual desafio foi apresentado. - Preciso de um plano específico da CaptchaAI para resolver os dois tipos? Não. Os dois usam o método
turnstile(outurnstile_stagingpara o desafio JS), disponível em qualquer plano — do BASIC (US$ 15/mês, 5 threads) ao VIP-3. O que muda entre os planos é o número de threads simultâneas, não os desafios que você consegue resolver. - O Desafio Interativo vai ser desativado? A Cloudflare não anunciou data oficial, mas recomenda o Gerenciado para toda regra nova. O Interativo segue ativo para compatibilidade — sites migram quando quiserem.
Resumo
O Desafio Gerenciado da Cloudflare ajusta a dificuldade por visitante — de passagem invisível a desafio JavaScript completo —, enquanto o Desafio Interativo sempre exibe um CAPTCHA visível, sem exceção. Os dois produzem o mesmo cookie cookie_qa_validacao e são resolvidos com a CaptchaAI — turnstile cobre a maior parte dos casos, e turnstile_staging entra para páginas de desafio JavaScript. Na dúvida sobre qual regra o site está usando, o código HTTP (503 ou 403) já responde a maior parte da pergunta.