Cloudflare Turnstile is one of the most common CAPTCHAs on the web. In this tutorial, you'll learn how to bypass it programmatically using Python and the NSLSolver API. We'll go from zero to a working solution in under 5 minutes.
Prerequisites
- Python 3.7 or higher installed
- requests library (pip install requests)
- An NSLSolver API key — sign up free
Step 1: Install dependencies
You only need the requests library. Install it with pip:
Step 2: Get your API key
To use the NSLSolver API, you need an API key:
- Create a free account at nslsolver.com
- Verify your email to get 100 free requests
- Copy your API key from the dashboard
Step 3: Send a solve request
Here's the minimal code to solve a Turnstile CAPTCHA:
import requests
API_KEY = "nsl_YOUR_API_KEY"
response = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": API_KEY},
json={
"type": "turnstile",
"siteKey": "0x4XXXXXXXXXXXXXXXXX",
"url": "https://example.com"
}
)
data = response.json()
print(data["token"])The API returns a JSON response with the solved token:
{
"success": true,
"token": "1.AgAAAIxD...a_long_token_string",
"cost": 0.001
}Step 4: Use the token
Now submit the token along with your form data to the target site:
# After getting the token from NSLSolver:
token = data["token"]
# Submit the form with the solved token
result = requests.post(
"https://example.com/login",
data={
"username": "[email protected]",
"password": "your_password",
"cf-turnstile-response": token
}
)
print(result.status_code)Complete example with error handling
Here's a production-ready example with retries and error handling:
import requests
import time
API_KEY = "nsl_YOUR_API_KEY"
SITE_KEY = "0x4XXXXXXXXXXXXXXXXX"
PAGE_URL = "https://example.com/protected-page"
def solve_turnstile(site_key, url, retries=3):
"""Solve a Cloudflare Turnstile challenge via NSLSolver."""
for attempt in range(retries):
try:
resp = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": API_KEY},
json={
"type": "turnstile",
"siteKey": site_key,
"url": url
},
timeout=30
)
resp.raise_for_status()
data = resp.json()
if data.get("success"):
return data["token"]
print(f"Attempt {attempt + 1} failed: {data}")
except requests.RequestException as e:
print(f"Request error: {e}")
if attempt < retries - 1:
time.sleep(2)
return None
# Solve and use the token
token = solve_turnstile(SITE_KEY, PAGE_URL)
if token:
print("Got token, submitting form...")
result = requests.post(
PAGE_URL,
data={"cf-turnstile-response": token}
)
print(f"Status: {result.status_code}")
else:
print("Failed to solve turnstile after retries.")Error handling
Common HTTP status codes you may encounter:
- 401Invalid API key. Check your X-API-Key header.
- 402Insufficient balance. Add funds to your account.
- 429Rate limited. Back off and retry after a short delay.
- 500Server error. Retry the request. If persistent, contact support.
Pro tip: Always implement retry logic. Transient failures are rare but possible. The complete example above handles this automatically.
Ready to start solving?
Create a free account and get 100 requests to try it out. No credit card required.