Scarnox · Blog

Token de captcha caducado: causas y cómo solucionarlo

Un token de captcha es una prueba de corta duración de que se superó un desafío. Los tokens de PopularCaptcha de Scarnox caducan unos dos minutos después de emitirse. Si envías un token después de esa ventana, el sitio rechaza el formulario, a menudo con un mensaje que dice que el captcha ha caducado o no es válido. La solución casi siempre tiene que ver con el momento: resuelve el captcha lo más cerca posible del envío, usa cada token una sola vez y reintenta solo cuando sepas que el primer intento no fue aceptado.

Por qué caducan los tokens

Un token no es una credencial permanente. El sitio quiere saber que una persona (o un solver que actúa en su nombre) completó el desafío hace poco, así que le da una vida corta. El reloj empieza cuando se emite el token, no cuando llamas por primera vez a la API. Todo lo que pasa entre la resolución y el envío consume esos dos minutos.

Causas habituales

La solución: resuelve justo antes de enviar

El patrón más sencillo y fiable es hacer de la resolución y el envío un único paso. Pide un token, ponlo en el formulario, envía el formulario y no hagas nada lento entre medias:

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,  # the call blocks until the token is ready
    )
    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)  # solve right before posting
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Fíjate en que submit_form no guarda un token en una caché ni en una cola. Pide uno, lo envía y sigue. Las resoluciones fallidas no se cobran, así que una petición fallida no te cuesta nada en el lado de la resolución.

Reintenta con seguridad

Algunos sitios rechazan un token caducado con una respuesta clara. Otros devuelven una página normal con un mensaje de error dentro, así que el código de estado por sí solo no te dirá nada. Mira la respuesta que el sitio devuelve de verdad para un token caducado y construye tu comprobación en torno a ella. Un bucle de reintentos podría verse así:

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  # accepted, as far as this site's response shows
    raise RuntimeError("captcha token rejected after retries")

Ten cuidado con los reintentos en formularios que crean algo. Si el primer intento sí fue aceptado pero tu código interpretó mal la respuesta, un reintento puede crear una cuenta, un pedido o un mensaje duplicado. Reintenta solo cuando estés seguro de que el primer envío no fue aceptado, y haz que la comprobación sea específica del sitio con el que trabajas.

Mantén el tiempo honesto

Errores habituales

Registra lo suficiente para diagnosticarlo

Cuando un envío falla, anota la hora en que se emitió el token, la hora en que se envió el formulario, el código HTTP y los primeros cientos de caracteres de la respuesta. Con esos cuatro valores puedes ver de un vistazo si el token caducó o si el sitio lo rechazó por otro motivo. No registres el token completo en logs compartidos, porque un token válido es una credencial para ese único desafío.

Qué comprobar si sigue fallando

  1. Imprime el tiempo transcurrido entre la devolución del token y el POST del formulario.
  2. Confirma que site_url coincide con la página que muestra el captcha.
  3. Confirma que la sitekey se leyó de la página actual, no de una copia antigua.
  4. Confirma los nombres de los campos del formulario. Los tokens de PopularCaptcha van en h-captcha-response, y a menudo también en g-recaptcha-response.

Para la lista completa de respuestas de error y cómo gestionar cada una, consulta gestión de errores del solver de captchas.

Próximos pasos