hCaptcha in Python mit dem CapSkip-SDK: ein Aufruf, ein Token

hcaptcha in python - hCaptcha in Python with the CapSkip SDK: One Call, One Token

Um hCaptcha in Python mit dem CapSkip-SDK zu lösen, rufen Sie solver.hcaptcha() mit dem sitekey des Widgets und der Seitenadresse auf und senden dann Ihr Formular mit dem zurückgegebenen Token und dem gemeldeten User-Agent. Das SDK sendet die Aufgabe, fragt das Ergebnis ab und gibt beide Werte zurück, sodass das Skript hauptsächlich aus Wiederholungsregeln und dem Formular-POST besteht. Der Löser dahinter ist der CapSkip-hCaptcha-Löser. Er läuft auf Ihrem eigenen Windows-PC mit einer Pauschallizenz, daher kostet es nichts, einen abgelaufenen oder abgelehnten Token zu ersetzen.

Was Sie brauchen

  • Ein Windows-PC mit CapSkip 4.0.0 oder neuer. Diese Version vom 3. November 2026 brachte das Lösen von hCaptcha mit, Enterprise eingeschlossen. Installieren Sie CapSkip nach der Einrichtungsanleitung.
  • Python 3.10 oder neuer, das ist das Minimum, das das Paket capskip deklariert, und zwei Pakete: capskip 1.6.0 oder neuer, die erste Version mit einer hCaptcha-Methode, und requests. Getestet mit capskip 1.6.0 und requests 2.34.2 unter Python 3.11.7 und 3.14.0, mit keinen anderen Versionen.
  • Eine PowerShell-Eingabeaufforderung, in der Sie pip install capskip requests ausführen.
  • Eine Seite mit einem hCaptcha-Widget, die Ihnen gehört oder die Sie automatisieren dürfen, und der sitekey dieses Widgets. Schritt 2 zeigt, wo Sie ihn finden.
  • Eine Adresse für CapSkip. Wo das Skript läuft, bestimmt den Modus. Der Local-Modus (127.0.0.1) bedient nur den PC, auf dem CapSkip läuft. Der Server-Modus lauscht zusätzlich auf Ihrer Netzwerkadresse oder öffentlichen IP, sodass ein anderer PC, ein Windows-VPS oder eine gehostete Plattform dieselben Anfragen senden kann. Den Modus wechseln Sie in den Verbindungseinstellungen. Der Code unten erwartet das Standardformat von CapSkip, lassen Sie also jede Einstellung für den Service Emulator auf ihrem Standardwert.
  • Optional: ein Proxy. Wohin er gehört, behandelt Schritt 2.

So wurde getestet: gegen zwei Mock-Server, die ich geschrieben habe, nicht gegen die echte CapSkip-App und nicht gegen eine echte hCaptcha-Website. Ein Mock bildet die Prüfungen im hCaptcha-Abschnitt der CapSkip API-Dokumentation. Der andere spielt ein Registrierungsformular und dient zugleich als Forward-Proxy. Nichts hier misst eine echte Lösezeit, und die Regeln der Website im Mock (Token nur einmal verwendbar, passender User-Agent, zwei Minuten Lebensdauer) stammen aus der CapSkip-Dokumentation, nicht von hCaptcha. Die eigentliche Prüfung übernimmt die Website, die Sie ansprechen. Wie das funktioniert, zeigen die Entwicklerdokumente von hCaptcha.

Schritt 1: den Solver erstellen

Die vier Codeblöcke unten gehören der Reihenfolge nach in eine Datei. Nennen Sie sie hcaptcha_demo.py. Nichts läuft, bis der letzte Block eingefügt ist. Das SDK war bei diesen Läufen das echte capskip 1.6.0, und nur die CapSkip-App dahinter war ein Mock. Das Argument apiKey des Konstruktors hat den Standardwert capskip, der funktioniert, solange API Key Validation ausgeschaltet ist. Haben Sie die Validierung eingeschaltet, übergeben Sie Ihren Schlüssel als apiKey.

Der Konstruktor legt auch fest, wie lange das SDK auf hCaptcha wartet. Sein Argument recaptchaTimeout, standardmäßig 300 Sekunden, gilt, weil das Widget in einem echten Browser bestanden wird. Der Code senkt es auf 180 Sekunden, das ist meine Wahl und keine Einstellung von CapSkip. Dieses Limit gilt nur für das Abfragen. Das SDK setzt für seine eigenen HTTP-Aufrufe kein Timeout, und gegen den Mock hielt eine um 20 Sekunden verzögerte Antwort den Aufruf bei recaptchaTimeout von 5 die vollen 20 Sekunden lang wartend. Probleme kommen als Exceptions an, die Sie aus capskip importieren: ValidationException, wenn das SDK Ihre Argumente ablehnt, bevor es etwas sendet, ApiException bei einem Fehlercode von CapSkip, TimeoutException, wenn die Wartezeit abläuft, und NetworkException, wenn CapSkip nicht erreichbar ist.

# pip install capskip requests
import re

import requests
from capskip import ApiException, CapSkip

PAGE_URL = "https://example.com/signup"  # the page that shows the widget
SITEKEY = "YOUR_SITEKEY"  # the data-sitekey of its h-captcha div

# Local mode. In Server mode, use your server's address as the host.
# With API Key Validation on, also pass apiKey="YOUR_API_KEY".
solver = CapSkip(host="127.0.0.1", port=8080, recaptchaTimeout=180)

Schritt 2: CapSkip um den Token bitten

Der sitekey ist öffentlich und für jeden Besucher derselbe. Die meisten Seiten geben ihn am Widget-Container als data-sitekey aus. Eine Seite, die das Widget per Skript baut, übergibt ihn als Option sitekey von hcaptcha.render(), und die Adresse des hCaptcha-iframe trägt ihn als sitekey=. Setzen Sie ihn in SITEKEY und die vollständige Adresse der Seite, die das Widget zeigt, in PAGE_URL.

Der Aufruf lautet solver.hcaptcha(SITEKEY, PAGE_URL). Er sendet die Aufgabe und fragt ab, bis der Token bereit ist, Sie halten also keine Aufgaben-ID und schreiben keine Schleife. Die Dokumentation der rohen API rät, zuerst 10 Sekunden zu warten, aber das SDK fragt sofort ab, schläft dann 0,25 Sekunden und verdoppelt diese Zeit nach jeder Antwort, dass das Ergebnis noch nicht bereit ist, bis auf höchstens 5 Sekunden. Laut Dokumentation dauert eine Lösung in der Regel 10 bis 30 Sekunden. Eine echte habe ich nie gemessen.

Das Ergebnis ist ein Dictionary. Seine Felder token und code enthalten denselben String, den für h-captcha-response, und userAgent ist der User-Agent, mit dem er ausgestellt wurde. Das Feld respKey ist ein zweiter Wert, den hCaptcha dem Widget übergibt. Es ist immer vorhanden, leer, wenn es keinen gibt, und laut Dokumentation lesen die meisten Websites es nie, daher ignoriert der Code es. Jedes Ergebnis wird nur einmal geliefert, und das SDK liest es für Sie, sodass die Funktion den Token und den User-Agent zusammen zurückgibt. Laut Dokumentation nutzt CapSkip ein Argument userAgent nur, wenn es zu dem Browser passt, mit dem es löst, daher lässt das Beispiel CapSkip wählen.

Ein Proxy ist für diese Methode optional. Laut Dokumentation reicht eine einzelne Adresse zum Testen, und ein stetiger Strom von Lösungen von einer einzigen IP ist genau das, was die Ratenbegrenzungen von hCaptcha erkennen sollen. Für größere Mengen laden Sie eine Proxy-Liste in den hCaptcha-Einstellungen oder senden mit jeder Aufgabe einen Proxy. Hat die Aufgabe selbst einen Proxy, geht er der Liste vor. Die Funktion nimmt einen Proxy als vollständige URL wie http://user:[email protected]:8080 und sendet das Schema als proxytype und den Rest als Feld proxy. HTTP- und HTTPS-Proxys funktionieren unverändert. Für einen SOCKS-Proxy führen Sie zuerst pip install requests[socks] aus. Wenn Sie Proxys rotieren, finden Sie im Leitfaden zur Proxy-Rotation die Einzelheiten.

def solve(proxy=None):
    options = {}
    if proxy:  # for example http://user:[email protected]:8080
        scheme, address = proxy.split("://", 1)
        # The SDK sends type as proxytype and uri as proxy.
        options["proxy"] = {"type": scheme.upper(), "uri": address}
    result = solver.hcaptcha(SITEKEY, PAGE_URL, **options)
    return result["token"], result["userAgent"]  # delivered once: keep both

Schritt 3: Das Formular mit demselben User-Agent senden

In einem Browser schreibt das Widget den Token in ein verstecktes Textarea-Feld namens h-captcha-response, mit einer Kopie namens g-recaptcha-response. Ohne Browser senden Sie h-captcha-response selbst, und g-recaptcha-response ebenfalls, wenn das Formular so ein Feld hat. Der Code unten sendet beide. Die eigenen Felder Ihres Formulars kommen dazu, ihre Namen richten sich nach der Website. Der POST geht an PAGE_URL. Zeigt die action des Formulars auf eine andere Adresse, ändern Sie daher das erste Argument des post-Aufrufs, PAGE_URL.

Der User-Agent ist wichtig. Die Antwort nennt den Browser, der den Token erzeugt hat, und die Dokumentation verlangt, das Formular mit genau dieser Zeichenfolge zu senden. Deshalb setzt die Funktion sie an der Session, bevor die Seite geladen wird, sodass das Laden der Seite und der POST denselben User-Agent tragen. Tokens sind nur einmal verwendbar und laufen etwa zwei Minuten nach der Ausstellung ab, senden Sie also sofort und fordern Sie bei jedem Versuch einen neuen an.

Der Post nennt außerdem die Seite, von der er kam, als Referer, denn requests sendet von sich aus weder einen Referer- noch einen Origin-Header. Manche Frameworks lehnen einen HTTPS-Formular-POST ab, der keinen von beiden hat. Die Django-CSRF-Dokumentation beschreibt zum Beispiel eine strenge Referer-Prüfung für HTTPS-Anfragen, die ohne Origin-Header kommen.

def submit_form(session, token, user_agent, email):
    # Every request from here on carries the User-Agent the token was
    # earned with, the page load included.
    session.headers["User-Agent"] = user_agent
    session.get(PAGE_URL, timeout=30)  # picks up the page's own cookies
    return session.post(
        PAGE_URL,
        data={
            "email": email,  # your form's own fields go here
            "h-captcha-response": token,
            "g-recaptcha-response": token,  # the widget fills both
        },
        headers={"Referer": PAGE_URL},  # requests sends no Referer by itself
        timeout=30,
    )

Schritt 4: Das vollständige Beispiel mit Wiederholungsregeln

Der letzte Block verbindet die Schritte zu einem Skript. Fügen Sie ihn am Ende von hcaptcha_demo.py ein, prüfen Sie, dass PAGE_URL und SITEKEY oben Ihre eigenen sind, und führen Sie python hcaptcha_demo.py in dem Ordner aus, der die Datei enthält (py hcaptcha_demo.py funktioniert, wenn python nicht in Ihrem PATH liegt). Das Skript macht bis zu drei Versuche.

Der Fehlercode entscheidet, was einen neuen Versuch bekommt. Laut Dokumentation bedeutet ERROR_CAPTCHA_UNSOLVABLE, dass die Aufgabe gescheitert ist und eine neue gesendet werden sollte, daher ist er der einzige Code, der wiederholt wird. Zwei andere Fehlschläge nennen ihre Ursache, weil ein erneutes Senden genauso scheitern würde: ein sitekey, den hCaptcha für die Seite abgelehnt hat, und ein Proxy, der nicht erreichbar ist. Die übrigen Codes in der Tabelle Häufige Fehler verweisen auf die Anfrage oder die Einrichtung. Das SDK legt den Code in die Meldung der ApiException, als bloßen Text oder in einem kleinen JSON-Umschlag, daher greift error_code das Wort ERROR_ heraus und funktioniert mit beidem. Alles andere beendet das Skript sofort, auch die drei Exceptions, die die Schleife nicht abfängt: ValidationException, TimeoutException und NetworkException.

Ein Formular, das die Website ablehnt, bekommt einen neuen Token und einen weiteren Versuch. Scheitern drei Tokens auf dieselbe Weise, schauen Sie sich die Formularfelder an. Ein HTTP 400 wegen eines fehlenden Feldes wiederholt sich, egal wie gut der Token ist. Außerdem bedeutet reply.ok nur, dass der Status unter 400 lag. Viele Websites antworten mit 200 und zeigen eine Fehlermeldung in der Seite, ersetzen Sie diesen Test daher durch eine Prüfung auf etwas, das Ihre Website nur bei Erfolg zeigt.

# Only a task CapSkip could not solve gets another try. A bad sitekey, a
# dead proxy or a wrong key would fail the same way again.
RETRY = {"ERROR_CAPTCHA_UNSOLVABLE"}


def error_code(err):
    # The message holds the code as bare text or inside a JSON envelope.
    found = re.search(r"ERROR_[A-Z_]+", str(err))
    return found.group(0) if found else str(err)


def sign_up(email, proxy=None):
    session = requests.Session()
    if proxy:
        session.proxies = {"http": proxy, "https": proxy}
    for attempt in range(1, 4):
        try:
            token, user_agent = solve(proxy)
        except ApiException as err:
            code = error_code(err)
            if code not in RETRY:
                raise
            print(f"attempt {attempt}: {code}, new task")
            continue
        reply = submit_form(session, token, user_agent, email)
        if reply.ok:
            return reply
        print(f"attempt {attempt}: the site answered {reply.status_code}, new token")
    raise RuntimeError("no accepted form after 3 attempts")


if __name__ == "__main__":
    reply = sign_up("[email protected]")
    print(reply.status_code, reply.text[:60])

Im Mock-Lauf verhielt sich das Skript so, mit denselben Ergebnissen auf Python 3.11.7 und 3.14.0:

Mock-EinstellungWas das Skript tat
Token bei der zweiten Abfrage bereitEine Aufgabe, dann wurde das Formular mit Status 200 angenommen
Die ersten zwei Lösungen abgelehntZwei Versuchszeilen, dann Status 200 bei der dritten Aufgabe
Die Website antwortet auf den ersten Formular-POST mit 403Eine Versuchszeile, eine zweite Aufgabe mit einem neuen Token, dann Status 200
ERROR_PROXY_CONNECT_REFUSED bei der AbfrageNach einer Aufgabe ausgelöst, ohne Wiederholung
Fehler als bloßer Text statt als JSON gesendetDasselbe Verhalten wie mit JSON, einschließlich der Wiederholung
Eine Proxy-URL an sign_up übergebenin.php erhielt den Proxy mit proxytype HTTP, und sowohl das Laden der Seite als auch der Formular-POST liefen über den Proxy-Mock
Token unter dem Standard-User-Agent von requests gesendetDie Mock-Website antwortete mit 403
Derselbe Token zweimal gesendetDer zweite POST bekam eine 403
CapSkip nie bereit, recaptchaTimeout auf 25 Sekunden gesenktTimeoutException etwa 28 Sekunden nach dem Aufruf, weil das letzte Warten zwischen den Abfragen 5 Sekunden dauert

Betrachten Sie die Zeilen zur Website als Tests meines eigenen Mocks. Seine Regeln folgen der CapSkip-Dokumentation, außer dass ich eine Prüfung des Session-Cookies hinzugefügt habe und die Anforderung, dass beide Token-Felder übereinstimmen. Sie beweisen nichts über hCaptcha oder über eine echte Website.

Häufige Fehler

FehlerUrsacheBeheben
ValidationExceptionDas SDK lehnte den Aufruf ab, bevor es ihn sendete: ein leerer sitekey, eine Seitenadresse, die keine vollständige http- oder https-URL ist, ein invisible-Wert außer 0, 1, true oder false, ein nicht unterstützter Proxy-Typ oder eine Option, die die hCaptcha-API von CapSkip nicht annimmt, etwa domain von 2CaptchaLesen Sie die Meldung, die das Problem nennt, und korrigieren Sie dann das Argument
ERROR_RECAPTCHA_INVALID_SITEKEYhCaptcha hat den sitekey für diese Seite abgelehnt. Ein leerer sitekey kommt nie so weit, weil das SDK ihn vorher ablehntKopieren Sie data-sitekey erneut von der Seite und prüfen Sie, dass PAGE_URL die Seite ist, die das Widget zeigt
ERROR_CAPTCHA_UNSOLVABLEhCaptcha wurde nicht bestandenSenden Sie eine neue Aufgabe. Die Schleife macht das bis zu dreimal
ERROR_PROXY_FORMATCapSkip konnte den Proxy-Wert nicht lesenPrüfen Sie den Proxy-Wert. CapSkip liest IP:PORT, LOGIN:PASSWORD@IP:PORT und IP:PORT:LOGIN:PASSWORD, und dieses Skript zerlegt eine URL wie http://user:pass@IP:PORT in einen proxytype und die Adresse nach dem Schema
ERROR_PROXY_CONNECT_REFUSEDDas Ziel war über den Proxy nicht erreichbar. Ich konnte das nur simulierenTesten Sie den Proxy für sich allein und prüfen Sie dann Typ und Login erneut
ERROR_TASK_NOT_SUPPORTEDDieses CapSkip akzeptiert den Aufgabentyp nicht. Mögliche Ursachen sind eine Version älter als 4.0.0 oder ein Service Emulator, der auf einen Dienst eingestellt ist, der hCaptcha ablehntAktualisieren Sie CapSkip auf 4.0.0 oder neuer und lassen Sie den Service Emulator auf seinem Standardwert
ERROR_WRONG_USER_KEY oder ERROR_KEY_DOES_NOT_EXISTDer Schlüssel ist falsch, während API Key Validation eingeschaltet ist. Das SDK sendet den String capskip, solange Sie keinen apiKey übergebenÜbergeben Sie Ihren Schlüssel als Argument apiKey von CapSkip()
TimeoutExceptionKein Token nach den 180 Sekunden Wartezeit, die recaptchaTimeout in Schritt 1 festlegt, oder CapSkip hat aufgehört zu antworten, während das SDK abfragte, was das SDK als noch nicht bereit zählt. Dieser Fall wird nicht wiederholtÖffnen Sie CapSkip, sehen Sie im Monitor nach der Aufgabe und starten Sie das Skript dann erneut
NetworkExceptionAuf dem Host und Port, die Sie CapSkip() gegeben haben, lauscht nichts, oder CapSkip antwortete mit einem HTTP-FehlerstatusStarten Sie CapSkip und vergleichen Sie dann Host und Port mit den Verbindungseinstellungen
Die Website lehnt einen Token ab, der gültig aussiehtDer Token wurde schon einmal verwendet, war älter als etwa zwei Minuten, kam mit einem anderen User-Agent, oder der Post trug keinen Referer. Die ersten drei Ursachen stammen aus der CapSkip-DokumentationSenden Sie jeden Token nur einmal, sofort, mit dem User-Agent aus derselben Antwort und der Seite als Referer

Wenn die Website den Token weiterhin ablehnt

Manche Websites, besonders hCaptcha-Enterprise-Websites, lehnen Tokens ab, die hCaptcha als riskant bewertet hat, obwohl das Widget bestanden wurde. Die CapSkip-Dokumentation nennt diese strenge sitekeys. Für hCaptcha rät die Dokumentation zur Einstellung High score mode unter Settings, Captcha types, hCaptcha. Dafür muss Google Chrome auf dem PC installiert sein, auf dem CapSkip läuft. Laut Changelog zu 4.0.0 ist der Modus standardmäßig eingeschaltet, und hCaptcha wird im CapSkip Custom Browser gelöst, wenn er ausgeschaltet ist oder Chrome fehlt. Die Dokumentation verlangt außerdem einen guten Proxy und dass das Formular von derselben Adresse aus gesendet wird, mit dem User-Agent aus der Antwort. Ich konnte nichts davon ohne eine echte strenge Website testen, betrachten Sie es also als Hinweise der CapSkip-Dokumentation und nicht als etwas, das ich geprüft habe.

CapSkip auf einem Server aus Ihrem Skript nutzen

Das Skript braucht von CapSkip nur einen Host und einen Port. Im Server-Modus nimmt CapSkip auch Verbindungen von anderen Geräten in Ihrem Netzwerk an, oder aus dem Internet auf einem Windows-VPS, und die Einrichtungsanleitung empfiehlt für stabilen Zugriff eine statische öffentliche IP. Der Server-Modus verlangt, dass CapSkip als Administrator läuft. Übergeben Sie Adresse und Port des Servers an CapSkip(), und sonst ändert sich nichts im Skript. Auch Besitz und Abrechnung bleiben gleich: Der Rechner gehört Ihnen, und es wird nichts nach Verbrauch abgerechnet. Der Port bleibt dadurch allerdings für andere Adressen offen, erstellen Sie also eine Blockierregel der Windows Firewall für alle, denen Sie nicht trauen.

Die Lösung findet nun auf dem Server statt. Für einen strengen sitekey verlangt die Dokumentation auf beiden Seiten dieselbe Adresse, geben Sie daher dem Argument proxy von sign_up einen Proxy, und er geht sowohl an die Aufgabe als auch an Ihre Session.

FAQ

Kann ich den asynchronen Client verwenden?

Ja. AsyncCapSkip nimmt dieselben Konstruktorargumente, und wenn Sie seine Methode hcaptcha() mit demselben sitekey und derselben Seitenadresse mit await aufrufen, kommt dasselbe Dictionary zurück. Es nutzt httpx, das pip zusammen mit capskip installiert. Ich habe ihn nur gegen den Mock ausgeführt.

Kann ich CapSkip von einer gehosteten Plattform aufrufen?

Ja, über den Server-Modus. Lassen Sie CapSkip auf einem Windows-Rechner mit erreichbarer Adresse laufen, übergeben Sie diese Adresse an CapSkip(), und die Aufrufe bleiben dieselben. Der Solver bleibt auf Hardware, die Sie kontrollieren, und die Plattform sendet nur HTTP-Anfragen an ihn.

Was ist mit unsichtbaren und Enterprise-Widgets?

Sie verwenden dieselbe Methode hcaptcha(). Ein unsichtbares Widget hat das Attribut data-size auf invisible gesetzt, übergeben Sie also invisible=True. Für eine Enterprise-Website, die einen rqdata-Wert setzt, übergeben Sie ihn als data und holen für jede Aufgabe einen neuen. Gegen den Mock erhielt in.php in beiden Fällen invisible=1 und den Wert data. Keinen von beiden habe ich auf einer echten Website ausgeführt.

Die Kurzfassung

hCaptcha in Python zu lösen läuft auf einen Aufruf hcaptcha() und einen Formular-POST mit dem User-Agent hinaus, mit dem der Token ausgestellt wurde. Wiederholen Sie nur, wenn CapSkip die Aufgabe nicht lösen konnte, und lassen Sie jeden anderen Fehler das Skript beenden. Da CapSkip ein lokaler Captcha-Löser ist, der mit einer Pauschallizenz arbeitet, genügt es, die Schleife noch einmal laufen zu lassen, um einen abgelehnten Token zu ersetzen. Die Python-Captcha-Solver-Seite zeigt die SDK-Aufrufe für die anderen Typen, und wie das Widget bestanden wird, sehen Sie in der hCaptcha-Demo.