NSLSolver
API Reference

Cloudflare Turnstile

Solve Cloudflare Turnstile widgets. Required parameters, how to locate the site key, and how to use the returned token.

Cloudflare Turnstile

Turnstile is Cloudflare's lightweight bot check. It exposes a public site_key on the page and expects a token to be submitted back through a form or API call.

Request

FieldTypeRequiredNotes
typestringYesturnstile (or the alias cloudflare-turnstile).
site_keystringYesThe data-sitekey value embedded in the page. [a-zA-Z0-9_-]{1,128}.
urlstringYesPage URL — http/https, public host, max 2048 chars.
actionstringNoPass through if the site sets data-action.
cdatastringNoPass through if the site sets data-cdata.
proxystringNoOptional. Most Turnstile pages don't need one.
user_agentstringNoUse the same UA you'll replay the token with.

Response

{
  "success": true,
  "type": "turnstile",
  "token": "0.AkBr7...",
  "cost": 0.0008
}

Submit the token in the form field the site expects — usually cf-turnstile-response or the name of the input rendered next to the widget.

Finding the site key

Most Turnstile widgets render a div with data-sitekey:

<div class="cf-turnstile" data-sitekey="0x4AAAAAAAB..."></div>

If you don't see it in the static HTML:

  1. Open DevTools, switch to Elements, and search for cf-turnstile or data-sitekey.
  2. If the widget is mounted by JavaScript, search the JS bundles for sitekey: or turnstile.render(.
  3. As a last resort, watch the Network tab and filter for challenges.cloudflare.com — the site key appears in the URL of the iframe.

JS-rendered widgets

When turnstile.render() is called dynamically, the page may also pass action and cdata arguments. Capture those too — submitting a token solved without the matching action/cdata will be rejected.

Performance

MetricTypical value
Solve time~1 second
Token lifetime~300 seconds
Success rate99.9%

Token lifetime is set by the target site — use it promptly.

Examples

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/login",
        "action": "login",
    },
    timeout=120,
)
token = r.json()["token"]

# Replay
requests.post(
    "https://example.com/login",
    data={
        "username": "[email protected]",
        "password": "password",
        "cf-turnstile-response": token,
    },
)
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: "turnstile",
    site_key: "0x4AAAAAAAB...",
    url: "https://example.com/login",
    action: "login",
  }),
  signal: AbortSignal.timeout(120_000),
});

const { token } = await r.json();
payload, _ := json.Marshal(map[string]string{
    "type":     "turnstile",
    "site_key": "0x4AAAAAAAB...",
    "url":      "https://example.com/login",
    "action":   "login",
})

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"))
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": "0x4AAAAAAAB...",
    "url": "https://example.com/login",
    "action": "login"
  }'

Troubleshooting

SymptomLikely causeFix
Site rejects token immediatelyToken expiredUse it within ~300s of receiving it.
Site rejects token after delayMissing action or cdataInspect the widget for data-action/data-cdata and pass them.
Repeated Solve failed (503)Wrong site_keyConfirm against the live HTML — sites rotate keys occasionally.
Solves work but downstream login failsUA mismatchPass the same user_agent you use on the form submission.

On this page