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.
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_2026at 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 firstGeetestTaskProxyLesssolves.
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
challengefrom 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
challengefield on a v4 site. Shared helper code that always setschallengesends a v4 site down the v3 path. Sendchallengeonly when the page loadsapi.geetest.com. - Custom GeeTest host. If the Network tab shows GeeTest calls on the site's own domain instead of
geetest.com, pass it ascaptchaHost(v3) orgeetestApiServerSubdomain(v4). - Own proxy errors.
GeetestTask(your proxy) without aproxyfield returnsERROR_PROXY_NOT_DEFINED; a malformed one returnsERROR_PROXY_FORMAT. Usehost:port:user:pass(proxy format), or stay onGeetestTaskProxyLess. - User agent checks. If the site compares the browser on submit, pass your client's
userAgentin the task, or send theuserAgentthe 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.

