Scarnox · Blog

Token de captcha expiré : causes et solutions

Un token de captcha est une preuve de courte durée qu'un défi a été réussi. Les tokens PopularCaptcha de Scarnox expirent environ deux minutes après leur émission. Si vous soumettez un token après cette fenêtre, le site rejette le formulaire, souvent avec un message indiquant que le captcha a expiré ou est invalide. La correction concerne presque toujours le timing : résolvez le captcha au plus près de la soumission, utilisez chaque token une seule fois, et ne réessayez que lorsque vous savez que la première tentative n'a pas été acceptée.

Pourquoi les tokens expirent

Un token n'est pas un identifiant permanent. Le site veut savoir qu'une personne (ou un solveur agissant pour elle) a accompli le défi récemment, il donne donc au token une courte durée de vie. Le chronomètre démarre à l'émission du token, et non au moment où vous appelez l'API pour la première fois. Tout ce qui se passe entre la résolution et la soumission consomme ces deux minutes.

Causes courantes

La solution : résoudre juste avant de soumettre

Le schéma le plus simple et le plus fiable consiste à faire de la résolution et de la soumission une seule étape. Demandez un token, placez-le dans le formulaire, envoyez le formulaire, et ne faites rien de lent entre les deux :

import requests

API_KEY = "scarnox_YOURAPIKEY"
CREATE_URL = "https://api.scarnox.com/api/tasks/create"

def fresh_token(sitekey: str, page_url: str) -> str:
    r = requests.post(
        CREATE_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "captcha_type": "PopularCaptchaTaskProxyless",
            "site_key": sitekey,
            "site_url": page_url,
        },
        timeout=185,  # l'appel bloque jusqu'à ce que le token soit prêt
    )
    data = r.json()
    if data.get("errorId") != 0:
        raise RuntimeError(f"{data.get('errorCode')}: {data.get('errorDescription')}")
    return data["solution"]["token"]

def submit_form(page_url: str, sitekey: str, form: dict) -> requests.Response:
    token = fresh_token(sitekey, page_url)  # résoudre juste avant l'envoi
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Remarquez que submit_form ne garde aucun token dans un cache ou une file d'attente. Il en demande un, l'envoie, et passe à la suite. Les résolutions échouées ne sont pas facturées, donc une requête échouée ne vous coûte rien côté résolution.

Réessayer en toute sécurité

Certains sites rejettent un token expiré avec une réponse claire. D'autres renvoient une page normale contenant un message d'erreur, si bien qu'un code de statut seul ne suffit pas à le savoir. Regardez la réponse que le site renvoie réellement pour un token expiré, et construisez votre contrôle à partir de celle-ci. Une boucle de réessai pourrait ressembler à ceci :

def submit_with_retry(page_url: str, sitekey: str, form: dict, attempts: int = 2):
    for _ in range(attempts):
        resp = submit_form(page_url, sitekey, form)
        if resp.status_code < 400 and "captcha" not in resp.text.lower():
            return resp  # accepté, d'après la réponse de ce site
    raise RuntimeError("captcha token rejected after retries")

Soyez prudent avec les réessais sur les formulaires qui créent quelque chose. Si la première tentative a bel et bien été acceptée mais que votre code a mal interprété la réponse, un réessai peut créer un compte, une commande ou un message en double. Ne réessayez que lorsque vous êtes certain que le premier envoi n'a pas été accepté, et rendez le contrôle spécifique au site sur lequel vous travaillez.

Gardez un timing honnête

Erreurs courantes

Journalisez assez pour diagnostiquer

Lorsqu'une soumission échoue, notez l'heure d'émission du token, l'heure d'envoi du formulaire, le statut HTTP et les premières centaines de caractères de la réponse. Avec ces quatre valeurs, vous voyez d'un coup d'œil si le token a expiré ou si le site l'a rejeté pour une autre raison. Ne journalisez pas le token complet dans des journaux partagés, car un token valide est un identifiant pour ce défi précis.

Que vérifier si cela échoue encore

  1. Affichez le temps écoulé entre le retour du token et l'envoi du formulaire.
  2. Confirmez que site_url correspond à la page qui affiche le captcha.
  3. Confirmez que la sitekey a été lue sur la page actuelle, et non sur une copie ancienne.
  4. Confirmez les noms des champs du formulaire. Les tokens PopularCaptcha vont dans h-captcha-response, et souvent aussi dans g-recaptcha-response.

Pour la liste complète des réponses d'erreur et la façon de traiter chacune, consultez la gestion des erreurs du solveur de captcha.

Étapes suivantes