GeeTest v3 + v4

Solve GeeTest v3 (slide) and v4 (slide, icon, svg_icon, nine, word, phrase, space, pencil, voice) challenges automatically

Overview

GeeTest is a behavioral CAPTCHA system used by major exchanges, gaming platforms, and SaaS products. Our API solves GeeTest v3 fullpage (slide puzzle on api.geetest.com) and all 9 v4 challenge types on gcaptcha4.geetest.com, returning the validated seccode payload.

Single task type for both versions

One task type (GeetestTask / GeetestTaskProxyLess) handles both. Routing is automatic based on which fields you send:

  • gt + challenge -> v3 flow
  • captchaId only -> v4 flow

Supported Task Types

Task TypeProxy RequiredDescription
GeetestTaskProxyLessNoUses our built-in proxy infrastructure
GeetestTaskYesRequires your own proxy

Supported Challenge Types

The solver auto-detects which challenge GeeTest serves and dispatches to the right routine - you never need to specify a risk_type.

v3

TypeDescription
slideDrag the puzzle piece into the gap on the fullpage SDK

v4

Risk TypeDescription
slideDrag the puzzle piece into the gap
iconClick matching icons in order
svg_iconClick icons matching an SVG prompt
ninePick all matching tiles in a 3x3 grid
wordClick characters matching a target word
phraseClick phrase tokens in order
spaceSpatial reasoning click
pencilTracing/path challenge
voiceAudio transcription challenge

Create Task

Endpoint: POST /createTask

Request Parameters

ParameterTypeRequiredDescription
clientKeyStringYesYour API key
task.typeStringYesGeetestTaskProxyLess or GeetestTask
task.websiteURLStringYesTarget page URL serving the GeeTest challenge
task.gtStringv3 onlyGeeTest gt (32-hex). Required for v3 alongside challenge.
task.challengeStringv3 onlyGeeTest challenge (32-hex). Presence selects v3 flow.
task.captchaIdStringv4 onlyGeeTest v4 captcha_id (32-hex). Use this without challenge for v4.
task.captchaHostStringNov3 enterprise proxy host (e.g. captcha-api.pingan.com) when site routes geetest through a custom domain
task.geetestApiServerSubdomainStringNov4 custom API host (default gcaptcha4.geetest.com)
task.proxyStringNoProxy (required for GeetestTask). See Proxy Format
task.userAgentStringNoUser agent to match your client fingerprint

Request Example - v3

{
  "clientKey": "YOUR_API_KEY",
  "task": {
    "type": "GeetestTaskProxyLess",
    "websiteURL": "https://example.com/login",
    "gt": "81388ea1fc187e0c335c0a8907ff2625",
    "challenge": "7b33c5254c55c432cf558767e36b8ef5"
  }
}

Request Example - v4

{
  "clientKey": "YOUR_API_KEY",
  "task": {
    "type": "GeetestTaskProxyLess",
    "websiteURL": "https://example.com/login",
    "captchaId": "fcd636b4514bf7ac4143922550b3008b"
  }
}

Response

{
  "errorId": 0,
  "taskId": "07af74e1-6fec-4503-86e3-a8d080126516"
}

Get Task Result

Endpoint: POST /getTaskResult

Request

{
  "clientKey": "YOUR_API_KEY",
  "taskId": "07af74e1-6fec-4503-86e3-a8d080126516"
}

Response (Ready) - v3

{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "challenge": "7b33c5254c55c432cf558767e36b8ef5g3",
    "validate": "5e2af8d1f9c4b1a9e3f6c7d8e9f0a1b2",
    "seccode": "5e2af8d1f9c4b1a9e3f6c7d8e9f0a1b2|jordan",
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
  }
}

Submit geetest_challenge, geetest_validate, geetest_seccode as form parameters on your target site's verification endpoint - matches the v3 SDK callback shape exactly.

Response (Ready) - v4

{
  "errorId": 0,
  "status": "ready",
  "solution": {
    "captcha_id": "fcd636b4514bf7ac4143922550b3008b",
    "lot_number": "b851bce155d94932921939de5f0fface",
    "pass_token": "fc5d9cec1c9412d1845249a0b70060b939ce94f51833f0324dd91f8f93ccc904",
    "gen_time": "1778247610",
    "captcha_output": "aDCl9jf9IT64VmwG8eCe9Gjqv..."
  }
}

The five fields together form the GeeTest v4 seccode payload. Submit them as form parameters (or JSON) on your target site's verification endpoint exactly as you would after a real human solve.


How to Find the captcha_id (v4) or gt+challenge (v3)

v4 - captcha_id

The captcha_id is a 32-hex string that uniquely identifies the v4 deployment on a given site.

  1. Open the target page in Chrome with DevTools (F12) -> Network tab
  2. Filter by gcaptcha4.geetest.com
  3. Look for requests to /load or /verify
  4. The captcha_id= query parameter is the value you need
https://gcaptcha4.geetest.com/load?captcha_id=fcd636b4514bf7ac4143922550b3008b&challenge=...
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

captcha_id is constant per site

The captcha_id is fixed for a given page and rarely changes. You can hard-code it in your client once discovered. The challenge UUID rotates per request - our solver handles that automatically.

v3 - gt + challenge

For v3, both gt (constant per site) and challenge (rotates per page load) are issued by your target site's backend when the user requests a captcha. You forward both to us.

  1. Open the target page in DevTools -> Network tab
  2. Find the call to api.geetest.com/gettype.php?gt=... or api.geetest.com/get.php?gt=...&challenge=...
  3. The gt= query param is constant per site
  4. The challenge= query param is fresh per request - capture it from your backend's register response and forward it to us with the gt

For enterprise sites that route GeeTest through a custom proxy (e.g. captcha-api.pingan.com/get.php), pass that host via task.captchaHost.


How to Identify GeeTest

Indicatorv3v4
Network requestsapi.geetest.com, api.geevisit.com, static.geetest.com/v?/...gcaptcha4.geetest.com, static.geetest.com/v4/...
Scriptfullpage.X.X.X-*.js, slide.X.X.X.js, gct.*.jsgcaptcha4.js from static.geetest.com/v4/static/v1.9.x-.../js/
Loaded APIwindow.initGeetest(...)window.initGeetest4(...)
UISlide puzzle, "Click to verify" radar widgetSlide puzzle, icon-grid, or "Click in order" prompt

DevTools Quick Check:

Network tab -> Filter: "geetest" -> Look for /gettype.php (v3) or /load (v4)

Code Examples

import requests
import time

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.capbypass.pro"

def solve_geetest(website_url, *, gt=None, challenge=None, captcha_id=None, proxy=None):
    task = {
        "type": "GeetestTask" if proxy else "GeetestTaskProxyLess",
        "websiteURL": website_url,
    }
    if challenge:                # v3
        task["gt"] = gt
        task["challenge"] = challenge
    else:                        # v4
        task["captchaId"] = captcha_id
    if proxy:
        task["proxy"] = proxy

    res = requests.post(f"{BASE_URL}/createTask", json={
        "clientKey": API_KEY,
        "task": task,
    }).json()
    task_id = res["taskId"]

    while True:
        result = requests.post(f"{BASE_URL}/getTaskResult", json={
            "clientKey": API_KEY,
            "taskId": task_id,
        }).json()

        if result["status"] == "ready":
            return result["solution"]

        if result.get("errorId"):
            raise Exception(result.get("errorDescription"))

        time.sleep(1)

# v3 example
v3 = solve_geetest(
    "https://example.com/login",
    gt="81388ea1fc187e0c335c0a8907ff2625",
    challenge="7b33c5254c55c432cf558767e36b8ef5",
)
print(v3["seccode"])

# v4 example
v4 = solve_geetest(
    "https://example.com/login",
    captcha_id="fcd636b4514bf7ac4143922550b3008b",
)
print(v4["pass_token"])
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.capbypass.pro';

async function solveGeetest({ websiteURL, gt, challenge, captchaId, proxy }) {
  const task = {
    type: proxy ? 'GeetestTask' : 'GeetestTaskProxyLess',
    websiteURL,
  };
  if (challenge) {              // v3
    task.gt = gt;
    task.challenge = challenge;
  } else {                       // v4
    task.captchaId = captchaId;
  }
  if (proxy) task.proxy = proxy;

  const createRes = await fetch(`${BASE_URL}/createTask`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ clientKey: API_KEY, task }),
  });
  const { taskId } = await createRes.json();

  while (true) {
    const resultRes = await fetch(`${BASE_URL}/getTaskResult`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ clientKey: API_KEY, taskId }),
    });
    const result = await resultRes.json();

    if (result.status === 'ready') return result.solution;
    if (result.errorId) throw new Error(result.errorDescription);

    await new Promise((r) => setTimeout(r, 1000));
  }
}

// v3 example
const v3 = await solveGeetest({
  websiteURL: 'https://example.com/login',
  gt: '81388ea1fc187e0c335c0a8907ff2625',
  challenge: '7b33c5254c55c432cf558767e36b8ef5',
});
console.log(v3.seccode);

// v4 example
const v4 = await solveGeetest({
  websiteURL: 'https://example.com/login',
  captchaId: 'fcd636b4514bf7ac4143922550b3008b',
});
console.log(v4.pass_token);

Typical Solve Time

ChallengeAverageMaximum
v3 slide2-4 seconds15 seconds
v4 slide1-2 seconds10 seconds
v4 icon / svg_icon2-3 seconds15 seconds
v4 nine / word / phrase3-5 seconds20 seconds

Pricing

$0.99 per 1,000 successful solves (both v3 and v4). Failed solves are not charged.

Error Codes

Error CodeDescription
ERROR_KEY_DOES_NOT_EXISTInvalid API key
ERROR_ZERO_BALANCEInsufficient balance
ERROR_CAPTCHA_UNSOLVABLEChallenge could not be solved
ERROR_TASK_NOT_FOUNDTask ID not found
ERROR_INVALID_TASK_DATAMissing or invalid parameters
ERROR_PROXY_NOT_DEFINEDProxy required for a non-ProxyLess task type — use the ProxyLess variant or supply task.proxy
ERROR_PROXY_CONNECTION_FAILEDCould not connect through your proxy (refused, unreachable, or bad credentials) - check the proxy is alive and reachable
ERROR_PROXY_BANNEDThe target blocked your proxy IP (datacenter or flagged) - use a residential or mobile proxy
ERROR_INVALID_DEVELOPER_KEYThe provided developerKey is invalid or disabled
ERROR_WRONG_TASK_TYPEWrong task type for this site (e.g., standard vs enterprise)
ERROR_TIMEOUTTask exceeded timeout
ERROR_TASK_QUEUE_FULLServer is at capacity — retry in a few seconds
ERROR_TASK_TYPE_COMING_SOONTask type is not yet available
ERROR_TASK_TYPE_INACTIVETask type is currently disabled
ERROR_WORKER_CRASHEDSolver process exited mid-solve — balance refunded, safe to retry
ERROR_INTERNALInternal server error

Next Steps

On this page