Quickstart
From zero to a solved captcha in under a minute. Authenticate, check your balance, send a solve request, and use the result.
Grab your API key
API keys are provisioned from the dashboard or by an admin. A key encodes:
- A balance (or unlimited flag)
- A list of allowed captcha types
- A maximum captchas-per-minute (CPM) ceiling
- An optional IP allowlist
Treat the key like a password. Don't ship it in client-side bundles or commit it to source control.
The key is sent in the X-API-Key header on every request. There is no query-parameter fallback — passing the key in the URL will return 401.
Confirm you're set up
Hit GET /balance to verify the key works and read the limits it carries:
curl https://api.nslsolver.com/balance \
-H "X-API-Key: $NSL_API_KEY"A healthy response looks like this:
{
"success": true,
"balance": 14.50,
"unlimited": false,
"allowed_types": ["turnstile", "challenge", "kasada", "akamai"],
"max_cpm": 600,
"current_cpm": 0,
"cpm_limit": 600
}The fields that matter for sizing your workers:
max_cpm— your absolute ceiling, in captchas per minute.current_cpm— how many you've already used in the rolling window.cpm_limit— same asmax_cpm, included for symmetry.
Send your first solve
Pick the captcha type you're up against. The request shape changes per type — see the solve reference for the full schema.
import requests
r = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": "YOUR_KEY"},
json={
"type": "turnstile",
"site_key": "0x4AAAAAAAB...",
"url": "https://example.com",
},
timeout=120,
)
data = r.json()
print(data["token"])Needed fields: type, site_key, url. Everything else is optional — see the Turnstile page for the full list.
import requests
r = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": "YOUR_KEY"},
json={
"type": "challenge",
"url": "https://example.com/protected",
"proxy": "http://user:[email protected]:8080",
},
timeout=120,
)
data = r.json()
print(data["cookies"]["cf_clearance"])A proxy is required for Challenge — the solver uses it as the egress so the resulting cf_clearance is valid for your traffic.
import requests
r = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": "YOUR_KEY"},
json={
"type": "kasada",
"url": "https://passport.twitch.tv",
"user_agent": "Mozilla/5.0 ... Chrome/145.0.0.0 Safari/537.36",
"ua_version": 145,
"kasada_config": {
"p_js_path": "/149e9513-.../2d206a39-.../p.js",
"fp_host": "passport.twitch.tv",
"tl_host": "gql.twitch.tv"
}
},
timeout=180,
)
print(r.json()["headers"])Kasada needs the p.js path and the FP/TL hosts you can find in DevTools. The response contains the x-kpsdk-* headers to forward on your next request.
Use the result
Each captcha type returns a slightly different payload. Replay it back at the protected site exactly as you would if a real browser had solved it.
{
"success": true,
"type": "turnstile",
"token": "0.AkBr7...",
"cost": 0.0008
}Submit token in the form field the site expects (commonly cf-turnstile-response).
{
"success": true,
"type": "challenge",
"cookies": { "cf_clearance": "abc123..." },
"user_agent": "Mozilla/5.0 ...",
"cost": 0.001
}Send the cookie back on subsequent requests from the same proxy IP and using the returned user_agent. The clearance is bound to both.
{
"success": true,
"type": "kasada",
"headers": {
"x-kpsdk-ct": "...",
"x-kpsdk-cd": "...",
"x-kpsdk-v": "j-1.2.xxx",
"x-kpsdk-h": "..."
},
"cost": 0.0015
}Forward the x-kpsdk-* headers on your next request to the protected origin, keeping the same User-Agent.
The cost field tells you what was deducted for this call — useful for instrumentation.
Common pitfalls
- Client timeouts that are too short. Most solves finish in seconds, but the server allows up to ~120 seconds for Turnstile/Challenge and ~180 seconds for Kasada. Use 120s (180s for Kasada) as your client timeout.
- Reusing a
cf_clearancefrom a different IP. Cloudflare binds the cookie to the egress IP from the proxy you used during the solve. Use the same proxy when replaying. - Calling /balance in a hot loop. That endpoint is per-IP rate limited (30/min). Check it on startup, not per request.
Next up
- Authentication — header, IP allowlists, allowed types.
- Solve endpoint — every parameter with validation rules.
- Errors — every status code with retry guidance.
- Rate limits — how the CPM bucket works.