Scarnox · Blog

Token de captcha expirado: causas e como resolver

Um token de captcha é uma prova de curta duração de que um desafio foi cumprido. Os tokens do PopularCaptcha da Scarnox expiram cerca de dois minutos depois de emitidos. Se você enviar um token depois dessa janela, o site rejeita o formulário, muitas vezes com uma mensagem dizendo que o captcha expirou ou é inválido. A correção quase sempre é uma questão de tempo: resolva o captcha o mais perto possível do envio, use cada token uma única vez e tente de novo apenas quando souber que a primeira tentativa não foi aceita.

Por que os tokens expiram

Um token não é uma credencial permanente. O site quer saber se uma pessoa (ou um solver agindo por ela) cumpriu o desafio recentemente, então dá ao token uma vida curta. O relógio começa quando o token é emitido, não quando você chama a API pela primeira vez. Tudo o que acontece entre a resolução e o envio consome esses dois minutos.

Causas comuns

A correção: resolva logo antes de enviar

O padrão mais simples e confiável é transformar a resolução e o envio em um único passo. Peça um token, coloque-o no formulário, envie o formulário e não faça nada lento no meio:

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,  # a chamada fica bloqueada até o token estar pronto
    )
    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)  # resolve logo antes de enviar
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Repare que submit_form não mantém um token em cache ou em uma fila. Ele pede um, envia e segue em frente. Resoluções com falha não são cobradas, então uma requisição que falha não custa nada do lado da resolução.

Repetindo com segurança

Alguns sites rejeitam um token expirado com uma resposta clara. Outros retornam uma página normal com uma mensagem de erro dentro dela, então o código de status sozinho não diz nada. Observe a resposta que o site realmente devolve para um token expirado e construa a sua verificação em torno dela. Um loop de retentativa poderia ficar assim:

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  # aceito, pelo menos segundo a resposta deste site
    raise RuntimeError("captcha token rejected after retries")

Tenha cuidado com retentativas em formulários que criam algo. Se a primeira tentativa foi de fato aceita, mas o seu código interpretou mal a resposta, uma nova tentativa pode criar uma conta, um pedido ou uma mensagem duplicada. Repita somente quando tiver certeza de que o primeiro envio não foi aceito, e torne a verificação específica para o site com que você está trabalhando.

Mantenha o tempo honesto

Erros comuns

Registre o suficiente para diagnosticar

Quando um envio falha, registre a hora em que o token foi emitido, a hora em que o formulário foi enviado, o status HTTP e os primeiros caracteres da resposta. Com esses quatro valores você consegue ver de imediato se o token envelheceu ou se o site o rejeitou por outro motivo. Não registre o token completo em logs compartilhados, já que um token válido é uma credencial para aquele desafio.

O que verificar se ainda falhar

  1. Imprima o tempo entre o token ser devolvido e o envio do formulário.
  2. Confirme que o site_url corresponde à página que mostra o captcha.
  3. Confirme que o sitekey foi lido da página atual, não de uma cópia antiga.
  4. Confirme os nomes dos campos do formulário. Os tokens do PopularCaptcha vão em h-captcha-response, e muitas vezes também em g-recaptcha-response.

Para a lista completa de respostas de erro e como tratar cada uma, veja tratamento de erros do solver de captcha.

Próximos passos