Your form submit comes back with "verification failed" because the page expects a reCAPTCHA v3 token and your script never ran the widget. You don't need a browser to fix that: send the page URL, the siteKey and the action to a solver API and get a g-recaptcha-response token back. Over the last 60 days, ReCaptchaV3TaskProxyLess solves averaged 0.7 s and 99.9% succeeded. This post shows the full solve in curl, Python and TypeScript, then the three things that make a valid token fail anyway.

What you need from the page

reCAPTCHA v3 has no checkbox. The page loads api.js?render=<siteKey> and calls grecaptcha.execute(siteKey, {action}) right before it submits. You need three values:

  • websiteURL: the page that runs the execute call, not the API endpoint it posts to.
  • websiteKey: the render= value in the script URL, starting with 6L.
  • pageAction: the action string passed to grecaptcha.execute. Search the page source or the JS bundle for grecaptcha.execute(.
<script src="https://www.google.com/recaptcha/api.js?render=6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696"></script> <script> grecaptcha.execute('6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696', { action: 'login' }) .then(token => submitLogin(token)); </script> 

If the script is recaptcha/enterprise.js and the call is grecaptcha.enterprise.execute, the key is Enterprise. Use the Enterprise task types instead, covered in the reCAPTCHA Enterprise solver guide.

Solving with curl

Two calls: createTask queues the solve, getTaskResult returns the token once it is ready.

curl -s https://api.capbypass.pro/createTask \ -H 'Content-Type: application/json' \ -d '{ "clientKey": "'"$CAPBYPASS_API_KEY"'", "task": { "type": "ReCaptchaV3TaskProxyLess", "websiteURL": "https://example.com/login", "websiteKey": "6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696", "pageAction": "login" } }' # {"errorId":0,"taskId":"f47ac10b-58cc-4372-a567-0e02b2c3d479"} curl -s https://api.capbypass.pro/getTaskResult \ -H 'Content-Type: application/json' \ -d '{"clientKey": "'"$CAPBYPASS_API_KEY"'", "taskId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"}' 

A ready result looks like this:

{ "errorId": 0, "status": "ready", "solution": { "gRecaptchaResponse": "03AGdBq26fE8...", "userAgent": "Mozilla/5.0 ...", "secChUa": "\"Chromium\";v=\"136\", ..." } } 

Until then status is processing. Poll every second or two and give up after a fixed timeout. The details (intervals, timeouts per task type, which errors to retry) are in polling captcha API tasks.

Solving in Python

The Python SDK wraps create and poll in one solve() call.

pip install capbypass-sdk 
import os import requests from capbypass import CapBypass from capbypass.errors import SolverError, TimeoutError client = CapBypass(api_key=os.environ["CAPBYPASS_API_KEY"]) try: solution = client.solve({ "type": "ReCaptchaV3TaskProxyLess", "websiteURL": "https://example.com/login", "websiteKey": "6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696", "pageAction": "login", }, timeout=120) except (SolverError, TimeoutError) as e: raise SystemExit(f"solve failed: {e}") # submit right away: the token is valid for 2 minutes resp = requests.post( "https://example.com/api/login", data={"email": "me@example.com", "password": "...", "g-recaptcha-response": solution["gRecaptchaResponse"]}, headers={"User-Agent": solution["userAgent"]}, ) print(resp.status_code) 

The field name the site expects varies: g-recaptcha-response is the default for forms, JSON APIs often use recaptchaToken or captcha. Copy whatever the browser sends in DevTools.

Solving in TypeScript

Same flow with the TypeScript SDK:

npm i @capbypass/sdk 
import { CapBypassClient, TaskType } from '@capbypass/sdk'; const client = new CapBypassClient({ apiKey: process.env.CAPBYPASS_API_KEY }); const solution = await client.solve({ type: TaskType.RECAPTCHA_V3_PROXYLESS, websiteURL: 'https://example.com/login', websiteKey: '6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696', pageAction: 'login', }, 120); const res = await fetch('https://example.com/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'User-Agent': solution.userAgent }, body: JSON.stringify({ email: 'me@example.com', password: '...', recaptchaToken: solution.gRecaptchaResponse }), }); console.log(res.status); 

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 ReCaptchaV3TaskProxyLess solves.

Proxyless or your own proxy

There are two classic v3 task types. ReCaptchaV3TaskProxyLess solves from our network. ReCaptchaV3Task takes a proxy field (host:port:user:pass, see the proxy format) and solves through your IP.

We compared both over the last 60 days of production traffic:

Task type Success Average solve time
ReCaptchaV3TaskProxyLess 99.9% 0.7 s
ReCaptchaV3Task (your proxy) 99.3% 5.2 s

Average reCAPTCHA v3 solve time over 60 days: 0.7 s proxyless versus 5.2 s through the customer's own proxy

Success is about the same. Time is not: the whole solve runs through a connection we don't control, and the average is 7 times slower. Pick the proxied type only when the token has to be generated from a specific IP, for example a residential IP you already know scores well on that site. Otherwise use ProxyLess.

The score itself follows IP reputation more than anything a solver does. If tokens are accepted but the score is too low to pass, read why your reCAPTCHA v3 score is low before switching task types.

Things that go wrong

  • Token rejected after a few minutes. A v3 token lives 2 minutes and works once. Solve right before the submit, never in a batch ahead of time, and never reuse a token for a second request.
  • Wrong or missing action. If you leave pageAction out, the token is minted for the action homepage. A login endpoint that checks for login then rejects it with no useful error. See reCAPTCHA action mismatch for how to find the right string.
  • Classic task on an Enterprise key. The solve succeeds, the site's assessment does not. Check for enterprise.js first.
  • Failed solves. A task that ends in failed (for example ERROR_CAPTCHA_UNSOLVABLE) is refunded. Create a new task rather than polling the old one again.

Use this on sites you own or have permission to test. The full field list, including isSession and apiDomain, is on the reCAPTCHA v3 docs page.

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