Scarnox · Blog

Captchatoken verlopen: oorzaken en hoe je het oplost

Een captchatoken is een kortlevend bewijs dat een uitdaging is gehaald. De PopularCaptcha-tokens van Scarnox verlopen ongeveer twee minuten na uitgifte. Als je een token na dat venster verzendt, wijst de site het formulier af, vaak met een melding dat de captcha is verlopen of ongeldig is. De oplossing gaat bijna altijd over timing: los de captcha zo dicht mogelijk bij het verzenden op, gebruik elk token één keer, en probeer alleen opnieuw wanneer je weet dat de eerste poging niet is geaccepteerd.

Waarom tokens verlopen

Een token is geen permanente referentie. De site wil weten dat een persoon (of een solver die namens een persoon handelt) de uitdaging recent heeft voltooid, dus geeft hij het token een korte levensduur. De klok start bij uitgifte van het token, niet wanneer je voor het eerst de API aanroept. Alles wat tussen de oplossing en het verzenden gebeurt, eet aan die twee minuten.

Veelvoorkomende oorzaken

De oplossing: los op vlak voor het verzenden

Het eenvoudigste betrouwbare patroon is om de oplossing en het verzenden één stap te maken. Vraag een token aan, zet het in het formulier, post het formulier, en doe er niets traags tussenin:

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,  # de aanroep blokkeert totdat het token klaar is
    )
    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)  # los op vlak voor het posten
    return requests.post(
        page_url,
        data={**form, "h-captcha-response": token, "g-recaptcha-response": token},
        timeout=30,
    )

Let op dat submit_form geen token in een cache of wachtrij bewaart. Hij vraagt er één aan, post hem, en gaat verder. Mislukte oplossingen worden niet in rekening gebracht, dus een mislukt verzoek kost je aan de oplossingskant niets.

Veilig opnieuw proberen

Sommige sites wijzen een verlopen token af met een duidelijk antwoord. Andere geven een normale pagina terug met een foutmelding erin, dus een statuscode alleen vertelt je niet genoeg. Bekijk het antwoord dat de site daadwerkelijk teruggeeft voor een verlopen token en bouw je controle daarop. Een lus voor opnieuw proberen kan er zo uitzien:

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  # geaccepteerd, voor zover het antwoord van deze site dat laat zien
    raise RuntimeError("captcha token rejected after retries")

Wees voorzichtig met nieuwe pogingen bij formulieren die iets aanmaken. Als de eerste poging wel is geaccepteerd maar je code het antwoord verkeerd heeft gelezen, kan een nieuwe poging een dubbel account, bestelling of bericht aanmaken. Probeer alleen opnieuw wanneer je zeker weet dat de eerste post niet is geaccepteerd, en maak de controle specifiek voor de site waarmee je werkt.

Houd de timing eerlijk

Veelgemaakte fouten

Log genoeg om het te diagnosticeren

Wanneer een verzending mislukt, registreer dan het tijdstip waarop het token is uitgegeven, het tijdstip waarop het formulier is gepost, de HTTP-status en de eerste paar honderd tekens van de respons. Met die vier waarden zie je in één oogopslag of het token is verlopen of dat de site het om een andere reden heeft afgewezen. Log het volledige token niet in gedeelde logs, want een geldig token is een referentie voor die ene uitdaging.

Wat je moet controleren als het nog steeds faalt

  1. Print de tijd tussen het moment dat het token wordt teruggegeven en het posten van het formulier.
  2. Bevestig dat site_url overeenkomt met de pagina die de captcha toont.
  3. Bevestig dat de sitekey is gelezen van de huidige pagina, niet van een oude kopie.
  4. Bevestig de veldnamen van het formulier. PopularCaptcha-tokens gaan in h-captcha-response, en vaak ook in g-recaptcha-response.

Voor de volledige lijst met foutantwoorden en hoe je elk afhandelt, zie foutafhandeling van de captcha-solver.

Volgende stappen