NSLSolver
Guides

Proxies

When to use a proxy, what formats are accepted, residential vs datacenter trade-offs, and how to keep cf_clearance valid.

Proxies

Pass a proxy via the proxy field in your /solve body. The solver uses it for the entire solve, so the resulting token/cookies/headers reflect that egress IP.

Accepted formats

The server validates against this regex:

(http|https|socks4|socks5)://([user:pass@])?host:port
SchemeExample
httphttp://host:8080
httphttp://user:pass@host:8080
httpshttps://user:pass@host:8443
socks4socks4://host:1080
socks5socks5://user:pass@host:1080

Validation also enforces:

  • Port between 1 and 65535.
  • The host must be public — proxies pointing at loopback, private (RFC1918), link-local, or .local/.internal hosts are rejected with 400.
  • Max length 512 chars.

When to use a proxy

ScenarioProxy?
Cloudflare Challenge targetRequired
Turnstile on a geo-blocked pageRecommended
Kasada on a geo-blocked targetRecommended
You'll replay cf_clearance with a specific IPRequired, matched
You'll replay headers from a specific countryRecommended, matched
You're saturating an IP-based per-source rate limitRequired (rotate)

For Challenge, the proxy is mandatory because the issued cf_clearance is bound to its egress IP. Replaying it from any other IP is rejected by Cloudflare.

Residential vs datacenter

FactorResidentialDatacenter
IP reputationHigh — owned by real ISPsLower — known hosting ranges
Detection riskLowHigher (varies by provider)
SpeedVariableFast, consistent
CostHigher (per GB)Lower (per IP / per GB)
Best forHeavily protected sitesHigh-volume, lighter protection

Default to datacenter for cost. Switch to residential only when you measure elevated failure rates on the target site.

Examples

Python
import requests

requests.post(
    "https://api.nslsolver.com/solve",
    headers={"X-API-Key": "YOUR_KEY"},
    json={
        "type": "turnstile",
        "site_key": "0x4AAAAAAA",
        "url": "https://example.com",
        "proxy": "http://user:[email protected]:8080",
    },
    timeout=120,
)
Node.js
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: "challenge",
    url: "https://example.com/protected",
    proxy: "socks5://user:[email protected]:1080",
  }),
});
cURL
curl -X POST https://api.nslsolver.com/solve \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $NSL_API_KEY" \
  -d '{
    "type": "challenge",
    "url": "https://example.com/protected",
    "proxy": "http://user:[email protected]:8080"
  }'

Keeping cf_clearance valid

Cloudflare binds the clearance cookie to the egress IP and the User-Agent used during the solve. To keep it usable:

  1. Send the solve through your real proxy (the same one your downstream traffic goes through).
  2. Capture the returned user_agent.
  3. On the downstream request: set the cf_clearance cookie, use that exact User-Agent, and route through the same proxy.

A mismatch on any of those three points invalidates the cookie immediately.

Common 400 messages

{ "success": false, "error": "proxy format must be protocol://[user:pass@]host:port" }
{ "success": false, "error": "proxy port must be 1-65535" }
{ "success": false, "error": "proxy must not target internal addresses" }

Fix the URL and resend.

Rotation

For high volume, rotate across a pool of proxies. The simplest approach is round-robin:

from itertools import cycle

proxies = cycle([
    "http://u:p@proxy1:8080",
    "http://u:p@proxy2:8080",
    "http://u:p@proxy3:8080",
])

def solve_payload(site_key, url):
    return {
        "type": "turnstile",
        "site_key": site_key,
        "url": url,
        "proxy": next(proxies),
    }

For Challenge solves you'll need to track which proxy issued each clearance cookie, since replaying requires the same IP.

On this page