Authentication
Every API call authenticates via the X-API-Key header. Keys carry balance, allowed captcha types, CPM ceiling, and an optional IP allowlist.
Authentication
Every endpoint except the health checks requires an API key sent in the X-API-Key HTTP header.
curl https://api.nslsolver.com/balance \
-H "X-API-Key: $NSL_API_KEY"There is no query-parameter authentication. Passing the key as ?api_key=… returns 401 Unauthorized.
What a key carries
A single key encodes several access rules. You can read them all with GET /balance.
| Property | Description |
|---|---|
balance | Funds remaining, in USD. Drained per successful solve. Failures do not deduct. |
unlimited | If true, solves don't touch the balance (subject to unlimited_expires_at). |
allowed_types | Captcha types the key is allowed to solve. Requesting another type returns 403. |
max_cpm | Maximum captchas per minute, enforced via a token bucket. 0 means uncapped. |
| IP allowlist | If set, only requests originating from one of the listed IPs are accepted. Otherwise: 403. |
Code examples
curl -X POST https://api.nslsolver.com/solve \
-H "Content-Type: application/json" \
-H "X-API-Key: $NSL_API_KEY" \
-d '{"type":"turnstile","site_key":"0x4AAAAAAA","url":"https://example.com"}'import os, requests
requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": os.environ["NSL_API_KEY"]},
json={"type": "turnstile", "site_key": "0x4AAAAAAA", "url": "https://example.com"},
timeout=120,
)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: "turnstile",
site_key: "0x4AAAAAAA",
url: "https://example.com",
}),
});req, _ := http.NewRequest("POST", "https://api.nslsolver.com/solve", body)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("NSL_API_KEY"))Error responses
401 — Missing API key
{
"success": false,
"error": "Missing API key. Use X-API-Key header."
}No header was present. Add X-API-Key: <key> and resend.
401 — Invalid API key
{
"success": false,
"error": "Invalid API key"
}The key is not recognized — common causes are typos, trailing whitespace, or a key that was rotated or deleted. Verify the value end-to-end with printf '%s' "$NSL_API_KEY" | xxd | tail to spot stray newlines.
403 — IP not whitelisted
{
"success": false,
"error": "IP not whitelisted"
}The key has an IP allowlist and your egress IP is not on it. Either update the allowlist or originate the call from an allowed IP.
403 — Type not allowed
{
"success": false,
"error": "Captcha type 'kasada' is not allowed for your account"
}The requested type is missing from the key's allowed_types. Use GET /balance to inspect the list.
Repeated 401s often come from accidentally including the key inside JSON or with extra characters. Always pass it in the X-API-Key header, never the body.
Quickstart
From zero to a solved captcha in under a minute. Authenticate, check your balance, send a solve request, and use the result.
POST /solve
The single endpoint that solves Turnstile, Challenge, Kasada, and Akamai captchas. Synchronous — the response body contains the solved token, cookies, or headers.