Um token Turnstile que funciona em testes falha na produção. A causa: expiração do token. Os tokens da catraca têm vida útil limitada e, se o seu fluxo de trabalho demorar muito entre o recebimento do token e o envio, o site o rejeitará. Veja como lidar com o tempo corretamente.
Vida útil do token
Os tokens da catraca expiram aproximadamente 300 segundos (5 minutos) após a criação. Isso é mais generoso do que os aproximadamente 120 segundos do reCAPTCHA, mas ainda surgem condições de corrida em fluxos de trabalho complexos.
| Tipo CAPTCHA | Vida útil do token |
|---|---|
| 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 CaptchaAI o retorna para você e não quando você o recebe em seu código.
A condição da corrida
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
O relógio está contando a partir de 0:20. Você tem até aproximadamente 5h20 para enviar o token. Isso parece generoso, mas considere o que acontece em um fluxo de trabalho 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
Cenários comuns de condições de corrida
1. Formulários de várias etapas
Formulários que requerem várias páginas antes do envio final:
Step 1: Fill personal info → Step 2: Fill address →
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit
Se o CAPTCHA estiver na Etapa 3, mas o envio ocorrer na Etapa 5, o atraso entre a resolução e o envio poderá exceder 5 minutos.
2. Filas de processamento em lote
Resolvendo tokens antecipadamente e usando-os posteriormente:
# 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
3. Tentar novamente loops com tokens antigos
Reutilizando um token após um envio com falha:
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
Prevenindo a Expiração
Estratégia 1: Resolver Just-in-Time
Solicite o token somente quando estiver pronto para enviar:
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
Estratégia 2: Rastrear a Idade do Token
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: novo token na nova tentativa (JavaScript)
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');
}
Detectando tokens expirados
O site normalmente não informa explicitamente "token expirado". Procure estes sinais:
| Sinal | Indicação |
|---|---|
| HTTP 403 após enviar token | Token inválido ou expirado |
| Redirecionar de volta para a página do formulário | Falha na verificação do token |
| Mensagem de erro: "falha na verificação" | Falha genérica – pode ser expiração |
| A página do desafio reaparece | Token rejeitado, Cloudflare desafia novamente |
Registro para diagnóstico
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)")
Comportamento de atualização automática do Turnstile
Em fluxos baseados em navegador, os widgets Turnstile atualizam automaticamente os tokens antes que expirem. O data-expired-callback é acionado quando um token expira:
turnstile.render('#captcha', {
sitekey: '0x4AAAA...',
callback: (token) => {
console.log('New token:', token);
},
'expired-callback': () => {
console.log('Token expired — widget will auto-refresh');
}
});
Na automação somente API (sem navegador), você não se beneficia da atualização automática. Você mesmo deve gerenciar a atualização do token.
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| O token funciona em testes, mas não em produção | O fluxo de trabalho de produção é mais lento | Resolva just-in-time, não antecipadamente |
| O primeiro envio foi bem-sucedido, as novas tentativas falharam | Reutilizando tokens consumidos | Resolva um novo token para cada tentativa |
| Falhas intermitentes em formulários longos | O token expira durante o fluxo de várias etapas | Mova a resolução CAPTCHA para a última etapa |
| Trabalhos em lote têm alta taxa de falhas | Os tokens resolvidos em massa expiram antes do uso | Resolva tokens sob demanda, não em lotes |
Perguntas frequentes
Posso estender a vida útil de um token Turnstile?
Não. A validade é definida pela Cloudflare e não pode ser modificada. Sua única opção é resolver um novo token.
Quão exato é o limite de 300 segundos?
É aproximado. A Cloudflare pode ajustar o tempo com base na configuração. Use 270 segundos (4,5 minutos) como máximo prático para uma margem de segurança.
Devo validação antecipada em staging os tokens para economizar tempo?
Somente se o seu fluxo de trabalho puder usá-los em alguns minutos. Para processamento em lote, resolva tokens sob demanda, e não antecipadamente.
Artigos relacionados
- Cloudflare Turnstile em staging vs detecção de catraca
- Comparação de Geetest vs Cloudflare Turnstile
- Cloudflare Turnstile 403 Após correção do token
Próximas etapas
Impedir a expiração do token Turnstile —obtenha sua chave API CaptchaAIe implementar soluções just-in-time com taxa de sucesso de 100%.