Skip to content

cloudflyer-project/cloudflyer-python-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CFSolver

PyPI version Python 3.8+ License: MIT

Python HTTP client that automatically bypasses Cloudflare challenges using the CloudFlyer API.

Features

  • Drop-in replacement for requests and httpx - minimal code changes required
  • Automatic challenge detection - detects Cloudflare protection and solves transparently
  • Multiple solving modes - auto-detect, always pre-solve, or disable
  • Turnstile support - solve Cloudflare Turnstile CAPTCHA and get tokens
  • Transparent proxy mode - automatic bypass for any HTTP client without code changes
  • Proxy support - HTTP/HTTPS/SOCKS5 proxies for both requests and API calls
  • Browser impersonation - TLS fingerprint mimicking via curl-impersonate
  • Async support - full async/await API for high-performance applications
  • Command-line interface - quick operations without writing code

Installation

# Basic installation
pip install cfsolver

# With transparent proxy support (requires mitmproxy)
pip install cfsolver[proxy]

# All features
pip install cfsolver[all]

Quick Start

Python API

Works just like requests, but automatically handles Cloudflare challenges:

from cfsolver import CloudflareSolver

solver = CloudflareSolver("your-api-key")
response = solver.get("https://protected-site.com")
print(response.text)

Command Line

# Set API key
export CLOUDFLYER_API_KEY="your-api-key"

# Make a request with automatic bypass
cfsolver request https://protected-site.com

# Start transparent proxy
cfsolver proxy -P 8080

Table of Contents


Python API

CloudflareSolver

The main synchronous client for bypassing Cloudflare challenges.

from cfsolver import CloudflareSolver

# Basic usage with context manager (recommended)
with CloudflareSolver("your-api-key") as solver:
    response = solver.get("https://protected-site.com")
    print(response.status_code)
    print(response.text)

# Without context manager
solver = CloudflareSolver("your-api-key")
response = solver.get("https://protected-site.com")
solver.close()

Supported HTTP Methods

solver.get(url, **kwargs)
solver.post(url, **kwargs)
solver.put(url, **kwargs)
solver.delete(url, **kwargs)
solver.head(url, **kwargs)
solver.options(url, **kwargs)
solver.patch(url, **kwargs)
solver.request(method, url, **kwargs)

All methods accept the same keyword arguments as curl_cffi.requests:

response = solver.post(
    "https://api.example.com/data",
    json={"key": "value"},
    headers={"Authorization": "Bearer token"},
    timeout=30,
)

AsyncCloudflareSolver

Async version for use with asyncio:

import asyncio
from cfsolver import AsyncCloudflareSolver

async def main():
    async with AsyncCloudflareSolver("your-api-key") as solver:
        response = await solver.get("https://protected-site.com")
        print(response.text)

asyncio.run(main())

Concurrent Requests

import asyncio
from cfsolver import AsyncCloudflareSolver

async def fetch_all():
    urls = [
        "https://site1.com",
        "https://site2.com",
        "https://site3.com",
    ]
    
    async with AsyncCloudflareSolver("your-api-key") as solver:
        tasks = [solver.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        
        for url, resp in zip(urls, responses):
            print(f"{url}: {resp.status_code}")

asyncio.run(fetch_all())

Solving Modes

CFSolver supports three solving modes to balance speed and reliability:

Mode 1: Auto-detect (Default, Recommended)

Solves only when a Cloudflare challenge is detected. Best for most use cases.

solver = CloudflareSolver("your-api-key")
# or explicitly:
solver = CloudflareSolver("your-api-key", solve=True, on_challenge=True)

Mode 2: Always Pre-solve

Always solves before each request. Slower but most reliable for heavily protected sites.

solver = CloudflareSolver("your-api-key", solve=True, on_challenge=False)

Mode 3: Disabled

Direct requests only, no challenge solving. Useful for testing or unprotected endpoints.

solver = CloudflareSolver("your-api-key", solve=False)

Turnstile Support

Solve Cloudflare Turnstile CAPTCHA and get the token for form submission:

from cfsolver import CloudflareSolver

with CloudflareSolver("your-api-key") as solver:
    # Get the Turnstile token
    token = solver.solve_turnstile(
        url="https://example.com/login",
        sitekey="0x4AAAAAAA..."  # From cf-turnstile element
    )
    
    # Use the token in your form submission
    response = solver.post(
        "https://example.com/login",
        data={
            "username": "user",
            "password": "pass",
            "cf-turnstile-response": token,
        }
    )

Finding the Sitekey

The sitekey is found in the page's HTML within the cf-turnstile element:

<div class="cf-turnstile" data-sitekey="0x4AAAAAAA..."></div>

Proxy Configuration

Single Proxy for All Requests

solver = CloudflareSolver(
    "your-api-key",
    proxy="http://proxy.example.com:8080"
)

Separate Proxies for HTTP and API

Use different proxies for your HTTP requests and CloudFlyer API calls:

solver = CloudflareSolver(
    "your-api-key",
    proxy="http://fast-proxy:8080",      # For your HTTP requests
    api_proxy="http://stable-proxy:8081"  # For CloudFlyer API calls
)

Supported Proxy Formats

# HTTP proxy
proxy="http://host:port"
proxy="http://user:pass@host:port"

# HTTPS proxy
proxy="https://host:port"

# SOCKS5 proxy
proxy="socks5://host:port"
proxy="socks5://user:pass@host:port"

Transparent Proxy

The transparent proxy automatically detects and solves Cloudflare challenges for any application that supports HTTP proxies, without requiring code changes.

How It Works

  1. Start the CFSolver proxy server
  2. Configure your application to use the proxy
  3. All requests are automatically monitored for Cloudflare challenges
  4. When a challenge is detected, it's solved transparently
  5. The cf_clearance cookie is cached and reused for subsequent requests

Command Line Usage

# Start proxy on default port 8080
cfsolver proxy

# Custom host and port
cfsolver proxy -H 0.0.0.0 -P 8888

# With upstream proxy (for requests going through another proxy)
cfsolver proxy -X http://upstream:8080
cfsolver proxy -X socks5://upstream:1080

# Disable challenge detection (pure proxy mode)
cfsolver proxy -D

# Disable cookie caching (solve every challenge)
cfsolver proxy -S

Then use the proxy with any HTTP client:

Note: Since the transparent proxy performs HTTPS interception (MITM), you must disable SSL certificate verification.

# curl (use -k to skip certificate verification)
curl -k -x http://127.0.0.1:8080 https://protected-site.com

# wget (use --no-check-certificate to skip certificate verification)
wget --no-check-certificate -e https_proxy=http://127.0.0.1:8080 https://protected-site.com

# Environment variables
export HTTP_PROXY=http://127.0.0.1:8080
export HTTPS_PROXY=http://127.0.0.1:8080
curl -k https://protected-site.com

Programmatic Usage

from cfsolver import CloudAPITransparentProxy
import requests

# Using context manager
with CloudAPITransparentProxy(api_key="your-api-key", port=8080) as proxy:
    response = requests.get(
        "https://protected-site.com",
        proxies={
            "http": "http://127.0.0.1:8080",
            "https": "http://127.0.0.1:8080"
        },
        verify=False,  # Required for HTTPS interception
    )
    print(response.text)

# Manual start/stop
proxy = CloudAPITransparentProxy(api_key="your-api-key", port=8080)
proxy.start()

# ... make requests ...

proxy.stop()

Managing cf_clearance Cache

with CloudAPITransparentProxy(api_key="your-api-key", port=8080) as proxy:
    # Pre-set cf_clearance for a host
    proxy.set_cf_clearance("example.com", "Mozilla/5.0...", "cf_clearance_value")
    
    # Get stored cf_clearance
    cf_value = proxy.get_cf_clearance("example.com", "Mozilla/5.0...")
    
    # Clear cache for specific host
    proxy.clear_cf_clearance("example.com")
    
    # Clear all cache
    proxy.clear_cf_clearance()

Proxy Options

Parameter Type Default Description
api_key str required CloudFlyer API key
api_base str https://solver.zetx.site CloudFlyer API base URL
host str 127.0.0.1 Listen address
port int 8080 Listen port
user_proxy str None Upstream proxy for forwarding requests
api_proxy str None Proxy for CloudFlyer API calls
impersonate str chrome Browser to impersonate
enable_detection bool True Enable challenge detection
no_cache bool False Disable cf_clearance caching
timeout int 120 Challenge solve timeout (seconds)
extra_title_indicators list None Additional title patterns for detection
extra_cf_indicators list None Additional CF-specific indicators

Command Line Interface

CFSolver provides a comprehensive CLI for common operations.

Global Options

cfsolver --help                    Show help
cfsolver --version                 Show version
cfsolver -v <command>              Enable verbose output

Common Options

These options are available for most commands:

-K, --api-key       API key (or set CLOUDFLYER_API_KEY env var)
-B, --api-base      API base URL (default: https://solver.zetx.site)
-X, --proxy         Proxy for HTTP requests (scheme://host:port)
--api-proxy         Proxy for API calls (scheme://host:port)
-I, --impersonate   Browser to impersonate (default: chrome)

solve cloudflare

Solve a Cloudflare challenge and get cookies/user-agent:

# Basic usage
cfsolver solve cloudflare https://protected-site.com

# With options
cfsolver solve cloudflare -K your-api-key https://protected-site.com

# Output as JSON
cfsolver solve cloudflare --json https://protected-site.com

# With proxy
cfsolver solve cloudflare -X http://proxy:8080 https://protected-site.com

# With timeout
cfsolver solve cloudflare -T 180 https://protected-site.com

Output (normal):

[+] Challenge solved successfully!
    Status: 200
    Cookies: {'cf_clearance': '...'}
    User-Agent: Mozilla/5.0...

Output (JSON):

{
  "success": true,
  "url": "https://protected-site.com",
  "status_code": 200,
  "cookies": {"cf_clearance": "..."},
  "user_agent": "Mozilla/5.0..."
}

solve turnstile

Solve a Turnstile challenge and get the token:

# Basic usage
cfsolver solve turnstile https://example.com 0x4AAAAAAA...

# Output as JSON
cfsolver solve turnstile --json https://example.com 0x4AAAAAAA...

# With timeout
cfsolver solve turnstile -T 180 https://example.com 0x4AAAAAAA...

Arguments:

  • URL: Website URL containing the Turnstile widget
  • SITEKEY: Turnstile site key (from data-sitekey attribute)

Output:

[+] Turnstile solved successfully!
    Token: 0.xxx...
    Token length: 2048

request

Make HTTP requests with automatic challenge bypass:

# Simple GET request
cfsolver request https://protected-site.com

# POST request with JSON data
cfsolver request -m POST -d '{"key":"value"}' https://api.example.com

# With custom headers
cfsolver request -H "Authorization: Bearer token" https://api.example.com
cfsolver request -H "Content-Type: application/json" -H "X-Custom: value" https://api.example.com

# Save response to file
cfsolver request -o output.html https://protected-site.com

# Output response info as JSON
cfsolver request --json https://protected-site.com

Options:

-m, --method    HTTP method (default: GET)
-d, --data      Request body data
-H, --header    Request header (can be used multiple times)
-o, --output    Output file path
--json          Output response info as JSON

proxy

Start the transparent proxy server:

# Default settings (127.0.0.1:8080)
cfsolver proxy

# Custom host and port
cfsolver proxy -H 0.0.0.0 -P 8888

# With upstream proxy
cfsolver proxy -X http://upstream:8080
cfsolver proxy -X socks5://127.0.0.1:1080

# Disable challenge detection (pure proxy mode)
cfsolver proxy -D

# Disable cf_clearance caching
cfsolver proxy -S

# Custom timeout
cfsolver proxy -T 180

Options:

-H, --host              Listen address (default: 127.0.0.1)
-P, --port              Listen port (default: 8080)
-X, --proxy             Upstream proxy for all requests
--api-proxy             Proxy for API calls
-I, --impersonate       Browser to impersonate (default: chrome)
-D, --disable-detection Disable challenge detection
-S, --no-cache          Disable cf_clearance caching
-T, --timeout           Challenge solve timeout (default: 120)

balance

Check your CloudFlyer account balance:

cfsolver balance

Output:

[+] Balance: 100.00

Configuration

Parameters

CloudflareSolver / AsyncCloudflareSolver

Parameter Type Default Description
api_key str required Your CloudFlyer API key
api_base str https://solver.zetx.site CloudFlyer service URL
solve bool True Enable challenge solving
on_challenge bool True Solve only on challenge detection
proxy str None Proxy for HTTP requests
api_proxy str None Proxy for API calls
impersonate str chrome Browser to impersonate
use_polling bool False Use interval polling instead of long-polling

Impersonation Options

The impersonate parameter accepts browser identifiers supported by curl_cffi:

  • chrome (default)
  • chrome110, chrome116, chrome120, etc.
  • firefox
  • safari
  • edge

Environment Variables

Variable Description
CLOUDFLYER_API_KEY Default API key for all operations
CLOUDFLYER_API_BASE Default API base URL
# Set environment variables
export CLOUDFLYER_API_KEY="your-api-key"
export CLOUDFLYER_API_BASE="https://solver.zetx.site"

# Now you can use cfsolver without -K option
cfsolver request https://protected-site.com

Exceptions

CFSolver defines specific exceptions for different error scenarios:

from cfsolver import (
    CFSolverError,           # Base exception
    CFSolverAPIError,        # API request failed
    CFSolverChallengeError,  # Challenge solving failed
    CFSolverTimeoutError,    # Operation timed out
    CFSolverConnectionError, # Connection to service failed
    CFSolverProxyError,      # Transparent proxy error
)

Exception Handling

from cfsolver import CloudflareSolver, CFSolverChallengeError, CFSolverTimeoutError

try:
    with CloudflareSolver("your-api-key") as solver:
        response = solver.get("https://protected-site.com")
except CFSolverChallengeError as e:
    print(f"Failed to solve challenge: {e}")
except CFSolverTimeoutError as e:
    print(f"Operation timed out: {e}")
except CFSolverConnectionError as e:
    print(f"Connection failed: {e}")

Examples

Run Example Scripts

set CLOUDFLYER_API_KEY=your_api_key
set CLOUDFLYER_API_BASE=https://solver.zetx.site

python examples/sdk_challenge.py
python examples/sdk_turnstile.py

python examples/sdk_challenge.py --proxy http://user:pass@host:port
python examples/sdk_turnstile.py --proxy http://user:pass@host:port

Basic Challenge Bypass

import os
from cfsolver import CloudflareSolver

api_key = os.environ.get("CLOUDFLYER_API_KEY")

with CloudflareSolver(api_key) as solver:
    response = solver.get("https://protected-site.com")
    
    if response.status_code == 200:
        print("Success!")
        print(f"Cookies: {dict(solver._session.cookies)}")

Turnstile Token for Login

from cfsolver import CloudflareSolver

with CloudflareSolver("your-api-key") as solver:
    # Solve Turnstile
    token = solver.solve_turnstile(
        "https://example.com/login",
        "0x4AAAAAAA..."
    )
    
    # Submit login form with token
    response = solver.post(
        "https://example.com/login",
        data={
            "email": "user@example.com",
            "password": "password",
            "cf-turnstile-response": token,
        }
    )

Async Scraping

import asyncio
from cfsolver import AsyncCloudflareSolver

async def scrape_pages():
    urls = [
        "https://site.com/page1",
        "https://site.com/page2",
        "https://site.com/page3",
    ]
    
    async with AsyncCloudflareSolver("your-api-key") as solver:
        for url in urls:
            response = await solver.get(url)
            print(f"{url}: {len(response.text)} bytes")

asyncio.run(scrape_pages())

Transparent Proxy with requests

from cfsolver import CloudAPITransparentProxy
import requests

with CloudAPITransparentProxy(api_key="your-api-key", port=8080) as proxy:
    session = requests.Session()
    session.proxies = {
        "http": "http://127.0.0.1:8080",
        "https": "http://127.0.0.1:8080",
    }
    session.verify = False
    
    # All requests through this session will auto-bypass Cloudflare
    response = session.get("https://protected-site.com")
    print(response.text)

Using with Scrapy

# In your Scrapy settings.py
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,
}

HTTP_PROXY = 'http://127.0.0.1:8080'
HTTPS_PROXY = 'http://127.0.0.1:8080'

# Disable SSL certificate verification (required for transparent proxy)
DOWNLOAD_HANDLERS = {
    "https": "scrapy.core.downloader.handlers.http2.H2DownloadHandler",
}
DOWNLOADER_CLIENT_TLS_VERIFY_MODE = "CERT_NONE"

# Start cfsolver proxy before running Scrapy:
# cfsolver proxy -P 8080

Using with httpx

import httpx

# Disable SSL verification when using transparent proxy
with httpx.Client(
    proxy="http://127.0.0.1:8080",
    verify=False,  # Required for HTTPS interception
) as client:
    response = client.get("https://protected-site.com")
    print(response.text)

# Async version
async with httpx.AsyncClient(
    proxy="http://127.0.0.1:8080",
    verify=False,
) as client:
    response = await client.get("https://protected-site.com")
    print(response.text)

Using with aiohttp

import aiohttp
import ssl

# Create SSL context that doesn't verify certificates
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

async with aiohttp.ClientSession() as session:
    async with session.get(
        "https://protected-site.com",
        proxy="http://127.0.0.1:8080",
        ssl=ssl_context,  # Required for HTTPS interception
    ) as response:
        print(await response.text())

Requirements

  • Python 3.8+
  • curl_cffi>=0.7.0 - HTTP client with browser impersonation
  • pywssocks>=1.5.0 - WebSocket SOCKS tunnel for challenge solving
  • click>=8.0.0 - CLI framework

Optional Dependencies

  • mitmproxy>=10.0.0 - Required for transparent proxy mode (pip install cfsolver[proxy])

License

MIT License - see LICENSE for details.


Links

About

Cloudflyer SDK for solving Cloudflare captchas.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages