Troubleshooting

GeeTest Challenge Expired Before Submission: Timing Guide

GeeTest challenges expire quickly. If you extract the challenge parameters, wait too long, and then solve — the target site rejects the token because the challenge has expired.


GeeTest Timing

Phase Time Limit
Challenge token validity 60-120 seconds
Solve time (CaptchaAI) 10-30 seconds
Token submission window Must complete within challenge validity
Total budget ~60-90 seconds from extraction to submission

The Problem


1. Extract gt + challenge from page  ← Clock starts
2. Submit to CaptchaAI               ← Takes 1-5 seconds
3. Wait for solve                    ← Takes 10-30 seconds
4. Get token                         ← Must still be valid
5. Submit to target site             ← Must happen fast

If step 2-5 takes longer than the challenge validity, the token is rejected.


Solution: Extract and Solve Immediately

import requests
import time
import re


def extract_geetest_params(page_url, session=None):
    """Extract fresh GeeTest parameters from page."""
    s = session or requests.Session()
    resp = s.get(page_url, timeout=15)

    # Extract gt key
    gt_match = re.search(r'"gt":\s*"([^"]+)"', resp.text)
    challenge_match = re.search(r'"challenge":\s*"([^"]+)"', resp.text)

    if not gt_match or not challenge_match:
        # Try API endpoint (many sites fetch challenge via AJAX)
        api_match = re.search(r'captcha\?.*', resp.text)
        if api_match:
            api_resp = s.get(f"{page_url}/{api_match.group()}", timeout=15)
            data = api_resp.json()
            return data.get("gt"), data.get("challenge")

    if gt_match and challenge_match:
        return gt_match.group(1), challenge_match.group(1)

    return None, None


def solve_geetest_fast(api_key, page_url, session=None):
    """Extract, solve, and return GeeTest token as fast as possible."""
    s = session or requests.Session()

    # Step 1: Extract fresh parameters
    extraction_start = time.time()
    gt, challenge = extract_geetest_params(page_url, s)

    if not gt or not challenge:
        raise RuntimeError("Could not extract GeeTest parameters")

    print(f"Extracted params in {time.time() - extraction_start:.1f}s")

    # Step 2: Submit to CaptchaAI immediately
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": api_key,
        "method": "geetest",
        "gt": gt,
        "challenge": challenge,
        "pageurl": page_url,
        "json": 1,
    }, timeout=30)
    result = resp.json()

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

    task_id = result["request"]

    # Step 3: Poll aggressively
    time.sleep(10)  # GeeTest typically takes 10-30s
    for _ in range(16):  # 80s max
        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:
            total_time = time.time() - extraction_start
            print(f"Solved in {total_time:.1f}s total")

            if total_time > 90:
                print("WARNING: Challenge may have expired")

            return data["request"]

        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(f"Solve error: {data['request']}")

        time.sleep(5)

    raise TimeoutError("GeeTest solve timeout")

Handling Challenge API Endpoints

Many sites fetch GeeTest challenges via an AJAX call:

def get_fresh_challenge(api_url, session):
    """Fetch a fresh GeeTest challenge from site's API."""
    resp = session.get(api_url, timeout=15)
    data = resp.json()

    return {
        "gt": data["gt"],
        "challenge": data["challenge"],
        "new_captcha": data.get("new_captcha", True),
    }


# Common API patterns:
# GET /api/captcha/init
# GET /captcha?t=TIMESTAMP
# GET /geetest/register?t=TIMESTAMP

Retry with Fresh Challenge

def solve_geetest_with_retry(api_key, page_url, challenge_api, max_attempts=3):
    """Retry GeeTest solve with fresh challenge each time."""
    session = requests.Session()

    for attempt in range(max_attempts):
        try:
            # Always get FRESH challenge
            params = get_fresh_challenge(challenge_api, session)

            # Solve
            resp = requests.post("https://ocr.captchaai.com/in.php", data={
                "key": api_key,
                "method": "geetest",
                "gt": params["gt"],
                "challenge": params["challenge"],
                "pageurl": page_url,
                "json": 1,
            }, timeout=30)
            result = resp.json()

            if result.get("status") != 1:
                print(f"Attempt {attempt + 1}: Submit error")
                continue

            task_id = result["request"]

            # Poll
            time.sleep(10)
            for _ in range(12):
                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"]
                if data["request"] != "CAPCHA_NOT_READY":
                    break
                time.sleep(5)

        except Exception as e:
            print(f"Attempt {attempt + 1} failed: {e}")

    raise RuntimeError("Max GeeTest solve attempts exceeded")

Troubleshooting

Issue Cause Fix
Token always rejected Challenge expired during solve Extract → solve → submit in < 60s
Can't find challenge parameter Loaded via AJAX Intercept network requests
Challenge changes on each load Normal GeeTest behavior Always use fresh challenge
Same gt key, different challenge gt is static, challenge is dynamic Re-fetch challenge, keep gt

FAQ

How do I find the challenge API endpoint?

Open browser DevTools → Network tab → look for requests containing "geetest", "captcha", or "register" when the page loads. The response will contain gt and challenge.

Can I cache the gt parameter?

Yes. The gt key is usually static per site. Only the challenge token needs to be fresh. Cache gt and re-fetch challenge before each solve.

What if the site uses GeeTest v4?

GeeTest v4 uses a different API structure. Check CaptchaAI's documentation for v4-specific parameters.



Solve GeeTest fast — get CaptchaAI with 100% accuracy.

Discussions (0)

No comments yet.