Résolution de Problèmes

Calendrier d’expiration du jeton Cloudflare Turnstile et conditions de course

Un jeton Turnstile qui fonctionne lors des tests échoue en production. La cause : l’expiration du jeton. Les jetons Turnstile ont une durée de vie limitée, et si votre flux de travail prend trop de temps entre la réception du jeton et sa soumission, le site le rejette. Voici comment gérer correctement le timing.

Durée de vie du jeton

Les jetons tourniquet expirent environ 300 secondes (5 minutes) après leur création. C'est plus généreux que les ~120 secondes de reCAPTCHA, mais des conditions de concurrence surviennent toujours dans les flux de travail complexes.

Type CAPTCHA Durée de vie du jeton
reCAPTCHA v2/v3 ~120 secondes
Cloudflare Turnstile ~300 secondes
hCaptcha ~120 secondes

Le minuteur démarre lorsque Cloudflare génère le jeton, pas lorsque CaptchaAI vous le renvoie, ni lorsque vous le recevez dans votre code.

La condition de course

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

L'horloge tourne à partir de 0h20. Vous avez jusqu'à environ 17 h 20 pour soumettre le jeton. Cela semble généreux, mais considérez ce qui se passe dans un véritable flux de travail :

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

Scénarios courants de conditions de course

1. Formulaires en plusieurs étapes

Formulaires qui nécessitent plusieurs pages avant la soumission finale :

Step 1: Fill personal info → Step 2: Fill address → 
Step 3: Solve CAPTCHA → Step 4: Review → Step 5: Submit

Si CAPTCHA est à l'étape 3 mais que la soumission a lieu à l'étape 5, le délai entre la résolution et la soumission peut dépasser 5 minutes.

2. Files d'attente de traitement par lots

Résoudre les jetons à l'avance et les utiliser plus tard :

# 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. Réessayez les boucles avec d'anciens jetons

Réutiliser un token après un échec de soumission :

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

Prévenir l'expiration

Stratégie 1 : Résoudre le problème juste à temps

Demandez le jeton uniquement lorsque vous êtes prêt à le soumettre :

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

Stratégie 2 : suivre l'âge des jetons

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)

Stratégie 3 : nouveau jeton lors de la nouvelle tentative (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');
}

Détection des jetons expirés

Le site ne vous indique généralement pas explicitement « jeton expiré ». Recherchez ces signaux :

Signal Indications
HTTP 403 après la soumission du jeton Jeton invalide ou expiré
Rediriger vers la page du formulaire La vérification du jeton a échoué
Message d'erreur : "Échec de la vérification" Échec générique – peut être une expiration
La page du défi réapparaît Jeton rejeté, Cloudflare relance les défis

Journalisation pour le diagnostic

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)")

Comportement d'actualisation automatique du tourniquet

Dans les flux basés sur un navigateur, les widgets Turnstile actualisent automatiquement les jetons avant leur expiration. Le data-expired-callback se déclenche lorsqu'un jeton expire :

turnstile.render('#captcha', {
  sitekey: '0x4AAAA...',
  callback: (token) => {
    console.log('New token:', token);
  },
  'expired-callback': () => {
    console.log('Token expired — widget will auto-refresh');
  }
});

Dans l'automatisation API uniquement (pas de navigateur), vous ne bénéficiez pas de l'actualisation automatique. Vous devez gérer vous-même la fraîcheur des jetons.

Dépannage

Problème Parce que Corriger
Le jeton fonctionne en test mais pas en production Le flux de production est plus lent Résolvez juste à temps, pas à l’avance
La première soumission réussit, les nouvelles tentatives échouent Réutiliser les jetons consommés Résolvez un nouveau jeton pour chaque tentative
Échecs intermittents sur les formulaires longs Le jeton expire pendant un flux en plusieurs étapes Déplacer la résolution de CAPTCHA à la dernière étape
Les tâches par lots ont un taux d'échec élevé Les jetons résolus en masse expirent avant utilisation Résolvez les jetons à la demande, pas par lots

FAQ

Puis-je prolonger la durée de vie d'un jeton Turnstile ?

Non. L'expiration est définie par Cloudflare et ne peut pas être modifiée. Votre seule option est de résoudre un nouveau jeton.

Quelle est la précision de la limite de 300 secondes ?

C'est approximatif. Cloudflare peut ajuster la synchronisation en fonction de la configuration. Utilisez 270 secondes (4,5 minutes) comme maximum pratique pour une marge de sécurité.

Dois-je pré-résoudre les jetons pour gagner du temps ?

Seulement si votre flux de travail peut les utiliser en quelques minutes. Pour le traitement par lots, résolvez les jetons à la demande plutôt qu’à l’avance.

Articles connexes

Prochaines étapes

Empêcher l'expiration du jeton Turnstile –récupérez votre clé API CaptchaAIet mettez en œuvre une résolution juste à temps avec un taux de réussite de 100 %.

Les commentaires sont désactivés pour cet article.