O Cloudflare Turnstile dá cerca de 300 segundos entre gerar o token e recusá-lo. Se uma automação funciona em testes e falha em produção sem motivo aparente, o relógio é o culpado. Veja onde essa corrida contra o tempo se perde e como resolver o Turnstile no momento certo com a CaptchaAI.
Quanto tempo um token Turnstile continua válido
O token do Turnstile expira aproximadamente 300 segundos (5 minutos) depois de criado — mais folgado que os ~120 segundos do reCAPTCHA, mas ainda curto o suficiente para gerar condições de corrida. Para comparar:
- reCAPTCHA v2/v3: ~120 segundos.
- Cloudflare Turnstile: ~300 segundos.
- hCaptcha: ~120 segundos.
O cronômetro começa quando a Cloudflare gera o token — não quando a CaptchaAI devolve o resultado, nem quando seu código o recebe.
Por que a corrida contra o tempo acontece
A linha do tempo abaixo mostra um fluxo típico de resolução via API:
Time 0:00 — You submit a Turnstile task to CaptchaAI
Time 0:15 — CaptchaAI begins solving
Time 0:20 — Token is generated (timer starts here)
Time 0:25 — CaptchaAI returns token to you
Time 0:25+ — Your code processes the token
Time ??? — Your code submits the token to the site
A contagem começa em 0:20; você tem até por volta de 5:20 para enviar o token. Parece bastante, até somar cada etapa de um fluxo real:
Time 0:20 — Token generated
Time 0:25 — Received by your code
Time 0:30 — Fill form fields
Time 0:35 — Navigate to next page
Time 1:00 — Handle additional dialogs
Time 2:00 — Wait for page load
Time 4:00 — Network latency spike
Time 5:30 — Submit token → EXPIRED
Cada passo é rápido; a soma é que estoura os 300 segundos. Regra prática de bolso:
- Receba o token e envie-o em segundos, não em minutos.
- Qualquer coisa acima de 240 s de intervalo já é risco de rejeição.
Situações que mais derrubam o token antes da hora
Três padrões respondem pela maioria dos casos de token expirado em produção:
1. Formulários com várias etapas
Fluxos com várias telas antes da confirmação final são o cenário mais comum:
Step 1: Fill personal info → Step 2: Fill address →
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit
Se o CAPTCHA é resolvido na Etapa 3, mas o envio só acontece na Etapa 5, o intervalo pode passar de 5 minutos — comum em cadastros e checkouts com revisão manual.
2. Filas de processamento em lote
Resolver vários tokens de uma vez e guardá-los é o segundo padrão mais comum:
# DON'T: Solve all tokens first, then use them
tokens = []
for url in urls:
tokens.append(solve_turnstile(url)) # Tokens age while waiting
for url, token in zip(urls, tokens):
submit_form(url, token) # Early tokens may be expired
Os primeiros tokens envelhecem enquanto os últimos ainda são resolvidos.
3. Nova tentativa com o mesmo token
O terceiro padrão aparece em retries mal planejados:
token = solve_turnstile(site_key, page_url)
for attempt in range(3):
result = submit_form(page_url, token)
if result.ok:
break
# BUG: Retrying with the same token — it may be expired OR already consumed
Reenviar o mesmo token raramente funciona: pode estar vencido ou já consumido.
Como evitar a expiração do token
Estratégia 1: resolver just-in-time
Peça o token só quando o fluxo estiver pronto para enviá-lo:
import requests
import time
def solve_turnstile(site_key, page_url):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": "YOUR_API_KEY",
"method": "turnstile",
"sitekey": site_key,
"pageurl": page_url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": "YOUR_API_KEY",
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return data["request"]
raise TimeoutError("Solve timed out")
# Complete all form steps FIRST
fill_personal_info()
fill_address()
navigate_to_review()
# THEN solve and submit immediately
token = solve_turnstile(site_key, page_url)
submit_form(token) # Submit within seconds of receiving the token
Exemplo prático: uma equipe de QA autorizado com workers na região
sa-east-1(São Paulo) reduziu as falhas só ao mover a resolução do Turnstile para o último passo do fluxo.
Estratégia 2: acompanhar a idade do token
Guarde o horário de criação e verifique a validade antes de cada envio:
import time
class TimedToken:
def __init__(self, token, created_at=None):
self.token = token
self.created_at = created_at or time.time()
self.max_age = 270 # 4.5 min — safety margin from 5 min limit
@property
def is_valid(self):
return (time.time() - self.created_at) < self.max_age
@property
def remaining_seconds(self):
return max(0, self.max_age - (time.time() - self.created_at))
# Usage
timed_token = TimedToken(solve_turnstile(site_key, page_url))
# Check before using
if timed_token.is_valid:
submit_form(timed_token.token)
else:
# Solve a fresh token
timed_token = TimedToken(solve_turnstile(site_key, page_url))
submit_form(timed_token.token)
Estratégia 3: token novo a cada nova tentativa (JavaScript)
Em vez de reenviar o mesmo token no retry, resolva um novo a cada tentativa:
async function submitWithFreshToken(siteKey, pageUrl, formData) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
// Always solve a fresh token for each attempt
const token = await solveTurnstile(siteKey, pageUrl);
const response = await fetch(pageUrl, {
method: 'POST',
body: JSON.stringify({ ...formData, 'cf-turnstile-response': token }),
headers: { 'Content-Type': 'application/json' }
});
if (response.ok) return await response.json();
console.log(`Attempt ${attempt + 1} failed, solving fresh token...`);
}
throw new Error('All attempts failed');
}
Como reconhecer um token expirado
O site raramente exibe a mensagem "token expirado". Estes sinais costumam indicar isso:
- HTTP 403 depois de enviar o token — token inválido ou vencido.
- Redirecionamento de volta para o formulário — falha na verificação do token.
- Mensagem genérica "falha na verificação" — pode ser expiração, mas não é exclusivo disso.
- A página do desafio reaparece — token rejeitado; a Cloudflare desafia de novo.
Registro para diagnóstico
Registrar os horários de criação e de envio facilita a investigação:
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("turnstile")
token_received_at = time.time()
token = solve_turnstile(site_key, page_url)
logger.info(f"Token received, length: {len(token)}")
# ... workflow steps ...
submit_time = time.time()
age = submit_time - token_received_at
logger.info(f"Submitting token, age: {age:.1f}s")
if age > 270:
logger.warning(f"Token may be expired (age: {age:.1f}s > 270s safety limit)")
Atualização automática do widget no navegador
Em fluxos no navegador, o widget do Turnstile renova o token sozinho antes de expirar, disparando data-expired-callback:
turnstile.render('#captcha', {
sitekey: '0x4AAAA...',
callback: (token) => {
console.log('New token:', token);
},
'expired-callback': () => {
console.log('Token expired — widget will auto-refresh');
}
});
Em automações via API, sem navegador, essa renovação não existe: controlar a idade do token é tarefa do seu código.
Diagnóstico rápido: sintoma, causa e correção
- Funciona em testes, falha em produção — causa: fluxo de produção mais lento. Correção: resolver just-in-time, nunca com antecedência.
- Primeiro envio funciona, novas tentativas falham — causa: reenvio de token já consumido. Correção: resolver um token novo a cada tentativa.
- Falhas intermitentes em formulários longos — causa: token expira durante o fluxo. Correção: mover a resolução do CAPTCHA para a última etapa.
- Lote com alta taxa de falha — causa: tokens resolvidos em massa expiram antes de usados. Correção: resolver sob demanda, nunca em lote.
Perguntas frequentes
É possível aumentar a validade de um token Turnstile?
Não. O prazo é definido pela Cloudflare. Resolva um token novo quando o atual vencer.
Por que o token funciona nos testes, mas falha em produção?
Porque produção costuma ser mais lenta — fila, terceiros na página, picos de latência — e o token passa dos 300 segundos.
Meu formulário tem várias etapas — em qual delas devo resolver o CAPTCHA?
Na etapa mais próxima do envio final. Resolver o Turnstile logo no começo é o erro mais comum por trás de tokens expirados.
O widget do Turnstile também expira sozinho no navegador?
Sim, mas o próprio widget renova o token antes do vencimento. A expiração é praticamente exclusiva de integrações via API.
Artigos relacionados
- Cloudflare Challenge vs. Turnstile: como diferenciar em staging
- GeeTest comparado ao Cloudflare Turnstile
- Corrigindo o erro 403 depois do token do Turnstile
Próximas etapas
Elimine tokens expirados do seu fluxo — obtenha sua chave de API da CaptchaAI e aplique a resolução just-in-time deste guia.