spyderproxy

FlareSolverr: The Definitive Guide (Python + Cloudflare)

A

Alex R.

|
Published date

Sun May 10 2026

Quick verdict: FlareSolverr is the right tool when Cloudscraper fails — specifically against Cloudflare Turnstile, Bot Fight Mode, and JavaScript-heavy challenges. It runs a real headless Chrome (via undetected-chromedriver) inside Docker, so it is heavier than Cloudscraper but covers cases Cloudscraper cannot. The workflow: spin up FlareSolverr as a Docker container on localhost:8191, POST your target URL to it, get back the solved HTML + clearance cookies, then continue with normal requests.

When to Use FlareSolverr

ScenarioTool
Old "Just a moment..." JS challengeCloudscraper (lighter)
TLS fingerprint blockscurl_cffi with Chrome impersonation
Cloudflare TurnstileFlareSolverr
Bot Fight Mode (aggressive)FlareSolverr + residential proxies
Interactive "click to verify"FlareSolverr with CAPTCHA solver
Heavy JS rendering / SPAsPlaywright directly

Docker Setup

FlareSolverr runs as a Docker container. Install Docker first (docs.docker.com/get-docker), then:

docker run -d   --name flaresolverr   -p 8191:8191   -e LOG_LEVEL=info   -e TZ=UTC   ghcr.io/flaresolverr/flaresolverr:latest

Verify it is running:

curl http://localhost:8191/
# {"msg":"FlareSolverr is ready!","version":"3.x.x","userAgent":"..."}

For docker-compose (recommended for stable deployments):

version: "3"
services:
  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:latest
    container_name: flaresolverr
    environment:
      - LOG_LEVEL=info
      - TZ=UTC
      - CAPTCHA_SOLVER=none
    ports:
      - "8191:8191"
    restart: unless-stopped

First Request

import requests

r = requests.post("http://localhost:8191/v1", json={
    "cmd": "request.get",
    "url": "https://target-with-cloudflare.com",
    "maxTimeout": 60000,
})
data = r.json()
print(data["status"])              # ok | error
print(data["solution"]["status"])  # 200
print(data["solution"]["url"])     # final URL after challenge
print(data["solution"]["response"][:500])  # HTML
print(data["solution"]["cookies"])  # list of {name, value, domain, path}

The full response shape:

{
  "status": "ok",
  "message": "Challenge solved!",
  "solution": {
    "url": "https://target.com",
    "status": 200,
    "headers": {...},
    "response": "...full HTML...",
    "cookies": [{"name": "cf_clearance", "value": "...", "domain": ".target.com", "path": "/", ...}],
    "userAgent": "Mozilla/5.0 ..."
  },
  "startTimestamp": 1715353200000,
  "endTimestamp": 1715353215000,
  "version": "3.x.x"
}

Sessions: Reuse Cleared Cookies

Solving the challenge takes 5-15 seconds. For multiple requests to the same site, reuse the session:

# 1. Create a session
r = requests.post("http://localhost:8191/v1", json={"cmd": "sessions.create"})
session_id = r.json()["session"]

# 2. Use it for multiple requests
for url in urls:
    r = requests.post("http://localhost:8191/v1", json={
        "cmd": "request.get",
        "url": url,
        "session": session_id,
        "maxTimeout": 60000,
    })
    print(r.json()["solution"]["status"])

# 3. Cleanup when done
requests.post("http://localhost:8191/v1", json={
    "cmd": "sessions.destroy", "session": session_id
})

The session keeps the browser open between requests, so subsequent calls skip the challenge solving (cookies remain valid for ~30 minutes typically).

POST Requests + Forms

r = requests.post("http://localhost:8191/v1", json={
    "cmd": "request.post",
    "url": "https://target.com/api/data",
    "postData": "[email protected]",
    "maxTimeout": 60000,
})

JSON body:

r = requests.post("http://localhost:8191/v1", json={
    "cmd": "request.post",
    "url": "https://target.com/api/data",
    "postData": '{"name":"alice"}',
    "headers": [{"name": "Content-Type", "value": "application/json"}],
    "maxTimeout": 60000,
})

Routing FlareSolverr Through a Proxy

To route the headless Chrome through a proxy (e.g., residential IPs for IP rotation):

r = requests.post("http://localhost:8191/v1", json={
    "cmd": "request.get",
    "url": "https://target.com",
    "proxy": {
        "url": "http://gw.spyderproxy.com:8000",
        "username": "USER",
        "password": "PASS"
    },
    "maxTimeout": 60000,
})

For Cloudflare-protected sites, route through Premium Residential ($2.75/GB) for clean IPs. For the toughest targets (PerimeterX + Cloudflare), LTE Mobile ($2/IP) has the lowest detection rate.

Per-session proxy (set once, used for all requests in that session):

r = requests.post("http://localhost:8191/v1", json={
    "cmd": "sessions.create",
    "proxy": {"url": "http://USER:[email protected]:8000"},
})
session_id = r.json()["session"]

Captcha Solver Integration

FlareSolverr can hand off Cloudflare Turnstile to 2Captcha/CapMonster automatically. Set CAPTCHA_SOLVER env var:

docker run -d --name flaresolverr -p 8191:8191   -e LOG_LEVEL=info   -e CAPTCHA_SOLVER=hcaptcha-solver   -e CAPTCHA_SOLVER_API_KEY=your_2captcha_key   ghcr.io/flaresolverr/flaresolverr:latest

Cost: ~$2.99/1,000 Turnstile solves. Required when the challenge is interactive (not just JS).

Common Errors

  • {"status": "error", "message": "Challenge not detected!"} — site is not protected by Cloudflare, or returned a non-challenge response. FlareSolverr returns the raw HTML anyway in solution.response.
  • "message": "Timeout while solving the challenge" — bump maxTimeout (default 60000ms). Some sites take 30+ seconds.
  • "message": "Error: target_closed" — the headless Chrome crashed. Usually fixed by restarting the container.
  • 403 even after FlareSolverr clears — site has application-layer protection beyond Cloudflare. You need login/session cookies that FlareSolverr cannot generate alone.
  • Memory issues — each session holds an open Chrome instance (~200MB). Destroy sessions when done.

FlareSolverr vs Alternatives

ToolMemorySpeedHandles Turnstile
Cloudscraper~20 MBFast (1-2s)No
curl_cffi~30 MBFastest (<1s)No (TLS impersonation only)
FlareSolverr~250 MB / sessionSlow (5-15s)Yes
Playwright direct~300 MB / instanceSlow (5-15s)Yes (with stealth)

Best Practices

  • Reuse sessions aggressively — solving costs 5-15s and CPU; one session for 50+ requests is normal.
  • Route through residential proxies — FlareSolverr solves the challenge, but Cloudflare can still rate-limit by IP.
  • Set maxTimeout generously — 60s default is fine; bump to 120s for stubborn sites.
  • Destroy sessions when done — each holds ~200MB of RAM.
  • Run with --shm-size=2g for the Chrome shared memory if you see crashes.

Related: Cloudscraper tutorial, Bypass DataDome, How to bypass Cloudflare.