Hintergründe

GeeTest v3 Challenge-Response-Workflow: Technischer Deep Dive

Wer GeeTest v3 automatisiert lösen will, braucht am Ende genau zwei Eingabewerte und bekommt drei Werte zurück, die ins Formular gehören. Kurz gefasst:

  • Eingabe an CaptchaAI: gt und challenge, beide aus der Zielseite extrahiert.
  • Rückgabe von CaptchaAI: geetest_challenge, geetest_validate und geetest_seccode.

Der Weg dazwischen ist der eigentliche Knackpunkt. Anders als bei reCAPTCHA, wo ein einziger Token die gesamte Prüfung abdeckt, verteilt GeeTest v3 die Verifizierung auf eine serverseitige Registrierung, einen Challenge-Austausch im Browser und eine abschließende Validierung. Jeder Schritt erzeugt eigene Parameter. Dieser Deep Dive zeigt, an welcher Stelle welcher Wert entsteht – und wie Sie ihn sauber an CaptchaAI übergeben.

In der Praxis begegnet GeeTest v3 DACH-Teams vor allem auf Portalen mit asiatischem Ursprung: Login-Masken, Preisseiten oder Buchungsstrecken, die Sie für Monitoring oder QA in einer eigenen oder autorisierten Umgebung automatisieren. Wer den Protokollablauf kennt, spart sich stundenlanges Rätselraten darüber, warum ein scheinbar korrekter Token trotzdem abgelehnt wird.

Das Protokoll in zwei Phasen

GeeTest v3 läuft immer in zwei getrennten Phasen ab – eine auf dem Server, eine im Browser.

Phase 1: Registrierung (serverseitig)

Das Backend der Website kontaktiert GeeTest, um eine neue Abfrage zu registrieren:

Site Backend → GeeTest Server: "Give me a challenge for this user"
GeeTest Server → Site Backend: { gt, challenge, new_captcha }
Site Backend → Browser: Passes gt and challenge to the page

Phase 2: Verifizierung (Client-Seite + Server-Seite)

Der Browser rendert die Abfrage, der Nutzer löst sie, und das Ergebnis wird geprüft:

Browser: Renders slider/puzzle using gt + challenge
User: Solves the challenge
Browser → Site Backend: { geetest_challenge, geetest_validate, geetest_seccode }
Site Backend → GeeTest Server: Verifies the three values
GeeTest Server → Site Backend: { result: "success" }

Merke: gt bleibt konstant und identifiziert die Website, challenge wird pro Sitzung neu vergeben. Diese Trennung verhindert Replay-Angriffe und ist auch der Grund, warum Sie einen einmal genutzten Wert nie wiederverwenden können.

Online- oder Offline-Modus?

Bevor Sie in den Detailablauf einsteigen, lohnt ein Blick auf den Betriebsmodus, denn er bestimmt, wie streng die Prüfung ausfällt:

  • Online (success = 1): normale Challenge-Response über die GeeTest-Server.
  • Offline (success = 0): vereinfachte lokale Prüfung ohne GeeTest-Server.

Im Offline-Modus wird die Abfrage lokal erzeugt und die Verifizierung fällt einfacher aus. In der Praxis läuft die überwiegende Mehrheit der Websites im Online-Modus – prüfen Sie den success-Wert aus der Registrierung, bevor Sie einen Fehler an anderer Stelle suchen.

Der Ablauf Schritt für Schritt

Schritt 1: Registrierungs-Request

Achtung: Dieser Schritt läuft serverseitig ab – der Browser bekommt am Ende nur gt und challenge zu sehen, nie den Registrierungs-Request selbst.

Das Backend der Site ruft den Registrierungsendpunkt von GeeTest auf:

GET https://api.geetest.com/register.php?gt=GT_ID&json_format=1

Die Antwort:

{
  "success": 1,
  "gt": "81dc9bdb52d04dc20036dbd8313ed055",
  "challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "new_captcha": true
}

Die Antwort enthält drei Felder:

  • gt – GeeTest-ID, identifiziert das GeeTest-Konto der Website.
  • challenge – einmaliger Challenge-Token für diese Sitzung.
  • new_captcha – gibt an, ob das neue CAPTCHA-Format verwendet wird.

Wichtig: Der challenge-Wert ist einmalig und zeitlich begrenzt. Jeder Seitenaufruf erzeugt eine neue Abfrage – Caching ist hier keine Option.

Schritt 2: Rendering im Browser

Der Browser erhält gt und challenge und initialisiert das GeeTest-Widget:

initGeetest({
  gt: "81dc9bdb52d04dc20036dbd8313ed055",
  challenge: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  offline: false,
  new_captcha: true,
  product: "float"
}, function(captchaObj) {
  captchaObj.appendTo('#captcha-container');
  captchaObj.onSuccess(function() {
    var result = captchaObj.getValidate();
    // result contains: geetest_challenge, geetest_validate, geetest_seccode
  });
});

Schritt 3: Die Abfragetypen

GeeTest v3 kann je nach Konfiguration unterschiedliche Aufgaben ausspielen:

  • Slider: ein Puzzleteil verschieben, um das Bild zu vervollständigen.
  • Symbolklick: bestimmte Symbole in der angezeigten Reihenfolge anklicken.
  • Wortklick: chinesische Zeichen in der richtigen Reihenfolge anklicken.
  • Space: Aufgabe zum räumlichen Denken (anklicken oder auswählen).

Welcher Typ erscheint, entscheidet GeeTest anhand der Konfiguration der Website und des Risikoprofils des Nutzers. Für die Integration mit CaptchaAI spielt der konkrete Typ keine Rolle – Sie übergeben in allen Fällen dieselben Parameter.

Schritt 4: Die drei Lösungswerte

Nach dem Lösen liefert das Widget drei Werte:

{
  "geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
  "geetest_validate": "abc123def456_validate",
  "geetest_seccode": "abc123def456_validate|jordan"
}

Diese drei Werte sind das eigentliche Ziel der gesamten Automatisierung:

  • geetest_challenge – modifizierter Challenge-Token (Original + 2 zusätzliche Zeichen).
  • geetest_validate – Validierungs-Hash.
  • geetest_seccode – Sicherheitscode (validate-Wert + \|jordan-Suffix).

Schritt 5: Serverseitige Prüfung

Das Backend der Site schickt diese drei Werte zur Prüfung an GeeTest:

POST https://api.geetest.com/validate.php

seccode=abc123def456_validate|jordan
&challenge=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy
&sdk=geetest-python-3.0.0

GeeTest antwortet mit:

{
  "seccode": "abc123def456_validate",
  "validate": "abc123def456_validate"
}

Stimmt die Antwort mit den übermittelten Werten überein, gilt die Abfrage als gelöst und der Login- oder Formular-Request wird durchgelassen.

gt und challenge aus der Seite extrahieren

Für das Lösen mit CaptchaAI brauchen Sie nur gt und challenge. Drei Wege führen zum Ziel – wählen Sie den, der zur Struktur der Zielseite passt:

  • Methode 1 liest die Werte aus dem Netzwerk-Traffic (am robustesten).
  • Methode 2 greift sie aus den DOM-Attributen ab.
  • Methode 3 parst sie aus dem Seitenquelltext.

Methode 1: Registrierungsantwort abfangen

from playwright.sync_api import sync_playwright
import json

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()

    geetest_params = {}

    def handle_response(response):
        if "register" in response.url and "geetest" in response.url:
            data = response.json()
            geetest_params["gt"] = data.get("gt")
            geetest_params["challenge"] = data.get("challenge")

    page.on("response", handle_response)
    page.goto("https://example.com/login")

    # Wait for GeeTest to load
    page.wait_for_selector(".geetest_holder")
    print(f"gt: {geetest_params.get('gt')}")
    print(f"challenge: {geetest_params.get('challenge')}")

Tipp: Methode 1 ist am robustesten, weil sie die Werte direkt aus dem Netzwerk-Traffic liest – unabhängig davon, wie die Seite sie später ins DOM schreibt.

Methode 2: Aus dem Seiten-JavaScript auslesen

gt = page.evaluate("() => document.querySelector('[data-gt]')?.dataset.gt")
challenge = page.evaluate("() => document.querySelector('[data-challenge]')?.dataset.challenge")

Methode 3: Aus dem initGeetest-Aufruf

Durchsuchen Sie die Seitenquelle nach dem initGeetest-Aufruf:

import re
source = page.content()
gt_match = re.search(r"gt['\"]?\s*[:=]\s*['\"]([a-f0-9]{32})['\"]", source)
challenge_match = re.search(r"challenge['\"]?\s*[:=]\s*['\"]([a-f0-9]{32})['\"]", source)

Parameter an CaptchaAI übergeben

Senden Sie die extrahierten Werte an den Endpunkt:

POST https://ocr.captchaai.com/in.php

key=YOUR_API_KEY
&method=geetest
&gt=81dc9bdb52d04dc20036dbd8313ed055
&challenge=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
&pageurl=https://example.com/login
&json=1

Anschließend fragen Sie das Ergebnis ab:

GET https://ocr.captchaai.com/res.php?key=YOUR_API_KEY&action=get&id=TASK_ID&json=1

CaptchaAI gibt Folgendes zurück:

{
  "status": 1,
  "request": {
    "geetest_challenge": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6xy",
    "geetest_validate": "abc123def456_validate",
    "geetest_seccode": "abc123def456_validate|jordan"
  }
}

Sie erhalten damit alle drei Werte, die der Verifizierungsschritt der Website erwartet.

Hinweis zur Abrechnung: CaptchaAI rechnet Thread-basiert ab. Ein Thread ist eine gleichzeitig laufende Abfrage, jeder Tarif enthält unbegrenzte Lösungen pro Thread. Für erste Tests reicht BASIC (15 $/Monat, 5 Threads); wer viele GeeTest-Abfragen parallel verarbeitet, skaliert über ADVANCE (90 $/Monat, 50 Threads) nach oben.

Häufige Fragen

Wird GeeTest v4 von CaptchaAI unterstützt?

Nein, noch nicht. CaptchaAI deckt derzeit GeeTest v3 ab; die vierte Generation ist offiziell als „bald verfügbar" angekündigt, aber noch nicht nutzbar. Dieser Deep Dive bezieht sich ausschließlich auf das v3-Protokoll mit gt, challenge und den drei Rückgabewerten.

Welche drei Werte muss ich am Ende ins Formular schreiben?

geetest_challenge, geetest_validate und geetest_seccode. Alle drei liefert CaptchaAI im request-Objekt zurück. Fehlt einer davon oder landet er im falschen Input-Feld, lehnt das Backend die Abfrage ab.

Warum reichen für CaptchaAI gt und challenge aus?

Weil CaptchaAI daraus die komplette Challenge-Response abwickelt und Ihnen die drei fertigen Validierungswerte zurückgibt. Sie müssen den Slider oder die Symbolklicks nicht selbst nachbilden – nur die beiden Eingabeparameter korrekt aus der Seite extrahieren.

Was unterscheidet die GeeTest-v3-Integration von reCAPTCHA?

Bei reCAPTCHA übergeben Sie sitekey und pageurl und erhalten einen einzigen Token. GeeTest v3 dagegen ist zweiteilig: erst die Registrierung mit gt/challenge, dann drei getrennte Rückgabewerte. Der Extraktionsschritt ist deshalb aufwendiger, der Aufruf an CaptchaAI selbst aber ähnlich unkompliziert.

Typische Fehler und ihre Ursachen

Problem Ursache Lösung
challenge ist leer Registrierung fehlgeschlagen Prüfen, ob die Seite GeeTest korrekt lädt
Lösung wird abgelehnt Challenge bereits abgelaufen Frischen challenge extrahieren und sofort lösen
Falscher gt-Wert Mehrere GeeTest-Instanzen auf der Seite gt aus dem richtigen Widget extrahieren
Drei Werte da, Formular sendet nicht Formularfelder fehlen Alle drei Werte in die richtigen Input-Felder eintragen

Fazit

GeeTest v3 wirkt komplex, folgt aber einer klaren Logik. Für die Automatisierung zählen drei Dinge:

  • Registrierung und Verifizierung sind zwei getrennte Phasen mit eigenen Parametern.
  • gt ist konstant, challenge ist einmalig – niemals wiederverwenden.
  • CaptchaAI übernimmt die Challenge-Response und liefert geetest_challenge, geetest_validate und geetest_seccode zurück.

Verwandte Leitfäden

Kommentare sind für diesen Artikel deaktiviert.