Scarnox · Blog

Токен капчи истёк: причины и как это исправить

Токен капчи — это короткоживущее доказательство того, что проверка пройдена. Токены PopularCaptcha от Scarnox истекают примерно через две минуты после выдачи. Если отправить токен после этого окна, сайт отклонит форму, часто с сообщением, что капча истекла или недействительна. Исправление почти всегда связано с таймингом: решайте капчу как можно ближе к отправке, используйте каждый токен один раз и повторяйте только тогда, когда точно знаете, что первая попытка не была принята.

Почему токены истекают

Токен — не постоянное учётное данные. Сайт хочет знать, что человек (или решатель, действующий за человека) недавно прошёл проверку, поэтому токен живёт недолго. Отсчёт начинается с выдачи токена, а не с первого вызова API. Всё, что происходит между решением и отправкой, съедает эти две минуты.

Частые причины

Исправление: решайте прямо перед отправкой

Самый надёжный шаблон — сделать решение и отправку одним шагом. Запросите токен, положите его в форму, отправьте форму и не делайте ничего медленного между этими действиями:

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,  # вызов блокируется, пока токен не готов
    )
    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)  # решаем прямо перед отправкой
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Обратите внимание, что submit_form не держит токен в кеше или очереди. Он запрашивает токен, отправляет его и идёт дальше. Неудачные решения не списываются, поэтому неудачный запрос ничего не стоит на стороне решения.

Безопасные повторы

Некоторые сайты отклоняют истёкший токен понятным ответом. Другие возвращают обычную страницу с сообщением об ошибке внутри, поэтому один только код статуса ничего не скажет. Посмотрите, что сайт реально возвращает для истёкшего токена, и постройте проверку вокруг этого ответа. Цикл повторов может выглядеть так:

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  # принято, судя по ответу этого сайта
    raise RuntimeError("captcha token rejected after retries")

Будьте осторожны с повторами на формах, которые что-то создают. Если первая попытка была фактически принята, а ваш код неправильно прочитал ответ, повтор может создать дубликат аккаунта, заказа или сообщения. Повторяйте только тогда, когда уверены, что первая отправка не была принята, и делайте проверку конкретной для сайта, с которым работаете.

Держите тайминг честным

Частые ошибки

Логируйте достаточно, чтобы понять причину

Когда отправка не удалась, записывайте время выдачи токена, время отправки формы, HTTP-статус и первые несколько сотен символов ответа. По этим четырём значениям сразу видно, истёк ли токен или сайт отклонил его по другой причине. Не логируйте полный токен в общих логах: действительный токен — это учётные данные для одной конкретной проверки.

Что проверить, если всё ещё не работает

  1. Выведите время между получением токена и отправкой формы.
  2. Убедитесь, что site_url совпадает со страницей, на которой показана капча.
  3. Убедитесь, что sitekey считан с текущей страницы, а не из старой копии.
  4. Проверьте имена полей формы. Токены PopularCaptcha идут в h-captcha-response, и часто также в g-recaptcha-response.

Полный список ответов об ошибках и способов их обработки — в обработке ошибок решателя капчи.

Что дальше