API-Tutorials

GeeTest Slide CAPTCHA-Parameter und API-Leitfaden

Ein GeeTest-Slider scheitert selten am eigentlichen Lösen – er scheitert an den Parametern. Wer gt, challenge und pageurl nicht sauber aus der Seite zieht oder eine bereits abgelaufene challenge übermittelt, bekommt zuverlässig einen Fehler. Dieser Leitfaden zeigt, welche vier Werte GeeTest v3 erwartet, wie Sie sie extrahieren und korrekt an die CaptchaAI-API übergeben – mit Python-Beispielen von der Extraktion bis zur Validierung auf der Zielseite.

Das Wichtigste in Kürze:

  • GeeTest v3 erwartet drei Pflichtparameter – gt, challenge und pageurl – plus das optionale api_server.
  • gt ist die feste Konto-ID der Site; challenge wird pro Sitzung neu vergeben und läuft nach 60–120 Sekunden ab.
  • CaptchaAI gibt challenge, validate und seccode zurück; diese drei Werte gehen an die Zielseite.
  • CaptchaAI löst GeeTest v3; GeeTest v4 ist als „bald verfügbar" angekündigt.

Die vier GeeTest-v3-Parameter im Überblick

Parameter Erforderlich Beschreibung
gt Ja GeeTest-Konto-ID der Site (32-stellige Hexadezimalzahl). Steht im Seitenquelltext oder in der API-Antwort
challenge Ja Sitzungsspezifischer Wert. Muss für jede Lösung frisch sein
pageurl Ja Vollständige URL der Seite, auf der das CAPTCHA erscheint
api_server Nein Abweichende Subdomain des GeeTest-API-Servers

Nur challenge ist flüchtig: gt bleibt für eine Site konstant, challenge wird bei jedem Seitenaufruf neu vergeben und entscheidet später über Erfolg oder ERROR_CAPTCHA_UNSOLVABLE.


Der Ablauf in drei Schritten

Unabhängig von Sprache oder Framework folgt jede GeeTest-v3-Lösung derselben Reihenfolge:

  1. Extrahieren: gt und eine frische challenge aus der Zielseite oder ihrem Register-Endpunkt auslesen.
  2. Übermitteln: beide Werte plus pageurl an die CaptchaAI-API senden und das Ergebnis abfragen.
  3. Validieren: die zurückgegebenen Felder challenge, validate und seccode an den Prüf-Endpunkt der Zielseite posten.

Reißt einer dieser Schritte ab – etwa durch eine abgelaufene challenge –, wird die gesamte Übermittlung abgelehnt. Die folgenden Abschnitte zeigen jeden Schritt mit lauffähigem Python-Code.


gt und challenge aus der Seite extrahieren

Ein typisches DACH-Szenario: Ein Team wertet für ein Preismonitoring ein Login-Portal aus, dessen Anmeldeseite einen GeeTest-v3-Slider zeigt. Erster Schritt ist immer, gt und challenge aus Seite oder Register-Endpunkt zu lesen – bei personenbezogenen Daten mit der üblichen DSGVO-Sorgfalt.

In der Praxis gibt es dafür zwei Wege:

  • Aus dem HTML: gt steht häufig direkt als 32-stellige Hexadezimalzahl im Seitenquelltext.
  • Über den Register-Endpunkt: dieser liefert eine frische challenge – und gelegentlich auch gt – als JSON zurück.

Das folgende Skript probiert beide Wege nacheinander und gibt ein sauberes Parameter-Dictionary zurück:

# extract_geetest_params.py
import requests
import re
import json


def extract_geetest_v3(page_url, session=None):
    """Extract GeeTest v3 gt and challenge from a page."""
    if session is None:
        session = requests.Session()
        session.headers["User-Agent"] = (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36"
        )

    resp = session.get(page_url, timeout=15)
    html = resp.text

    # Method 1: Extract gt from HTML
    gt_match = re.search(r'gt["\']?\s*[:=]\s*["\']([a-f0-9]{32})', html)
    gt = gt_match.group(1) if gt_match else None

    # Method 2: Find API endpoint that returns challenge
    api_match = re.search(r'(https?://[^"\']+register-slide[^"\']*)', html)

    challenge = None
    if api_match:
        api_url = api_match.group(1)
        api_resp = session.get(api_url, timeout=10)
        try:
            data = api_resp.json()
            challenge = data.get("challenge")
            gt = gt or data.get("gt")
        except json.JSONDecodeError:
            pass

    if not challenge:
        # Try embedded challenge
        ch_match = re.search(r'challenge["\']?\s*[:=]\s*["\']([a-f0-9]+)', html)
        challenge = ch_match.group(1) if ch_match else None

    return {"gt": gt, "challenge": challenge, "pageurl": page_url}


# Usage
params = extract_geetest_v3("https://example.com/login")
print(f"gt: {params['gt']}")
print(f"challenge: {params['challenge']}")

GeeTest an die CaptchaAI-API übermitteln

Liegen die Parameter vor, senden Sie sie mit method=geetest an in.php und fragen das Ergebnis über res.php ab. GeeTest v3 wird im Median in 10–20 Sekunden gelöst.

# solve_geetest.py
import requests
import time
import os


def solve_geetest(gt, challenge, pageurl, api_server=None):
    """Solve GeeTest v3 slide CAPTCHA via CaptchaAI."""
    api_key = os.environ["CAPTCHAAI_API_KEY"]

    payload = {
        "key": api_key,
        "method": "geetest",
        "gt": gt,
        "challenge": challenge,
        "pageurl": pageurl,
        "json": 1,
    }

    if api_server:
        payload["api_server"] = api_server

    # Submit
    resp = requests.post(
        "https://ocr.captchaai.com/in.php",
        data=payload,
        timeout=30,
    )
    result = resp.json()

    if result.get("status") != 1:
        raise RuntimeError(f"Submit failed: {result.get('request')}")

    task_id = result["request"]

    # Poll — GeeTest typically solves in 10-20 seconds
    time.sleep(10)
    for _ in range(30):
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key,
            "action": "get",
            "id": task_id,
            "json": 1,
        }, timeout=15)
        data = resp.json()

        if data.get("status") == 1:
            return data["request"]  # Returns challenge, validate, seccode
        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(5)

    raise TimeoutError("GeeTest solve timeout")

Die Lösung an die Zielseite zurückgeben

Die API liefert drei Werte zurück, die Sie an den Validierungsendpunkt der Zielseite übergeben müssen – challenge, validate und seccode:

# submit_solution.py
import json


def submit_geetest_solution(session, validation_url, solution, original_challenge):
    """Submit GeeTest solution to the target site."""
    # Parse solution if string
    if isinstance(solution, str):
        solution = json.loads(solution)

    payload = {
        "geetest_challenge": solution.get("challenge", original_challenge),
        "geetest_validate": solution.get("validate", ""),
        "geetest_seccode": solution.get("seccode", ""),
    }

    resp = session.post(validation_url, data=payload, timeout=30)
    return resp


# Complete flow
def full_geetest_flow(page_url, validation_url):
    import requests
    from extract_geetest_params import extract_geetest_v3

    session = requests.Session()
    session.headers["User-Agent"] = (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36"
    )

    # Step 1: Extract parameters
    params = extract_geetest_v3(page_url, session)
    print(f"gt: {params['gt']}, challenge: {params['challenge'][:16]}...")

    # Step 2: Solve
    solution = solve_geetest(
        params["gt"], params["challenge"], params["pageurl"],
    )
    print("Solved!")

    # Step 3: Submit
    resp = submit_geetest_solution(
        session, validation_url, solution, params["challenge"],
    )
    print(f"Validation response: {resp.status_code}")
    return resp

Wichtig ist, dass dieselbe Session extrahiert, löst und validiert – so bleiben Cookies und Sitzungskontext konsistent.


Warum die challenge frisch sein muss

Der häufigste Grund für abgelehnte Lösungen ist eine veraltete challenge – der Wert ist sitzungsspezifisch und läuft schnell ab:

# fresh_challenge.py
import time


def get_fresh_challenge(session, register_url):
    """Always fetch a fresh challenge before solving."""
    resp = session.get(register_url, timeout=10)
    data = resp.json()

    challenge = data.get("challenge")
    if not challenge:
        raise ValueError("No challenge returned")

    return challenge


def solve_with_fresh_challenge(session, gt, register_url, pageurl):
    """Ensure challenge is fresh before submitting to CaptchaAI."""
    challenge = get_fresh_challenge(session, register_url)

    # Submit immediately — don't let it expire
    solution = solve_geetest(gt, challenge, pageurl)
    return solution

Grundregel: Extrahieren Sie die challenge und senden Sie sie innerhalb weniger Sekunden an CaptchaAI. Eine abgelaufene challenge scheitert zuverlässig.

Hinweis: Puffern Sie keine challenge-Werte auf Vorrat. Sie sind an die Sitzung gebunden und nach spätestens 60–120 Sekunden wertlos – holen Sie jeden Wert unmittelbar vor der Übermittlung neu.


api_server für abweichende GeeTest-Backends

Manche Sites betreiben GeeTest über eine eigene Subdomain. Geben Sie den Host dann über api_server mit – sonst gilt api.geetest.com:

# The api_server parameter specifies a custom GeeTest backend
# Default: api.geetest.com
# Custom examples: api-na.geetest.com, api.geetest.com/ajax-custom

solution = solve_geetest(
    gt="abc123...",
    challenge="def456...",
    pageurl="https://example.com/login",
    api_server="api-na.geetest.com",  # North America endpoint
)

Fehlerbehebung: häufige GeeTest-Fehler

Problem Ursache Lösung
ERROR_CAPTCHA_UNSOLVABLE challenge bereits abgelaufen oder verbraucht Direkt vor dem Absenden eine frische challenge holen
validate ist leer gt und challenge stammen nicht aus derselben Sitzung Beide Werte aus demselben Seitenaufruf verwenden
Lösung von der Website abgelehnt seccode fehlt in der Rückgabe Alle drei Felder – challenge, validate, seccode – übermitteln
Parameter gt nicht gefunden Wert erst per JavaScript nachgeladen Mit Selenium rendern oder die XHR-Antworten des Register-Endpunkts prüfen

Häufige Fragen

Welche GeeTest-Version unterstützt CaptchaAI?

CaptchaAI löst GeeTest v3. GeeTest v4 ist noch nicht verfügbar – die Unterstützung ist als „bald verfügbar" angekündigt.

Warum bekomme ich ERROR_CAPTCHA_UNSOLVABLE?

Meist ist die challenge bereits abgelaufen. Sie ist sitzungsspezifisch und gilt nur 60–120 Sekunden – holen Sie den Wert unmittelbar vor der Übermittlung.

Muss ich die Slider-Bewegung selbst berechnen?

Nein. Sie übergeben nur die Parameter; CaptchaAI ermittelt die Lösung und gibt challenge, validate und seccode zurück. Diese drei Werte senden Sie an den Validierungsendpunkt der Zielseite.

Woher stammt der gt-Wert einer Seite?

Meist steht er im Seitenquelltext als 32-stellige Hexadezimalzahl oder in der Antwort des Register-Endpunkts. Wird er per JavaScript nachgeladen, lesen Sie ihn aus den XHR-Antworten oder rendern die Seite mit Selenium.

Wozu dient der Parameter api_server?

Er benennt den GeeTest-Backend-Host für Sites mit eigener Subdomain. Ohne Angabe nutzt CaptchaAI den Standard api.geetest.com. Den passenden Host finden Sie in den Netzwerk-Anfragen der Seite unter api-*.geetest.com.


Verwandte Leitfäden


GeeTest-Parameter im Griff – starten Sie mit CaptchaAI.

Kommentare sind für diesen Artikel deaktiviert.