Anti-Bot 9 min read

GeeTest CAPTCHA v3 and v4: How to Solve Both Versions

Guide to solving GeeTest v3 (slide puzzle) and v4 (click/match) CAPTCHAs — understanding challenge types, API parameters, and integration examples.

GeeTest CAPTCHA v3 and v4: How to Solve Both Versions

GeeTest CAPTCHA v3 and v4: How to Solve Both Versions

GeeTest CAPTCHA is one of the most widely deployed challenge systems globally, particularly across Chinese-language platforms and increasingly on international sites. GeeTest uses interactive puzzles — slider challenges in v3 and click/match tasks in v4 — combined with behavioral analysis to verify human users. This guide covers how both versions work, the parameters you need to extract, and how to solve them programmatically through a CAPTCHA solver API.

For context on how GeeTest fits into the broader anti-bot ecosystem alongside platforms like Cloudflare, DataDome, and Arkose Labs, see our pillar guide on understanding anti-bot systems.

GeeTest v3: The Slide Puzzle

GeeTest v3 is the older and still widely deployed version. Its primary challenge type is the slide puzzle: a jigsaw piece is cut from a background image, and the user must drag a slider to move the piece horizontally into the correct gap position.

How GeeTest v3 Works

When a page loads the GeeTest v3 widget, several things happen:

  1. Initialization — The page’s JavaScript calls GeeTest’s API with a gt (app ID) parameter to register a new challenge session.
  2. Challenge generation — GeeTest’s server returns a challenge string that identifies this specific puzzle instance, along with the puzzle images.
  3. User interaction — The user drags the slider to solve the puzzle. GeeTest’s JavaScript records the drag trajectory, speed, and timing, and submits both the answer and behavioral data for validation.
  4. Server-side validation — GeeTest’s backend validates the puzzle answer and the behavioral data. If both pass, a validation token is returned that the website’s backend can verify.

Beyond the primary slide puzzle, GeeTest v3 also includes less common challenge types: icon click (click specific icons in order) and space puzzle (drag a piece to the correct position in both X and Y axes). The slide puzzle accounts for the vast majority of v3 deployments.

Finding GeeTest v3 Parameters

To solve GeeTest v3 via API, you need two values:

gt (App ID) — A 32-character hexadecimal string that identifies the GeeTest account. This value is static per site and does not change between sessions.

Where to find it:

  • Search the page source for gt: or "gt" in JavaScript configuration objects.
  • Monitor network requests to api.geetest.com and look for the gt parameter.

challenge — A session-specific string generated for each CAPTCHA instance. This value changes every time the CAPTCHA widget loads.

Where to find it:

  • The challenge is typically returned from the site’s backend API. Look for an endpoint that the page calls before initializing the GeeTest widget — it usually returns JSON containing gt, challenge, and success fields.
  • In network requests, filter for the site’s own API calls (not geetest.com) that return GeeTest initialization data.
// Typical server response containing GeeTest v3 parameters
{
  "gt": "81388ea1fc187e0c335c0a8907ff2625",
  "challenge": "4c936c7e78c3dd5daa1e01abc8a2b73b",
  "success": 1,
  "new_captcha": true
}

Solving GeeTest v3

Use the GeeTestTaskProxyless task type with the gt and challenge parameters:

import requests
import time

API_KEY = "YOUR_UCAPTCHA_API_KEY"
BASE_URL = "https://api.ucaptcha.net"

# Step 1: Get fresh challenge from the target site
site_response = requests.get("https://example.com/api/geetest/init").json()
gt = site_response["gt"]
challenge = site_response["challenge"]

# Step 2: Create the GeeTest task
task_response = requests.post(f"{BASE_URL}/createTask", json={
    "clientKey": API_KEY,
    "task": {
        "type": "GeeTestTaskProxyless",
        "websiteURL": "https://example.com/login",
        "gt": gt,
        "challenge": challenge
    }
}).json()

task_id = task_response["taskId"]

# Step 3: Poll for the result
while True:
    time.sleep(5)
    result = requests.post(f"{BASE_URL}/getTaskResult", json={
        "clientKey": API_KEY,
        "taskId": task_id
    }).json()

    if result["status"] == "ready":
        solution = result["solution"]
        print(f"challenge: {solution['challenge']}")
        print(f"validate: {solution['validate']}")
        print(f"seccode: {solution['seccode']}")
        break
    elif result["status"] == "processing":
        print("Solving...")
    else:
        raise Exception(f"Error: {result.get('errorDescription')}")

GeeTest v3 Solution Format

The solution object for GeeTest v3 contains three fields that you submit to the target site’s validation endpoint:

FieldDescription
challengeThe validated challenge string (may differ from the input challenge)
validateA validation hash proving the puzzle was solved
seccodeA security code derived from the validate value

Submit all three values to the target site in the same format it expects:

# Submit the solution to the target site
validation_response = requests.post("https://example.com/api/login", data={
    "username": "user@example.com",
    "password": "password",
    "geetest_challenge": solution["challenge"],
    "geetest_validate": solution["validate"],
    "geetest_seccode": solution["seccode"]
})

GeeTest v4: Click and Match Challenges

GeeTest v4 is the newer generation, launched to address limitations of the v3 slider format. It replaces the slide puzzle with diverse click-based and matching challenges that are harder to solve with simple automation.

GeeTest v4 Challenge Types

GeeTest v4 includes several challenge variants:

  • Icon click — Click specific icons in the order shown by a prompt.
  • Space reasoning — Identify which image matches a described spatial relationship.
  • Word matching — Click characters or words in a specific sequence.
  • Object matching — Match pairs of related images.
  • Semantic reasoning — Select the image that answers a question or matches a description.

The challenge type is determined dynamically by GeeTest’s risk engine. Higher-risk sessions receive harder challenge types.

Finding GeeTest v4 Parameters

GeeTest v4 uses a different parameter structure than v3. The primary identifier is the captcha_id:

captcha_id — A UUID-format string that identifies the GeeTest v4 account. This replaces the gt parameter from v3.

Where to find it:

  • Search the page source for captcha_id or captchaId in JavaScript configuration.
  • Monitor network requests to gcaptcha4.geetest.com and look for the captcha_id parameter.

Unlike v3, GeeTest v4 does not require you to fetch a separate challenge parameter. The challenge is generated internally when the task is created.

// Typical GeeTest v4 initialization in page source
initGeetest4({
  captchaId: "e392e1d7fd421dc63325744d5a2b9c73",
  product: "bind"
});

Solving GeeTest v4

Use the same GeeTestTaskProxyless task type, but pass captcha_id instead of gt and challenge:

import requests
import time

API_KEY = "YOUR_UCAPTCHA_API_KEY"
BASE_URL = "https://api.ucaptcha.net"

# Create the GeeTest v4 task
task_response = requests.post(f"{BASE_URL}/createTask", json={
    "clientKey": API_KEY,
    "task": {
        "type": "GeeTestTaskProxyless",
        "websiteURL": "https://example.com/register",
        "captcha_id": "e392e1d7fd421dc63325744d5a2b9c73"
    }
}).json()

task_id = task_response["taskId"]

# Poll for the result
while True:
    time.sleep(5)
    result = requests.post(f"{BASE_URL}/getTaskResult", json={
        "clientKey": API_KEY,
        "taskId": task_id
    }).json()

    if result["status"] == "ready":
        solution = result["solution"]
        print(f"captcha_id: {solution['captcha_id']}")
        print(f"lot_number: {solution['lot_number']}")
        print(f"pass_token: {solution['pass_token']}")
        print(f"gen_time: {solution['gen_time']}")
        print(f"captcha_output: {solution['captcha_output']}")
        break
    elif result["status"] == "processing":
        print("Solving...")

GeeTest v4 Solution Format

The v4 solution contains a different set of fields than v3:

FieldDescription
captcha_idThe CAPTCHA ID echoed back
lot_numberA unique identifier for this solve session
pass_tokenThe validation token proving the challenge was solved
gen_timeTimestamp of token generation
captcha_outputEncoded output of the challenge interaction

Submit these values to the target site’s backend for verification:

validation_response = requests.post("https://example.com/api/register", json={
    "email": "user@example.com",
    "password": "password",
    "captcha_id": solution["captcha_id"],
    "lot_number": solution["lot_number"],
    "pass_token": solution["pass_token"],
    "gen_time": solution["gen_time"],
    "captcha_output": solution["captcha_output"]
})

v3 vs v4: Key Differences

AspectGeeTest v3GeeTest v4
Primary challengeSlide puzzleClick/match challenges
Identifiergt (32-char hex)captcha_id (UUID)
Challenge parameterRequired (session-specific)Not required (generated internally)
Solution fieldschallenge, validate, seccodecaptcha_id, lot_number, pass_token, gen_time, captcha_output
API domainapi.geetest.comgcaptcha4.geetest.com
Difficulty scalingLimited (same slide puzzle)Dynamic (multiple challenge types)

Tips for Reliable GeeTest Solving

Use fresh challenges for v3. The challenge parameter in GeeTest v3 expires quickly. Fetch a new challenge immediately before creating your solver task. Using a stale challenge will result in failed solves.

Check the version first. v3 and v4 use different parameters. Sending v3 parameters for a v4 challenge (or vice versa) will fail. Inspect the page’s network requests to determine which version is in use — api.geetest.com indicates v3, while gcaptcha4.geetest.com indicates v4.

Handle both versions. Some sites are migrating from v3 to v4. Your integration should detect which version is present and use the correct parameters. Checking for the presence of captcha_id versus gt in the page’s JavaScript is the simplest way to differentiate.

Expect moderate solve times. GeeTest challenges typically take 10 to 25 seconds to solve. This is faster than FunCaptcha but slower than reCAPTCHA. Adjust your polling intervals and timeouts accordingly. For more on how FunCaptcha compares, see our FunCaptcha and Arkose Labs guide.

Conclusion

GeeTest v3 and v4 represent two generations of interactive puzzle CAPTCHAs, each with distinct challenge formats, parameters, and solution structures. Solving them programmatically requires extracting the correct identifiers from the target page and using the GeeTestTaskProxyless task type with the appropriate parameters.

uCaptcha handles both GeeTest versions through a single API at api.ucaptcha.net, routing each task to the provider with the best solve rate for the specific challenge type. Whether you encounter a v3 slide puzzle or a v4 click challenge, one integration covers both.

Related Articles