API Tutorials

How to Solve Cloudflare Challenge with Python

Cloudflare Challenge is the full-page interstitial that shows "Checking your browser…" before granting access to a protected site. Unlike Cloudflare Turnstile (which is a form widget), the Challenge page blocks the entire resource until passed. CaptchaAI solves it and returns a cf_clearance cookie — you inject that cookie with the solver's User-Agent and the same proxy IP to access the protected page.

A proxy is mandatory for Cloudflare Challenge because the cf_clearance cookie is bound to the IP address used during solving.


What you need

Requirement Details
CaptchaAI API key captchaai.com
Python 3.7+ With requests installed
Page URL The URL showing the Cloudflare Challenge
Proxy HTTP proxy (same IP must be used for solving and subsequent requests)

Install the dependency:

pip install requests

Step 1: Identify Cloudflare Challenge

A Cloudflare Challenge page has these characteristics:

  • Full-page interstitial with "Checking your browser…" or "Just a moment…"
  • HTTP 403 or 503 status code before passing
  • The page source contains cf-browser-verification or Cloudflare challenge scripts
  • After passing, a cf_clearance cookie is set

This is different from Cloudflare Turnstile, which appears as an embedded widget on a form. If you see a small checkbox widget, use the Turnstile method instead.


Step 2: Submit the task to CaptchaAI

import requests
import time

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/protected-page"
PROXY = "user:password@111.111.111.111:8080"

# Submit the Cloudflare Challenge task
submit_response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "cloudflare_challenge",
    "pageurl": TARGET_URL,
    "proxy": PROXY,
    "proxytype": "HTTP",
    "json": 1
})

submit_data = submit_response.json()

if submit_data.get("status") != 1:
    raise RuntimeError(f"Submit failed: {submit_data.get('request')}")

task_id = submit_data["request"]
print(f"Task submitted. ID: {task_id}")

Step 3: Poll for the result

Wait 20 seconds before polling, then check every 5 seconds:

# Poll for the cf_clearance cookie
time.sleep(20)

for attempt in range(30):
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY,
        "action": "get",
        "id": task_id,
        "json": 1
    }).json()

    if result.get("status") == 1:
        cf_clearance = result["request"]
        user_agent = result.get("user_agent", "")
        print(f"cf_clearance: {cf_clearance[:60]}...")
        print(f"User-Agent: {user_agent}")
        break

    if result.get("request") != "CAPCHA_NOT_READY":
        raise RuntimeError(f"Solve failed: {result['request']}")

    print(f"Attempt {attempt + 1}: not ready, waiting 5s...")
    time.sleep(5)
else:
    raise TimeoutError("Solve timed out")

Step 4: Access the protected page

Use the cf_clearance cookie with the exact same proxy and User-Agent that the solver used:

# Access the protected page with the cf_clearance cookie
session = requests.Session()

# Set the solver's User-Agent
session.headers.update({"User-Agent": user_agent})

# Set the cf_clearance cookie
session.cookies.set("cf_clearance", cf_clearance, domain="example.com")

# Use the same proxy
proxies = {
    "http": f"http://{PROXY}",
    "https": f"http://{PROXY}"
}

response = session.get(TARGET_URL, proxies=proxies)
print(f"Status: {response.status_code}")
print(f"Content length: {len(response.text)}")

Complete working script

import requests
import time
from urllib.parse import urlparse

API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/protected-page"
PROXY = "user:password@111.111.111.111:8080"


def solve_cloudflare_challenge():
    """Solve Cloudflare Challenge and return cf_clearance + User-Agent."""

    # Submit task
    submit = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "cloudflare_challenge",
        "pageurl": TARGET_URL,
        "proxy": PROXY,
        "proxytype": "HTTP",
        "json": 1
    }).json()

    if submit.get("status") != 1:
        raise RuntimeError(f"Submit error: {submit.get('request')}")

    task_id = submit["request"]
    print(f"Task ID: {task_id}")

    # Poll for result
    time.sleep(20)
    for _ in range(30):
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY, "action": "get", "id": task_id, "json": 1
        }).json()

        if result.get("status") == 1:
            return result["request"], result.get("user_agent", "")
        if result.get("request") != "CAPCHA_NOT_READY":
            raise RuntimeError(f"Solve error: {result['request']}")
        time.sleep(5)

    raise TimeoutError("Solve timed out")


def access_protected_page(cf_clearance, user_agent):
    """Use cf_clearance cookie to access the Cloudflare-protected page."""
    domain = urlparse(TARGET_URL).hostname
    session = requests.Session()
    session.headers.update({"User-Agent": user_agent})
    session.cookies.set("cf_clearance", cf_clearance, domain=domain)

    proxies = {
        "http": f"http://{PROXY}",
        "https": f"http://{PROXY}"
    }

    response = session.get(TARGET_URL, proxies=proxies)
    return response


if __name__ == "__main__":
    clearance, ua = solve_cloudflare_challenge()
    print(f"cf_clearance: {clearance[:60]}...")

    resp = access_protected_page(clearance, ua)
    print(f"Status: {resp.status_code}")

Expected output:

Task ID: 73849562810
cf_clearance: v_5.0.21_1689012345_0_MDE2YWUx...
Status: 200

Troubleshooting

Error Cause Fix
ERROR_BAD_PROXY Proxy is dead or blocked Use a working residential proxy
ERROR_CAPTCHA_UNSOLVABLE Challenge could not be solved Verify the URL shows a Challenge page, retry with a different proxy
ERROR_PAGEURL Missing page URL Include the full URL of the Challenge page
403 after injecting cookie IP mismatch Use the same proxy for solving and subsequent requests
403 after injecting cookie User-Agent mismatch Use the exact User-Agent returned by CaptchaAI
Cookie expires quickly Cloudflare rotation cf_clearance typically lasts 15–30 minutes; re-solve when expired

FAQ

Why is a proxy mandatory for Cloudflare Challenge?

The cf_clearance cookie is bound to the IP address used during solving. If you access the site from a different IP, Cloudflare will reject the cookie.

How long does cf_clearance last?

Typically 15–30 minutes, though some sites configure shorter or longer durations. Monitor for 403 responses and re-solve when the cookie expires.

What is the difference between Cloudflare Challenge and Turnstile?

Challenge is a full-page interstitial that blocks access. Turnstile is an embedded widget on a form. Challenge returns a cf_clearance cookie; Turnstile returns a token. Challenge requires a proxy; Turnstile does not.

Can I reuse cf_clearance across multiple pages on the same domain?

Yes. The cookie is valid for the entire domain, not just the specific URL. Use it for all requests to the same site within its validity window.

What proxy type should I use?

Residential proxies have the highest success rate. Datacenter proxies may be detected and blocked by Cloudflare.


Start solving Cloudflare Challenges

Get your API key at captchaai.com. Use method=cloudflare_challenge with a proxy to get cf_clearance cookies.


Full Working Code

Complete runnable examples for this article in Python, Node.js, PHP, Go, Java, C#, Ruby, Rust, Kotlin & Bash.

View on GitHub →

Discussions (0)

No comments yet.