Scarnox · Blog

Token captcha wygasł: przyczyny i jak to naprawić

Token captcha to krótkotrwały dowód, że wyzwanie zostało pokonane. Tokeny PopularCaptcha w Scarnox wygasają około dwóch minut po wydaniu. Jeśli wyślesz token po tym oknie, serwis odrzuci formularz, często z komunikatem, że captcha wygasła lub jest nieprawidłowa. Poprawka prawie zawsze dotyczy czasu: rozwiąż captcha jak najbliżej wysyłki, używaj każdego tokenu jeden raz i ponawiaj tylko wtedy, gdy wiesz, że pierwsza próba nie została zaakceptowana.

Dlaczego tokeny wygasają

Token nie jest trwałym poświadczeniem. Serwis chce wiedzieć, że człowiek (albo solver działający w jego imieniu) ukończył wyzwanie niedawno, więc nadaje tokenowi krótki czas życia. Zegar rusza, gdy token zostaje wydany, a nie gdy po raz pierwszy wywołujesz API. Wszystko, co dzieje się między rozwiązaniem a wysyłką, zjada te dwie minuty.

Częste przyczyny

Poprawka: rozwiąż tuż przed wysłaniem

Najprostszy niezawodny wzorzec to połączenie rozwiązania i wysyłki w jeden krok. Poproś o token, wstaw go do formularza, wyślij formularz i nie rób nic wolnego pomiędzy:

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,  # wywołanie blokuje się, aż token będzie gotowy
    )
    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)  # rozwiąż tuż przed wysłaniem
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Zauważ, że submit_form nie trzyma tokenu w cache ani w kolejce. Prosi o jeden, wysyła go i idzie dalej. Nieudane rozwiązania nie są naliczane, więc nieudane żądanie nic nie kosztuje po stronie rozwiązania.

Ponawiaj bezpiecznie

Niektóre serwisy odrzucają wygasły token w wyraźny sposób. Inne zwracają zwykłą stronę z komunikatem o błędzie w środku, więc sam kod statusu nic nie powie. Sprawdź, jaką odpowiedź serwis faktycznie zwraca dla wygasłego tokenu, i zbuduj kontrolę na jej podstawie. Pętla ponawiania może wyglądać tak:

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  # zaakceptowane, o ile wskazuje na to odpowiedź tego serwisu
    raise RuntimeError("captcha token rejected after retries")

Zachowaj ostrożność przy ponowieniach w formularzach, które coś tworzą. Jeśli pierwsza próba faktycznie została zaakceptowana, ale Twój kod źle odczytał odpowiedź, ponowienie może utworzyć duplikat konta, zamówienia lub wiadomości. Ponawiaj tylko wtedy, gdy masz pewność, że pierwsze wysłanie nie zostało zaakceptowane, i uczyń kontrolę konkretną dla serwisu, z którym pracujesz.

Dbaj o uczciwy czas

Częste błędy

Zapisuj dość, by zdiagnozować problem

Gdy wysyłka się nie powiedzie, zapisz czas wydania tokenu, czas wysłania formularza, status HTTP i pierwsze kilkaset znaków odpowiedzi. Dzięki tym czterem wartościom od razu zobaczysz, czy token się przeterminował, czy serwis odrzucił go z innego powodu. Nie zapisuj pełnego tokenu we wspólnych logach, bo ważny token to poświadczenie dla tego jednego wyzwania.

Co sprawdzić, gdy nadal nie działa

  1. Wypisz czas między zwróceniem tokenu a wysłaniem formularza.
  2. Potwierdź, że site_url zgadza się ze stroną, na której pojawia się captcha.
  3. Potwierdź, że sitekey został odczytany z aktualnej strony, a nie z nieaktualnej kopii.
  4. Potwierdź nazwy pól formularza. Tokeny PopularCaptcha trafiają do h-captcha-response, a często także do g-recaptcha-response.

Pełną listę odpowiedzi błędów i sposób obsługi każdej z nich znajdziesz w artykule obsługa błędów solvera captcha.

Następne kroki