Cloudflare's Managed Challenge (also called JS Challenge) is the full-page "Checking your browser" interstitial that blocks bots. Unlike Turnstile, which returns a token, the Challenge sets cf_clearance cookies that are bound to a specific IP address. In this tutorial, you'll learn how to bypass it using Python, a proxy, and the NSLSolver API.
Challenge vs Turnstile — what's the difference?
Turnstile is an embeddable widget that returns a token you submit with a form. Challenge is a full-page interstitial that sets cf_clearance cookies tied to the visitor's IP. Because the cookies are IP-bound, you must use a proxy when solving — and use the same proxy for subsequent requests.
Prerequisites
- Python 3.7 or higher installed
- requests library (pip install requests)
- A working HTTP/HTTPS proxy (cookies are IP-bound)
- 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 with your proxy
Send a POST request with type "challenge", the target URL, and your proxy. The proxy is required because cf_clearance cookies are bound to the IP that solved the challenge:
import requests
API_KEY = "nsl_YOUR_API_KEY"
response = requests.post(
"https://api.nslsolver.com/solve",
headers={"X-API-Key": API_KEY},
json={
"type": "challenge",
"url": "https://example.com/protected-page",
"proxy": "http://user:[email protected]:8080"
}
)
data = response.json()
print(data["cookies"])
print(data["user_agent"])Important: The proxy field is required for challenge solving. The cf_clearance cookie will only work when requests come from the same IP address that was used during the solve. If you omit the proxy or use a different one for subsequent requests, Cloudflare will reject the cookie.
The API returns cookies and a user_agent that you must use together:
{
"success": true,
"cookies": {
"cf_clearance": "aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
},
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"cost": 0.002
}Step 4: Use the cookies with the same proxy
Make requests to the protected page using the returned cookies, user agent, and the same proxy. All three must match for Cloudflare to accept the request:
# After getting cookies + user_agent from NSLSolver:
cookies = data["cookies"]
user_agent = data["user_agent"]
# Use the SAME proxy that was used to solve
proxies = {
"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080"
}
# Make request with matching cookies, user agent, and proxy
result = requests.get(
"https://example.com/protected-page",
headers={"User-Agent": user_agent},
cookies=cookies,
proxies=proxies
)
print(result.status_code) # 200 = success!Complete example with error handling
Here's a production-ready example with retries, error handling, and a requests.Session for cookie persistence:
import requests
import time
API_KEY = "nsl_YOUR_API_KEY"
TARGET_URL = "https://example.com/protected-page"
PROXY = "http://user:[email protected]:8080"
def solve_challenge(url, proxy, retries=3):
"""Solve a Cloudflare 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": "challenge",
"url": url,
"proxy": proxy
},
timeout=60
)
resp.raise_for_status()
data = resp.json()
if data.get("success"):
return data
print(f"Attempt {attempt + 1} failed: {data}")
except requests.RequestException as e:
print(f"Request error: {e}")
if attempt < retries - 1:
time.sleep(3)
return None
# Solve the challenge
solution = solve_challenge(TARGET_URL, PROXY)
if solution:
print("Challenge solved! Fetching protected page...")
# Build session with solved cookies + user agent
session = requests.Session()
session.headers["User-Agent"] = solution["user_agent"]
session.cookies.update(solution["cookies"])
session.proxies = {
"http": PROXY,
"https": PROXY
}
# Fetch the protected page
result = session.get(TARGET_URL)
print(f"Status: {result.status_code}")
print(result.text[:500])
else:
print("Failed to solve challenge after retries.")Common errors
HTTP status codes you may encounter when calling the API:
- 401Invalid API key. Check your X-API-Key header.
- 402Insufficient balance. Add funds to your account.
- 422Missing required field. For challenge type, both "url" and "proxy" are required.
- 429Rate limited. Back off and retry after a short delay.
- 500Server error. Retry the request. If persistent, contact support.
Pro tip: Use sticky/static proxies for challenge solving. Rotating proxies will break the IP binding and make the cf_clearance cookie useless. The cookie typically lasts 15-30 minutes, so you can reuse it for multiple requests within that window.
Ready to bypass Cloudflare Challenge?
Create a free account and get 100 requests to try it out. No credit card required.