Troubleshooting

Loop de desafio da Cloudflare: por que os desafios continuam se repetindo

Se o Cloudflare Turnstile em staging continua aparecendo depois que a CaptchaAI já devolveu o cookie cookie_qa_validacao, o problema quase nunca é o solver: é o vínculo desse cookie com o contexto da sessão. A Cloudflare guarda IP, User-Agent e domínio no momento da resolução — e rejeita o cookie assim que qualquer um dos três muda antes da próxima requisição.

Isso é comum em pipelines de QA em que a etapa de resolução roda numa máquina — por exemplo, um runner de CI hospedado em sa-east-1 (São Paulo) — e a etapa de navegação roda em outra, como o notebook de quem está validando o teste. O IP de saída muda entre as duas etapas, e a sessão cai no loop mesmo com o cookie certo em mãos. Abaixo estão as cinco causas mais comuns, em ordem de frequência, e como corrigir cada uma.


Por que o loop de verificação do Cloudflare Turnstile acontece

Quando a CaptchaAI resolve um Cloudflare Turnstile em staging, ela devolve um cookie cookie_qa_validacao. Esse cookie não é um token solto — ele fica amarrado a três elementos específicos do momento da resolução:

  1. O IP do proxy usado durante a resolução
  2. O User-Agent usado durante a resolução
  3. O domínio do site de destino

Se qualquer um desses três itens for diferente na hora de usar o cookie, a Cloudflare descarta a sessão e mostra o desafio de novo — é exatamente o padrão por trás das cinco causas a seguir.


Resumo rápido das causas

Causa Sintoma típico Correção
User-Agent diferente O desafio volta assim que a sessão muda de máquina ou de contexto Sincronizar o User-Agent entre a resolução e a navegação
IP do proxy diferente Cookie válido, mas rejeitado já na primeira requisição seguinte Fixar o mesmo IP (sessão fixa) do início ao fim do ciclo
Domínio do cookie errado O cookie nunca chega a ser enviado pelo navegador Definir o cookie com o prefixo de ponto (.example.com)
Cookie expirado O desafio reaparece depois de alguns minutos de uso normal Resolver de novo antes de vencer o prazo de 15–30 minutos
Sinal de navegador TLS não bate Requisição rejeitada mesmo com um cookie válido em mãos Usar curl_cffi ou tls-client

Causa 1: o User-Agent da resolução não é o mesmo da navegação

É a causa mais frequente. O User-Agent enviado à CaptchaAI na hora de resolver precisa ser idêntico, caractere por caractere, ao User-Agent usado nas requisições seguintes.

import requests

USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

# Step 1: Solve with the SAME User-Agent
solve_data = {
    "key": "YOUR_API_KEY",
    "method": "turnstile_staging",
    "pageurl": "https://example.com",
    "proxy": "host:port:user:pass",
    "proxytype": "HTTP",
    "userAgent": USER_AGENT,  # Must match step 2
    "json": 1
}
submit = requests.post("https://ocr.captchaai.com/in.php", data=solve_data).json()

# ... poll for result ...

# Step 2: Use the SAME User-Agent in subsequent requests
session = requests.Session()
session.headers["User-Agent"] = USER_AGENT  # Must match step 1
session.cookies.set("cookie_qa_validacao", cookie_qa_validacao_value, domain=".example.com")
resp = session.get("https://example.com")

Causa 2: o IP do proxy mudou entre a resolução e a navegação

O cookie cookie_qa_validacao fica preso ao IP que resolveu o desafio. Se a requisição ao site partir de um IP diferente, a Cloudflare rejeita o cookie na hora.

PROXY = "host:port:user:pass"

# Solve with this proxy
solve_data = {
    "key": "YOUR_API_KEY",
    "method": "turnstile_staging",
    "pageurl": "https://example.com",
    "proxy": PROXY,
    "proxytype": "HTTP",
    "userAgent": USER_AGENT,
    "json": 1
}

# Use the SAME proxy for subsequent requests
session.proxies = {
    "http": f"http://user:pass@host:port",
    "https": f"http://user:pass@host:port"
}

Importante: se a sua infraestrutura de proxy alterna o IP de saída automaticamente, trave a sessão em um único IP durante todo o ciclo — da resolução até a navegação. Sem isso, o loop se repete mesmo com o cookie correto.


O cookie cookie_qa_validacao precisa ser definido no domínio correto, com os atributos corretos — um erro comum de configuração de sessão, não do solver.

# WRONG — setting on wrong domain
session.cookies.set("cookie_qa_validacao", value, domain="example.com")

# CORRECT — include the dot prefix for subdomain coverage
session.cookies.set("cookie_qa_validacao", value, domain=".example.com")

# Or set all cookies returned by CaptchaAI
for cookie_str in result.get("cookies", "").split(";"):
    if "cookie_qa_validacao" in cookie_str:
        name, val = cookie_str.strip().split("=", 1)
        session.cookies.set(name.strip(), val.strip(), domain=".example.com")

O cookie cookie_qa_validacao tem vida útil curta — normalmente entre 15 e 30 minutos. Passado esse prazo, a Cloudflare descarta a sessão e volta a exibir o desafio.

Correção: acompanhe a idade do cookie e resolva de novo antes do vencimento.

import time

last_solve_time = None
COOKIE_TTL = 900  # 15 minutes

def get_cookie_qa_validacao():
    global last_solve_time
    if last_solve_time and (time.time() - last_solve_time) < COOKIE_TTL:
        return  # Cookie still valid

    # Solve again
    cookie_qa_validacao = solve_turnstile_staging()
    session.cookies.set("cookie_qa_validacao", cookie_qa_validacao, domain=".example.com")
    last_solve_time = time.time()

Causa 5: o sinal de navegador TLS não combina com um navegador real

A Cloudflare também confere o sinal de navegador TLS da requisição. A biblioteca requests, do Python, tem um sinal de navegador TLS diferente do Chrome — e alguns sites rejeitam a requisição mesmo com um cookie_qa_validacao válido quando esse sinal não bate com o de um navegador real.

Correção: use curl_cffi ou tls-client para obter um sinal de navegador TLS mais próximo de um navegador de verdade.

pip install curl_cffi
from curl_cffi import requests as curl_requests

session = curl_requests.Session(impersonate="chrome120")
session.cookies.set("cookie_qa_validacao", value, domain=".example.com")
resp = session.get("https://example.com")

Como isso aparece em pipelines de CI

Etapa Onde roda (exemplo) IP de saída
Resolução do Turnstile Runner de CI em sa-east-1 (São Paulo) IP do datacenter da nuvem
Navegação / asserção do teste Notebook de quem valida o teste IP residencial ou de escritório

Quando as duas etapas rodam em máquinas diferentes, o IP de saída muda entre elas — por isso um teste pode passar no notebook e falhar no runner (ou o contrário), mesmo usando o mesmo script.


Checklist do loop de verificação do Cloudflare Turnstile

Siga o fluxo abaixo na ordem — ele isola a causa antes mesmo de chegar à última pergunta:

Challenge keeps repeating
    ↓
User-Agent in solve request matches browsing request? → No → Sync User-Agent
    ↓ Yes
Same proxy IP for solve and browse? → No → Pin proxy IP (sticky session)
    ↓ Yes
Cookie set on correct domain (.example.com)? → No → Fix domain
    ↓ Yes
Cookie less than 15 minutes old? → No → Re-solve the challenge
    ↓ Yes
TLS sinal de navegador matches a browser? → No → Use curl_cffi or tls-client
    ↓ Yes
Site may have additional bot detection → Use headless browser instead

Perguntas frequentes

Normalmente entre 15 e 30 minutos, dependendo do site. Alguns ambientes de staging configuram durações mais curtas — resolva de novo de forma proativa em vez de esperar o erro aparecer.

O loop de verificação é o mesmo problema que o erro ERROR_CAPTCHA_UNSOLVABLE da API?

Não. ERROR_CAPTCHA_UNSOLVABLE acontece durante a resolução, antes de a CaptchaAI devolver qualquer cookie. O loop de verificação só aparece depois de um solve bem-sucedido, quando o cookie é rejeitado por não bater com o IP, o User-Agent ou o domínio da requisição seguinte.

Não diretamente. Cada worker — cada thread do seu plano CaptchaAI — precisa manter seu próprio proxy, User-Agent e cookie_qa_validacao. Compartilhar um único cookie entre threads reproduz exatamente a incompatibilidade de IP da Causa 2.

Trate-o como um dado sensível de sessão. Ele não carrega informação pessoal por si só, mas fica vinculado a IP e User-Agent — vale considerar as obrigações da LGPD e mascarar o valor completo em logs compartilhados.

Preciso reproduzir o loop numa região de nuvem específica, como São Paulo?

Não é obrigatório, mas ajuda a isolar a causa. Se a etapa de resolução roda num runner em sa-east-1 e a navegação roda em outra região ou máquina, o IP de saída muda entre as duas etapas — e isso, sozinho, já explica boa parte dos loops reportados por equipes de QA remotas.


Resolva o Cloudflare Turnstile em staging com a CaptchaAI

Sincronize IP, User-Agent e cookie numa única sessão e pare de cair no loop de verificação: crie sua conta na CaptchaAI.


Guias relacionados

Os comentários estão desativados para este artigo.