FlareSolverr Explained: How It Works, Docker Setup, Proxies and Its Limits (2026)

Developer guide · Last reviewed 20 October 2026 · 15 min read

FlareSolverr is an open-source proxy server that loads a URL in a real Chrome browser, waits for Cloudflare’s (or DDoS-GUARD’s) browser check to finish, and hands back the page HTML, the cookies and the browser’s User-Agent over a small JSON API. This guide covers how it works, Docker setup, every /v1 command, authenticated proxies, why reused cookies need the same IP and User-Agent, and its limits, all checked against the v3.5.2 README and source.

The short version

Run ghcr.io/flaresolverr/flaresolverr on port 8191, bound to localhost, and POST JSON commands to /v1. Each request.get opens the page in Chrome, waits for the challenge page to clear and returns solution.response, solution.cookies and solution.userAgent. Put authenticated proxies in sessions.create. To reuse the cookies in another HTTP client, send the same User-Agent through the same exit IP (with ProxyEmpire, the same sticky-session username). Use it only where you are authorized, and prefer an official API.

Scope. This is an engineering explainer for teams collecting public data or testing sites they own or are authorized to access. It is not a guide to getting past security controls on systems you have no permission to use. Read Responsible use first.

Key takeaways

  • FlareSolverr is a thin HTTP API around Selenium and undetected-chromedriver. A real browser runs the page’s JavaScript; nothing is “solved” at the network layer.
  • Without a session, every request starts and stops a full Chrome. Sessions are faster but hold memory until destroyed.
  • Per the README, proxy credentials work in sessions.create and PROXY_* variables, not on request.get.
  • solution.status is always 200 and solution.headers is empty. Don’t build logic on them.
  • Reuse cookies only with the same User-Agent and exit IP, and expect occasional re-challenges anyway.
  • None of the CAPTCHA solvers currently work. Treat an interactive challenge as a stop signal.
  • v3.5.2 shipped on 12 September 2026, after a year-long release gap in 2024–2025.

What FlareSolverr Is (and Isn’t)

A browser behind an HTTP endpoint

The project describes itself as “a proxy server to bypass Cloudflare and DDoS-GUARD protection.” The word “proxy” is a little misleading. FlareSolverr is not a forward proxy you configure in HTTP_PROXY. It is a small web service (Bottle on the Waitress WSGI server) that listens on port 8191 and accepts JSON commands. Each command tells it to open a URL in Chrome and report back what the browser ended up with.

Some sites behind Cloudflare answer a first visit with an interstitial page that runs JavaScript checks. A plain HTTP client such as requests can’t run that JavaScript; a real browser can. FlareSolverr lets software that only speaks HTTP borrow a browser for that step, then continue with the cookies it received.

It is best known as a companion to media-indexer apps such as Prowlarr and Jackett, which support it as an indexer proxy, and it is also used in small data-collection jobs. It is MIT-licensed and maintained on GitHub.

What it isn’t: a browser automation framework (no clicking or scripting API), a parser (it returns HTML), or a guarantee. Whether a check passes depends on Cloudflare’s current detection, the site’s settings and your IP. For background, see our primer on headless browsers and how they work.

How FlareSolverr Works Under the Hood

Selenium, a patched ChromeDriver and a wait loop

From the source (flaresolverr_service.py and utils.py), a request.get call runs like this:

  1. Get a browser. Reuse the session’s Chrome, or launch a new one through Selenium and the bundled undetected-chromedriver. In Docker this is Debian’s Chromium running headful inside an Xvfb virtual display.
  2. Navigate. The browser opens the URL. For request.post, FlareSolverr builds a hidden HTML form from your postData and submits it, because Selenium has no direct way to send a POST.
  3. Classify the page. It checks the title and known selectors. “Access denied” raises a “Cloudflare has blocked this request” error; “Just a moment…” or a challenge selector means a challenge is running.
  4. Wait. If a challenge was detected, it loops: wait for the challenge title and selectors to disappear, and if they don’t within BROWSER_WAIT_TIMEOUT seconds, try the page’s verify control and wait again. The whole call is bounded by your maxTimeout.
  5. Collect and return. It optionally sleeps for waitInSeconds, then reads the final URL, the page source, the cookies and the browser’s User-Agent, and returns them as JSON. A temporary browser is then shut down.
Figure 1 — where FlareSolverr sits in a pipeline
your code
   |  POST /v1 {"cmd": "request.get", "url": ...}
   v
FlareSolverr :8191
   |  Chrome (Selenium + undetected-chromedriver)
   |  loads page, runs JS, waits for challenge to clear
   v
proxy exit IP (sticky)  --->  site
   |
   |  JSON: response HTML, cookies, userAgent
   v
your code
   |  optional: requests.Session with same UA + cookies
   v
same proxy exit IP  --->  site (next pages)

Two operational details: the browser runs with --ignore-certificate-errors, so invalid TLS certificates go unreported; and the API has no authentication, so anyone who can reach port 8191 can drive your browser and proxy. The README says plainly not to expose it to the internet.

FlareSolverr Docker Setup

The recommended way to run it

The README recommends Docker because the image already contains a matching Chromium and ChromeDriver. Images are published to the GitHub Container Registry as ghcr.io/flaresolverr/flaresolverr and mirrored on Docker Hub as flaresolverr/flaresolverr, for linux/386, linux/amd64, linux/arm/v7 and linux/arm64. The container listens on port 8191 (and 8192 for the optional Prometheus exporter).

Example 1 — docker run, bound to localhost and pinned to a release (Bash)
docker run -d \
  --name=flaresolverr \
  -p 127.0.0.1:8191:8191 \
  -e LOG_LEVEL=info \
  -e TZ=Europe/London \
  --tmpfs /tmp:size=256M,mode=1777 \
  --restart unless-stopped \
  ghcr.io/flaresolverr/flaresolverr:v3.5.2

Three choices in that command are deliberate:

  • 127.0.0.1:8191:8191 publishes the port on loopback only. Other containers on the same Docker network can reach it as http://flaresolverr:8191.
  • A pinned tag instead of latest. Behavior changes with each Chromium bump, so upgrade on purpose.
  • --tmpfs /tmp keeps temporary browser profiles (roughly 10–30 MB per request, per the README) in RAM instead of on disk.

The same setup as Compose:

Example 2 — docker-compose.yml (YAML)
services:
  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:v3.5.2
    container_name: flaresolverr
    environment:
      - LOG_LEVEL=info
      - LOG_FILE=/config/flaresolverr.log
      - TZ=Europe/London
      - LANG=en_GB
    ports:
      - "127.0.0.1:8191:8191"
    volumes:
      - ./flaresolverr-config:/config
    tmpfs:
      - /tmp:size=256M,mode=1777
    restart: unless-stopped

Start it with docker compose up -d and check it before sending real work. GET /health returns {"status": "ok"}; GET / returns the version and the User-Agent the bundled browser will present.

Example 3 — health check and a first request (Bash)
curl -s http://127.0.0.1:8191/health
curl -s http://127.0.0.1:8191/

curl -s -X POST http://127.0.0.1:8191/v1 \
  -H 'Content-Type: application/json' \
  -d '{"cmd": "request.get", "url": "https://www.example.com/", "maxTimeout": 60000}'

Platform notes from the README: on Debian hosts, libseccomp2 should be 2.5.x; precompiled binaries and source installs are x64 only, so ARM boards should use the Docker image.

FlareSolverr Environment Variables

Only the documented ones

Configuration is entirely through environment variables. These are the ones the README documents, with their defaults:

VariableDefaultWhat it does
LOG_LEVELinfodebug logs each wait step and selector
LOG_FILEnoneAlso write logs to a file, e.g. /config/flaresolverr.log
LOG_HTMLfalseDebug only: log every page’s HTML
PROXY_URL / PROXY_USERNAME / PROXY_PASSWORDnoneDefault proxy when a command has none
CAPTCHA_SOLVERnoneDocumented, but the README says no solver works
TZUTCTime zone for logs and the browser
LANGnoneBrowser language, e.g. en_GB
HEADLESStrueDebug only: false shows the window
DISABLE_MEDIAfalseBlock images, CSS and fonts to save bandwidth
BROWSER_WAIT_TIMEOUT1Seconds per wait attempt; raise on slow hosts
TEST_URLhttps://www.google.comURL used for the startup self-test
PORT / HOST8191 / 0.0.0.0Listening port and interface
PROMETHEUS_ENABLED / PROMETHEUS_PORTfalse / 8192Expose request counters and durations

Two practical points. If you collect localized pages, set TZ and LANG consistently with the country of your exit IP, so the site serves the locale you expect. And if you enable Prometheus, the flaresolverr_request_total counter (labelled by domain and result) and the flaresolverr_request_duration histogram are the two numbers worth alerting on.

The FlareSolverr /v1 API

Five commands, one endpoint

Everything goes through POST /v1 with a JSON body whose cmd field picks the operation:

cmdWhat it doesKey parameters
request.getOpen a URL in the browser and return the resulturl (required), session, maxTimeout, proxy, cookies, returnOnlyCookies
request.postSame, submitting a form POSTAs above plus postData (URL-encoded string)
sessions.createStart a persistent browsersession (ID, optional), proxy with optional username/password
sessions.listList active session IDsNone
sessions.destroyClose a browser and delete its filessession (required)

Other documented options on request.get: session_ttl_minutes (recreate a session’s browser once it is older than this), waitInSeconds (pause after the challenge before reading the page, for content that loads late), disableMedia (per-request version of DISABLE_MEDIA) and returnScreenshot (a Base64 PNG of the final page, handy for debugging). maxTimeout is in milliseconds and defaults to 60000.

A trimmed successful response looks like this. The values are placeholders:

Example 4 — shape of a request.get response (JSON)
{
  "status": "ok",
  "message": "Challenge not detected!",
  "solution": {
    "url": "https://www.example.com/",
    "status": 200,
    "headers": {},
    "response": "<html>...</html>",
    "cookies": [
      {"name": "...", "value": "...", "domain": ".example.com",
       "path": "/", "secure": true, "httpOnly": true, "sameSite": "None"}
    ],
    "userAgent": "Mozilla/5.0 (X11; Linux x86_64) ..."
  },
  "startTimestamp": 1760954400000,
  "endTimestamp": 1760954406100,
  "version": "3.5.2"
}

Read it with these quirks in mind, all visible in the v3.5.2 source:

  • solution.status is hard-coded to 200 and solution.headers is an empty object, because Selenium doesn’t expose the HTTP status or headers. The source marks both as to-dos. A 404 or a 503 page comes back as “200”; check the HTML instead.
  • message tells you what happened: “Challenge solved!” or “Challenge not detected!”. The second is normal for pages that serve no interstitial at all.
  • Errors return HTTP 500 with "status": "error" and a message such as “Error solving the challenge. Timeout after 60.0 seconds.” Parse the JSON before you raise on the HTTP status, or you lose the reason.
  • Cookie objects use Selenium’s keys (expiry, not the expires shown in older README examples). Don’t assume every field is present.
  • There is no way to send custom headers or a custom User-Agent. Both parameters were removed in v2 and are ignored with a warning. request.post only accepts application/x-www-form-urlencoded data such as a=b&c=d, so it can’t send a JSON body.

Using a Proxy with FlareSolverr

Where the proxy goes, and which fields work where

A proxy gives the browser a different exit IP, typically to see pages as served in a specific country. FlareSolverr accepts one in three places, and the README is specific about each:

sessions.createproxy.url plus username and password. Authorization is documented as supported. This is the recommended place.
request.get / request.postproxy.url only; the README says username/password are not supported here. Ignored entirely when the request names a session.
PROXY_* env varsDefault for any command that has no proxy, with optional username and password. One proxy for the whole instance.

The URL needs a scheme: http://, socks4:// or socks5://. Without credentials it becomes Chrome’s --proxy-server flag; with credentials FlareSolverr generates a small Chrome extension that answers the auth prompt. Chromium doesn’t support SOCKS5 username/password auth, so use the http:// URL (HTTPS sites still work via CONNECT; see our SOCKS vs HTTP comparison).

ProxyEmpire with FlareSolverr

ProxyEmpire’s gateway is v2.proxyempire.io:5000 with username/password auth. Targeting and session settings live in the username, generated under Proxy Manager → Connection Builder. Choose the “Same IP” (sticky) mode: the username then carries a session ID (sid, and you can set your own 8-digit IDs), and every connection with that username uses the same exit IP. Test it first:

Example 5 — test the proxy, then create a FlareSolverr session that uses it (Bash)
# 1. The proxy works and returns an exit IP
curl -x http://USERNAME:[email protected]:5000 https://api.ipify.org

# 2. A FlareSolverr session bound to that sticky proxy
curl -s -X POST http://127.0.0.1:8191/v1 \
  -H 'Content-Type: application/json' \
  -d '{
    "cmd": "sessions.create",
    "session": "job-0001",
    "proxy": {
      "url": "http://v2.proxyempire.io:5000",
      "username": "USERNAME",
      "password": "PASSWORD"
    }
  }'

# 3. Requests in that session go through that proxy
curl -s -X POST http://127.0.0.1:8191/v1 \
  -H 'Content-Type: application/json' \
  -d '{"cmd": "request.get", "session": "job-0001", "url": "https://api.ipify.org/"}'

# 4. Clean up
curl -s -X POST http://127.0.0.1:8191/v1 \
  -H 'Content-Type: application/json' \
  -d '{"cmd": "sessions.destroy", "session": "job-0001"}'

Use the values copied from the Connection Builder; our curl proxy guide covers quoting special characters. For public pages, residential proxies in sticky mode are the usual choice for their country, city and ISP targeting.

Reusing FlareSolverr Cookies: Why the IP and User-Agent Must Match

The pattern most people get wrong

Launching Chrome for every page is slow, so the common pattern is to use FlareSolverr once, then switch to a lightweight HTTP client with the same cookies. The README warns that you must also send FlareSolverr’s User-Agent, or the challenge reappears.

The reason is in how Cloudflare describes its clearance cookie. Its clearance documentation says the cf_clearance cookie is “securely tied to the specific visitor and device it was issued to.” A request with that cookie but a different User-Agent or IP isn’t the visitor that passed the check. Keep three things constant:

  • The User-Agent: copy solution.userAgent exactly.
  • The exit IP: a rotating proxy would give the browser and your client different IPs; the same ProxyEmpire sticky username (same sid) gives both the same IP. See sticky vs rotating proxies.
  • The cookie jar: every cookie with its domain and path, not only cf_clearance.

The example creates a session on a sticky ProxyEmpire username, records the browser’s exit IP, loads the first page, then builds a requests.Session with the same User-Agent, cookies and proxy and confirms the IP matches before continuing.

Example 6 — FlareSolverr session, then requests on the same sticky IP (Python)
import os
import re
import uuid
from urllib.parse import quote

import requests

FLARESOLVERR = "http://127.0.0.1:8191/v1"
GATEWAY = "v2.proxyempire.io:5000"

# A sticky-session username copied from Proxy Manager -> Connection Builder.
# Same username (same sid) = same exit IP for the life of the session.
PROXY_USER = os.environ["PROXYEMPIRE_USER"]
PROXY_PASS = os.environ["PROXYEMPIRE_PASS"]

# Only use pages you are authorized to access.
START_URL = "https://www.example.com/"
NEXT_URL = "https://www.example.com/page/2"

IPV4 = re.compile(r"\b\d{1,3}(?:\.\d{1,3}){3}\b")


def fs(payload, timeout=90):
    """Call FlareSolverr. Errors come back as HTTP 500 with a JSON body."""
    r = requests.post(FLARESOLVERR, json=payload, timeout=timeout)
    data = r.json()
    if data.get("status") != "ok":
        raise RuntimeError(f"FlareSolverr: {data.get('message')}")
    return data


def http_client(solution):
    """A plain requests.Session that looks like the same visitor."""
    proxy_url = (
        f"http://{quote(PROXY_USER, safe='')}:{quote(PROXY_PASS, safe='')}"
        f"@{GATEWAY}"
    )
    s = requests.Session()
    s.proxies = {"http": proxy_url, "https": proxy_url}
    s.headers["User-Agent"] = solution["userAgent"]
    for c in solution["cookies"]:
        s.cookies.set(
            c["name"],
            c["value"],
            domain=c.get("domain", ""),
            path=c.get("path", "/"),
            secure=c.get("secure", False),
        )
    return s


def main():
    session_id = f"job-{uuid.uuid4().hex[:8]}"
    fs({
        "cmd": "sessions.create",
        "session": session_id,
        "proxy": {
            "url": f"http://{GATEWAY}",
            "username": PROXY_USER,
            "password": PROXY_PASS,
        },
    })
    try:
        # 1. Which exit IP does the browser use?
        ip_check = fs({
            "cmd": "request.get",
            "session": session_id,
            "url": "https://api.ipify.org/",
            "maxTimeout": 60000,
        })
        match = IPV4.search(ip_check["solution"]["response"])
        browser_ip = match.group(0) if match else None

        # 2. Load the first page in the browser.
        page = fs({
            "cmd": "request.get",
            "session": session_id,
            "url": START_URL,
            "maxTimeout": 60000,
        })
        solution = page["solution"]
        print(page["message"], solution["url"])

        # 3. Continue with a lightweight client on the same IP and UA.
        http = http_client(solution)
        client_ip = http.get("https://api.ipify.org/", timeout=30).text.strip()
        if client_ip != browser_ip:
            raise RuntimeError(f"exit IP changed: {browser_ip} -> {client_ip}")

        resp = http.get(NEXT_URL, timeout=30)
        print(resp.status_code, len(resp.text))
    finally:
        fs({"cmd": "sessions.destroy", "session": session_id})


if __name__ == "__main__":
    main()

Notes: the 90-second client timeout exceeds maxTimeout, so FlareSolverr’s own error arrives first; credentials are percent-encoded only for the requests proxy URL; and finally always destroys the session, because a leaked session is a leaked Chrome.

Matching IP and User-Agent is necessary, not sufficient. A Python client still differs from Chrome in observable ways such as its TLS handshake, and Cloudflare’s docs describe clearance that can be re-evaluated during a session. If a site re-challenges your client, keep those requests in the FlareSolverr session, slow down, or ask the owner for API access. Our article on how bot detection evaluates traffic explains these signals.

FlareSolverr Sessions and Lifecycle

Faster, but you own the cleanup

A session is a long-lived Chrome kept in memory under an ID you choose (or a UUID). It keeps cookies between requests and skips browser start-up. In exchange:

  • No automatic cleanup. A session lives until sessions.destroy or a restart; use sessions.list to find leaks.
  • The proxy is fixed at creation. A request’s proxy is ignored when it names a session, so a new IP means a new session.
  • sessions.create is idempotent. An existing ID returns “Session already exists.” and keeps the old browser and proxy. Use unique IDs per job.
  • session_ttl_minutes recreates the browser when a session is older than the TTL, but in the v3.5.2 code the recreated browser is started without the session’s original proxy. If you depend on a proxy, rotate sessions yourself instead of relying on the TTL.
  • Unknown session IDs are created silently, without your proxy. Sessions live only in memory. After a restart, a request.get naming an old ID starts a new browser under that ID with no session proxy, connecting directly or via the PROXY_* default. Check the exit IP, as Example 6 does, or recreate sessions at the start of every job.
  • One request at a time per session. A session is one browser driven by one Selenium connection, and FlareSolverr doesn’t serialize calls into it. Send requests for a session sequentially and scale out with more sessions, not parallel calls into one.

Align the proxy session’s lifetime with the FlareSolverr session (ProxyEmpire’s custom rotation time goes up to 2 hours). If the IP changes under a live session, the next request will likely be challenged again.

FlareSolverr Performance and Limits

A browser per request is not cheap

Memory and concurrency

The README warns that browsers “consume a lot of memory”, and every sessionless request launches one. There is also a server ceiling: FlareSolverr doesn’t override Waitress’s default of four worker threads, so one instance processes at most four /v1 calls at once and queues the rest. Scale with several containers behind your own job queue; the design questions mirror those of large Chromium clusters.

Latency

Each call includes browser start-up (without a session), page load and any challenge wait. Expect seconds per call, not milliseconds. disableMedia skips images, CSS and fonts when you only need HTML.

Fidelity and control

  • No HTTP status or headers in the response (see the API section).
  • No custom headers, no custom User-Agent, no JSON POST bodies.
  • No interaction beyond loading the URL. For clicks or forms on sites you may automate, use a framework; see our Selenium proxy guide or Puppeteer proxy guide.
  • Certificate errors are ignored by the browser, so don’t send anything sensitive through it.

CAPTCHAs

The README is direct: none of the CAPTCHA solvers currently work. CAPTCHA_SOLVER is still documented and in the sample Compose file, but no v3.5.2 code reads it. Recent releases added an experimental Turnstile-related option, which this guide doesn’t cover. An interactive challenge means the site owner wants a human there; stop, slow down, or ask for access.

Effectiveness changes

Cloudflare’s detection and each site’s configuration change without notice. Measure success rate continuously (the Prometheus counter helps) rather than treating it as a property of the tool.

FlareSolverr Maintenance Status in 2026

Active again, but check before you depend on it

Maintenance has been uneven, and that matters if you build on it:

  • Release v3.3.21 shipped in June 2024, and the next one, v3.3.22, not until June 2025: a year with no releases, during which many users reported breakage.
  • Since mid-2025 releases have been regular: the v3.4 series through autumn 2025 (adding proxy environment variables, waitInSeconds, screenshots, log files and media blocking), v3.5.0 in May 2026 and v3.5.2 on 12 September 2026, with commits to the main branch as recently as mid-October 2026.
  • The repository’s SECURITY.md says only the latest release is supported.

For production use, pin a version, watch the releases page and the open issues, and keep a fallback path (a browser framework, or a pause in collection) for the periods when it doesn’t work.

Responsible Use

A browser check is a site owner’s decision

Site owners turn on browser checks deliberately, usually to protect capacity or keep automated traffic out of parts of a site. FlareSolverr doesn’t change who is allowed in. Before you use it:

  • Have the right to access the data. Your own sites (for example, testing your Cloudflare rules), sites whose owners authorized you, or public data where the terms allow automated collection. Respect robots.txt, rate limits and personal-data rules.
  • Prefer an official API or ask. Use an API, feed or partner program if one exists. Otherwise, asking the owner for an allowlist or export is often faster than maintaining a browser pipeline.
  • If you run a legitimate crawler, identify it. Cloudflare’s Verified bots program covers bots that identify themselves honestly and behave well, such as search crawlers and monitors. As of October 2026 you apply through the BotBase submission form in the dashboard, with Web Bot Auth signatures or IP validation. IP validation requires IPs used only by your service, so shared proxy IPs don’t qualify.
  • Don’t use it to get into what you aren’t allowed to see. Logged-in areas, paywalled content and anything behind access controls you haven’t been granted are out of bounds, whatever tool you use.

A proxy changes where a request comes from. FlareSolverr changes what runs the request. Neither changes whether you are allowed to make it.

FlareSolverr vs a Browser Framework vs an Official API

Pick the lightest tool that fits
SituationFlareSolverrBrowser frameworkOfficial API
Site offers an API or feedNoNoYes, use it
Tool only speaks HTTP (indexer, cron job)Good fitOverkillIf available
Need HTML of a few public pagesGood fitWorksIf available
Need clicks, scrolling, formsCan’tYesIf available
Need status codes, headers, network dataNoYesYes
Thousands of pages per hourCostly; reuse cookiesNeeds a clusterBest
Interactive challenge / CAPTCHAStopStopAsk for access
Your own site, testing bot rulesUseful probeUsefulN/A

If you are writing the collection code yourself in Python, our guide to Python web scraping with residential proxies covers requests, httpx, Scrapy and Playwright, which together handle most cases without a separate service. For HTML of JavaScript-heavy public pages without running browsers yourself, a managed scraping API is another option.

Troubleshooting FlareSolverr

The messages you will actually see
SymptomLikely causeWhat to do
“Timeout after N seconds”Challenge never cleared, or slow proxy/pageCheck with returnScreenshot; raise maxTimeout or BROWSER_WAIT_TIMEOUT; don’t loop retries
“Cloudflare has blocked this request”The site denied access, not a challengeStop; the site owner has blocked this traffic
Challenge returns in your HTTP clientUA, IP or cookies differSame UA, same sticky username, full cookie jar
Proxy auth errors / 407Credentials on request.get, or SOCKS5 with authUse sessions.create with an http:// proxy
Container exits at startBrowser self-test failedCheck logs, libseccomp2 on Debian, TEST_URL reachability
Memory climbs over timeSessions not destroyedsessions.list, destroy in finally

For proxy-side errors in your own HTTP client (407, 502, tunnel failures), see our reference on proxy error codes.

Frequently Asked Questions

FlareSolverr in short
What is FlareSolverr?

An open-source, MIT-licensed service that opens URLs in real Chrome, waits for Cloudflare or DDoS-GUARD browser checks to finish, and returns HTML, cookies and User-Agent through a JSON API on port 8191.

What is the FlareSolverr Docker image and port?

ghcr.io/flaresolverr/flaresolverr (mirrored as flaresolverr/flaresolverr on Docker Hub), port 8191. Publish it on 127.0.0.1 only, since the API has no authentication, and pin a tag such as v3.5.2.

How do I use a proxy with username and password in FlareSolverr?

Pass "proxy": {"url": "http://host:port", "username": "...", "password": "..."} to sessions.create, or set the PROXY_URL, PROXY_USERNAME and PROXY_PASSWORD defaults. Use http://, because Chromium doesn’t support SOCKS5 authentication.

Why does the challenge come back when I reuse FlareSolverr cookies?

Cloudflare ties its clearance cookie to the visitor it was issued to. Send the exact userAgent, all cookies, and the same exit IP (the same sticky-session username). Other client differences can still trigger a new check.

Does FlareSolverr solve CAPTCHAs?

No. The README says none of the solvers currently work, and v3.5.2 doesn’t read CAPTCHA_SOLVER. Treat an interactive challenge as a signal to stop or ask for access.

Is FlareSolverr still maintained?

Yes, as of October 2026. After no releases from June 2024 to June 2025, it has shipped regularly; v3.5.2 came out on 12 September 2026. Only the latest release is supported.

How many requests can one FlareSolverr instance handle?

Memory is the first limit, since each request or session runs a browser. Waitress’s default of four threads also caps one instance at four concurrent calls. Scale with more containers and a bounded queue.

Give FlareSolverr a stable, targeted exit IP

ProxyEmpire sticky sessions keep the browser and your HTTP client on the same residential or mobile IP through one authenticated gateway, with country, city and ISP targeting on residential and carrier targeting on mobile.

ProxyEmpire proxy types and prices

ProxyEmpire

Proxies for data collection at scale.

Residential, mobile, ISP and datacenter proxies for scraping, ad verification, SEO monitoring and multi-account work. Choose from 30M+ ethically sourced residential IPs and 4M+ 4G/5G mobile IPs in 170+ countries, target by country, city, ZIP, ISP or carrier, and connect over HTTP(S) or SOCKS5 with 99.9% uptime. Try residential and mobile proxies for $1.97.

🏘️ Rotating Residential Proxies
  • 30M+ Premium Residential IPs
  •  170+ Countries
    Every residential IP in our network corresponds to an actual desktop device with a precise geographical location. Our residential proxies are fast and reliable, with 99.9% uptime, and work for a wide range of use cases. You can use country, region, city, ZIP, ISP, ASN and OS fingerprint targeting for our rotating residential proxies, at no extra charge.

See our Rotating Residential Proxies

📍 Static Residential Proxies
  • 24 Countries
    Buy a dedicated static residential IP from one of the 24 countries that we offer proxies in. Keep the same IP for a month or longer, while benefiting from their fast speed and stability.

See our Static Residential Proxies

📳 Rotating Mobile Proxies
  • 4M+ Premium Mobile IPs
  •  170+ Countries
    Access millions of clean mobile IPs with precise targeting by country, region, city, ZIP, mobile carrier, ASN and OS fingerprint, at no extra charge. Get far fewer IP blocks and CAPTCHAs with our 4G and 5G proxies.

See our Mobile Proxies

📱 Dedicated Mobile Proxies
  • 4 Countries
  • 50+ Locations
    Get your own dedicated mobile proxy in one of our supported locations, with unlimited bandwidth and unlimited IP changes on demand. A great choice when you need a small number of mobile IPs and a lot of proxy bandwidth.

See our 4G & 5G Proxies

🌐 Rotating Datacenter Proxies
  • 197,000+ IPs Premium IPs
  •  62 Countries
    On a budget and need to do some simple scraping tasks? Our datacenter proxies are the perfect fit! Get started with as little as $2

See our Datacenter Proxies

♾️ Unlimited Residential Proxies
  • 1M+ Daily Residential IPs
  • 85+ Countries
    Our unlimited residential proxies bill by connection speed, not gigabytes: 100 to 1000 Mbit with unlimited bandwidth, on daily, weekly or monthly plans. Ask us for a 1-hour trial at 50 Mbit before you pick a plan.

See our Unlimited Residential Proxies

proxy locations

30M+ rotating IPs

99.9% uptime - high speed

99.9% uptime.

dedicated support team

24/7 Dedicated Support.

fair price

Fair Pricing.

🏠 Residential Proxies Rotating / Static / Unlimited
📱 Mobile Proxies Rotating and Dedicated
🖥️ Datacenter Proxies Rotating
🌍 IP Pool 30M+ residential + 4M+ mobile IPs
📶 Uptime 99.9% · Live status
💳 Payment Card · PayPal · Crypto · Bank transfer
💬 Support 24/7 live chat · [email protected]