NSLSolver
API Reference

reCAPTCHA v3

Solve reCAPTCHA v3 (and v3 Enterprise) challenges. Returns a token you verify server-side via siteverify with your secret.

reCAPTCHA v3

reCAPTCHA v3 runs invisibly — there is no checkbox or puzzle. The page calls grecaptcha.execute(site_key, { action }), Google scores the session, and hands back a token. The solver drives that flow in a real browser behind your proxy and returns the resulting token. You then verify it server-side with your secret key; the score and action checks are yours to make.

Request

FieldTypeRequiredNotes
typestringYesrecaptchav3 (or alias recaptcha-v3).
site_keystringYesThe reCAPTCHA site key (the render/data-sitekey value, usually starts 6L).
urlstringYesThe page where reCAPTCHA v3 runs. The token is bound to this URL's domain.
actionstringNoThe action name to execute. Defaults to verify if omitted — match what your backend asserts.
enterpriseboolNotrue for reCAPTCHA Enterprise (loads enterprise.js). Defaults to false (standard v3).
proxystringYesA proxy is required. http://, https://, socks4://, socks5:// schemes only.
user_agentstringNoOptional User-Agent override for the solving browser.

Unlike Turnstile, proxy is required. reCAPTCHA scores the session partly on the egress IP, so the solver routes the whole flow through your proxy. Use a clean IP — a poor reputation egress yields a low score on siteverify.

Response

{
  "success": true,
  "type": "recaptchav3",
  "token": "03AFcWeA...",
  "cost": 0.0015
}
FieldTypeNotes
successboolAlways true on 200.
typestringEchoes the request type (recaptchav3).
tokenstringThe reCAPTCHA response token. Submit it where your app expects g-recaptcha-response.
costnumberUSD deducted from your balance for this call.

Forward the token to your backend and verify it against Google's siteverify endpoint with your secret key. The token is bound to the domain of the url you submitted — the hostname field in the siteverify response will match it. The returned score and action are for you to evaluate against your own thresholds; the API does not gate on them.

Verify server-side

A token on its own proves nothing. Always call siteverify from your server with your secret, then check success, hostname, action, and score before trusting the request.

How it works (under the hood)

  1. The solver opens the target url in a real browser context, routed through your proxy.
  2. It loads reCAPTCHA's api.js (or enterprise.js when enterprise is true) for your site_key.
  3. It calls grecaptcha.execute(site_key, { action }) — using action if you sent one, otherwise the default verify.
  4. Google issues a scored token, which the solver returns.

You don't drive any of this — you just need site_key, url, and proxy.

Performance

MetricTypical value
Solve time3-6 seconds
Success rate90%+
score returned0.7-0.9 with a clean proxy

Solve time is dominated by browser startup and the proxy latency on each leg. The score you get back from siteverify depends mostly on the egress IP reputation of your proxy — residential/mobile IPs score highest, datacenter IPs lowest.

Examples

import requests

proxy = "http://user:[email protected]:8000"

r = requests.post(
    "https://api.nslsolver.com/solve",
    headers={"X-API-Key": "YOUR_KEY"},
    json={
        "type": "recaptchav3",
        "site_key": "6LcAAAAA...",
        "url": "https://www.target.com/login",
        "action": "login",
        "proxy": proxy,
    },
    timeout=120,
)
solved = r.json()
token = solved["token"]

# Verify server-side with YOUR secret before trusting it
verify = requests.post(
    "https://www.google.com/recaptcha/api/siteverify",
    data={"secret": "YOUR_SECRET", "response": token},
).json()
# verify["success"], verify["hostname"], verify["action"], verify["score"]
const proxy = "http://user:[email protected]:8000";

const r = await fetch("https://api.nslsolver.com/solve", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.NSL_API_KEY,
  },
  body: JSON.stringify({
    type: "recaptchav3",
    site_key: "6LcAAAAA...",
    url: "https://www.target.com/login",
    action: "login",
    proxy: proxy,
  }),
  signal: AbortSignal.timeout(120_000),
});

const { token } = await r.json();
// Submit `token` as g-recaptcha-response, then siteverify on your backend.
type RecaptchaReq struct {
    Type     string `json:"type"`
    SiteKey  string `json:"site_key"`
    URL      string `json:"url"`
    Action   string `json:"action,omitempty"`
    Proxy    string `json:"proxy"`
}

payload, _ := json.Marshal(RecaptchaReq{
    Type:    "recaptchav3",
    SiteKey: "6LcAAAAA...",
    URL:     "https://www.target.com/login",
    Action:  "login",
    Proxy:   "http://user:[email protected]:8000",
})

req, _ := http.NewRequest("POST", "https://api.nslsolver.com/solve", bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("NSL_API_KEY"))

client := &http.Client{Timeout: 120 * time.Second}
curl -X POST https://api.nslsolver.com/solve \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $NSL_API_KEY" \
  -d '{
    "type": "recaptchav3",
    "site_key": "6LcAAAAA...",
    "url": "https://www.target.com/login",
    "action": "login",
    "proxy": "http://user:[email protected]:8000"
  }'

For reCAPTCHA Enterprise, add "enterprise": true to any of the requests above.

Troubleshooting

SymptomLikely causeFix
site_key is requiredMissing site keySend the render/data-sitekey value (usually starts 6L).
url is requiredMissing URLSend the page URL where reCAPTCHA v3 runs.
proxy is requiredMissing proxyreCAPTCHA v3 scores partly on the egress IP — a proxy is required.
proxy format must be protocol://[user:pass@]host:portBad proxy URLUse http://, https://, socks4://, or socks5://.
Low score on siteverifyPoor proxy IP reputation, or action mismatchUse cleaner (residential) proxies; ensure action matches your check.
action mismatch on siteverifySent action ≠ the one your backend assertsSend the same action your server expects (default is verify).
hostname mismatch on siteverifySolved a different domain than you verifyUse a url on the same domain you submit the token against.
Enterprise token rejectedSite uses enterprise.js but solved standardSet "enterprise": true.

On this page