Your login or sign-up request fails because the form expects GeeTest fields (lot_number, pass_token, captcha_output) that only a solved widget produces. CapBypass solves GeeTest v4 and v3 with one task type, GeetestTaskProxyLess: send captchaId for v4, or gt plus a fresh challenge for v3, and submit what comes back. GeeTest is slower than token captchas (median 14 s over the last 7 days), so this post also sets the poll interval and timeout to match.

GeeTest v4 or v3: check what the page loads

Open DevTools, Network tab, filter on geetest. The host tells you the version, and the version decides which fields you send.

What you see v3 v4
API host api.geetest.com (/gettype.php, /get.php) gcaptcha4.geetest.com (/load, /verify)
Page call window.initGeetest(...) window.initGeetest4(...)
Fields to send gt + challenge captchaId
Changes per page load challenge nothing

The routing rule is simple: if the task contains challenge, CapBypass runs the v3 flow. If it only has captchaId, it runs v4. You never pick a challenge type (slide, icon, nine, word and the others); the solver detects it.

GeeTest v3 vs v4 routing: gt plus a fresh challenge goes to the v3 flow and returns challenge, validate and seccode; captchaId alone goes to the v4 flow and returns five fields

Finding captchaId and gt + challenge

v4. The captcha_id is a 32-hex string in the query of the /load request: gcaptcha4.geetest.com/load?captcha_id=fcd636b4.... It is fixed per site, so you can hard-code it once.

v3. gt is fixed per site, but challenge is issued by the site's own backend each time a page asks for a captcha. Look for the site's register call (often something like /geetest/register, the name varies) that returns {"gt": "...", "challenge": "...", "success": 1}. Your code calls that endpoint for every attempt and forwards both values.

If the site routes GeeTest through its own domain, add captchaHost (v3) or geetestApiServerSubdomain (v4, default gcaptcha4.geetest.com). The full field list is on the GeeTest docs page.

Solving GeeTest v4 with CapBypass

Create the task, then poll getTaskResult. With curl:

curl -s https://api.capbypass.pro/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "'"$CAPBYPASS_API_KEY"'", "task": { "type": "GeetestTaskProxyLess", "websiteURL": "https://example.com/login", "captchaId": "fcd636b4514bf7ac4143922550b3008b" } }' # {"errorId":0,"taskId":"07af74e1-6fec-4503-86e3-a8d080126516"} curl -s https://api.capbypass.pro/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "'"$CAPBYPASS_API_KEY"'", "taskId": "07af74e1-6fec-4503-86e3-a8d080126516"}' 

While the solver works you get {"errorId":0,"status":"processing"}. When it is done:

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

The SDKs wrap create and poll in one solve() call. Python (SDK docs), pip install capbypass-sdk:

import os from capbypass import CapBypass client = CapBypass(api_key=os.environ["CAPBYPASS_API_KEY"]) solution = client.solve({ "type": "GeetestTaskProxyLess", "websiteURL": "https://example.com/login", "captchaId": "fcd636b4514bf7ac4143922550b3008b", }, timeout=120) print(solution["lot_number"], solution["pass_token"]) 

TypeScript (SDK docs), npm i @capbypass/sdk, then submit the five fields to the site:

import { CapBypassClient, TaskType } from '@capbypass/sdk'; const client = new CapBypassClient({ apiKey: process.env.CAPBYPASS_API_KEY }); const solution = await client.solve({ type: TaskType.GEETEST_PROXYLESS, websiteURL: 'https://example.com/login', captchaId: 'fcd636b4514bf7ac4143922550b3008b', }, 120); // most sites post the five v4 fields as-is next to the form data const body = new URLSearchParams({ username: 'user@example.com', 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, }); const res = await fetch('https://example.com/api/login', { method: 'POST', body }); console.log(res.status); 

Field names on the site side vary. Copy them from the request the page itself sends after a manual solve (DevTools, the POST right after the widget turns green).

Solving GeeTest v3: fetch a fresh challenge every time

The v3 flow adds one step before the task: ask the site for a new challenge. Then submit the three geetest_* form fields.

import os import requests from capbypass import CapBypass client = CapBypass(api_key=os.environ["CAPBYPASS_API_KEY"]) session = requests.Session() # a new gt + challenge for this attempt, from the site's own register call reg = session.get("https://example.com/geetest/register").json() solution = client.solve({ "type": "GeetestTaskProxyLess", "websiteURL": "https://example.com/login", "gt": reg["gt"], "challenge": reg["challenge"], }, timeout=120) resp = session.post("https://example.com/login", data={ "username": "user@example.com", "geetest_challenge": solution["challenge"], "geetest_validate": solution["validate"], "geetest_seccode": solution["seccode"], }) print(resp.status_code) 

Submit the challenge from the solution, not the one you sent. GeeTest v3 appends characters to it during the solve, and the site validates that extended value.

Bonus: +5% credits on every top-up

New to CapBypass? Apply code WELCOME_2026 at checkout for an extra 5% in credits on every top-up, with no minimum and no expiry. Redeem it on the top-up page and put it toward your first GeetestTaskProxyLess solves.

Poll interval and timeout for GeeTest

A GeeTest solve means running the real challenge (image, slide track, click order), not just minting a token. Over the last 7 days the median solved GeetestTaskProxyLess task took 14 s. That changes two numbers in your loop:

  • Poll every 3 s if you write the loop yourself. Polling every 500 ms for a 14 s task is about 28 requests per solve instead of 5, and 3 s adds at most 3 s of latency.
  • Time out at 120 s on the client. Slow solves exist, and a 30 s timeout copied from a reCAPTCHA integration abandons tasks that were about to finish. Both SDKs default solve() to 120 s.

A failed task (status: "failed", for example ERROR_CAPTCHA_UNSOLVABLE) is refunded, so the right reaction is a new task with fresh inputs, not a retry of the same taskId. The full polling contract, with error handling, is in polling captcha API tasks.

Things that go wrong

  • Stale v3 challenge. The most common v3 mistake is reusing a challenge from an earlier page load, a cached register response, or an attempt that already failed. The task runs against a challenge the site no longer accepts, and the site rejects the seccode. Call the register endpoint once per task.
  • A leftover challenge field on a v4 site. Shared helper code that always sets challenge sends a v4 site down the v3 path. Send challenge only when the page loads api.geetest.com.
  • Custom GeeTest host. If the Network tab shows GeeTest calls on the site's own domain instead of geetest.com, pass it as captchaHost (v3) or geetestApiServerSubdomain (v4).
  • Own proxy errors. GeetestTask (your proxy) without a proxy field returns ERROR_PROXY_NOT_DEFINED; a malformed one returns ERROR_PROXY_FORMAT. Use host:port:user:pass (proxy format), or stay on GeetestTaskProxyLess.
  • User agent checks. If the site compares the browser on submit, pass your client's userAgent in the task, or send the userAgent the v3 solution returns.

Use this on sites you own or have permission to test. For how the create, poll and submit model works across captcha types, see how a captcha-solving API works. Per-solve prices are on the pricing page.

Originally published on capbypass.pro. CapBypass is an AI-powered captcha-solving API for reCAPTCHA, hCaptcha, Cloudflare Turnstile and AWS WAF.