Tutorial

How to Bypass Cloudflare Challenge (Managed Challenge) with Python

2026-04-146 min read

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:

terminal
$pip install requests

Step 2: Get your API key

To use the NSLSolver API, you need an API key:

  1. Create a free account at nslsolver.com
  2. Verify your email to get 100 free requests
  3. 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:

solve_challenge.py
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:

response.json
{
  "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:

use_cookies.py
# 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:

challenge_bypass.py
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.