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.createandPROXY_*variables, not onrequest.get. solution.statusis always 200 andsolution.headersis 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 endpointThe 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 loopFrom the source (flaresolverr_service.py and utils.py), a request.get call runs like this:
- 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.
- Navigate. The browser opens the URL. For
request.post, FlareSolverr builds a hidden HTML form from yourpostDataand submits it, because Selenium has no direct way to send a POST. - 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.
- 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_TIMEOUTseconds, try the page’s verify control and wait again. The whole call is bounded by yourmaxTimeout. - 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.
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 itThe 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).
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:8191publishes the port on loopback only. Other containers on the same Docker network can reach it ashttp://flaresolverr:8191.- A pinned tag instead of
latest. Behavior changes with each Chromium bump, so upgrade on purpose. --tmpfs /tmpkeeps temporary browser profiles (roughly 10–30 MB per request, per the README) in RAM instead of on disk.
The same setup as Compose:
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.
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 onesConfiguration is entirely through environment variables. These are the ones the README documents, with their defaults:
| Variable | Default | What it does |
|---|---|---|
| LOG_LEVEL | info | debug logs each wait step and selector |
| LOG_FILE | none | Also write logs to a file, e.g. /config/flaresolverr.log |
| LOG_HTML | false | Debug only: log every page’s HTML |
| PROXY_URL / PROXY_USERNAME / PROXY_PASSWORD | none | Default proxy when a command has none |
| CAPTCHA_SOLVER | none | Documented, but the README says no solver works |
| TZ | UTC | Time zone for logs and the browser |
| LANG | none | Browser language, e.g. en_GB |
| HEADLESS | true | Debug only: false shows the window |
| DISABLE_MEDIA | false | Block images, CSS and fonts to save bandwidth |
| BROWSER_WAIT_TIMEOUT | 1 | Seconds per wait attempt; raise on slow hosts |
| TEST_URL | https://www.google.com | URL used for the startup self-test |
| PORT / HOST | 8191 / 0.0.0.0 | Listening port and interface |
| PROMETHEUS_ENABLED / PROMETHEUS_PORT | false / 8192 | Expose 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 endpointEverything goes through POST /v1 with a JSON body whose cmd field picks the operation:
| cmd | What it does | Key parameters |
|---|---|---|
| request.get | Open a URL in the browser and return the result | url (required), session, maxTimeout, proxy, cookies, returnOnlyCookies |
| request.post | Same, submitting a form POST | As above plus postData (URL-encoded string) |
| sessions.create | Start a persistent browser | session (ID, optional), proxy with optional username/password |
| sessions.list | List active session IDs | None |
| sessions.destroy | Close a browser and delete its files | session (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:
{
"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.statusis hard-coded to 200 andsolution.headersis 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.messagetells 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 theexpiresshown 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.postonly acceptsapplication/x-www-form-urlencodeddata such asa=b&c=d, so it can’t send a JSON body.
Using a Proxy with FlareSolverr
Where the proxy goes, and which fields work whereA 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:
proxy.url plus username and password. Authorization is documented as supported. This is the recommended place.proxy.url only; the README says username/password are not supported here. Ignored entirely when the request names a session.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:
# 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 wrongLaunching 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.userAgentexactly. - 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.
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 cleanupA 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.destroyor a restart; usesessions.listto find leaks. - The proxy is fixed at creation. A request’s
proxyis ignored when it names a session, so a new IP means a new session. sessions.createis idempotent. An existing ID returns “Session already exists.” and keeps the old browser and proxy. Use unique IDs per job.session_ttl_minutesrecreates 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.getnaming an old ID starts a new browser under that ID with no session proxy, connecting directly or via thePROXY_*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 cheapMemory 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 itMaintenance 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.mdsays 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 decisionSite 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| Situation | FlareSolverr | Browser framework | Official API |
|---|---|---|---|
| Site offers an API or feed | No | No | Yes, use it |
| Tool only speaks HTTP (indexer, cron job) | Good fit | Overkill | If available |
| Need HTML of a few public pages | Good fit | Works | If available |
| Need clicks, scrolling, forms | Can’t | Yes | If available |
| Need status codes, headers, network data | No | Yes | Yes |
| Thousands of pages per hour | Costly; reuse cookies | Needs a cluster | Best |
| Interactive challenge / CAPTCHA | Stop | Stop | Ask for access |
| Your own site, testing bot rules | Useful probe | Useful | N/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| Symptom | Likely cause | What to do |
|---|---|---|
| “Timeout after N seconds” | Challenge never cleared, or slow proxy/page | Check with returnScreenshot; raise maxTimeout or BROWSER_WAIT_TIMEOUT; don’t loop retries |
| “Cloudflare has blocked this request” | The site denied access, not a challenge | Stop; the site owner has blocked this traffic |
| Challenge returns in your HTTP client | UA, IP or cookies differ | Same UA, same sticky username, full cookie jar |
| Proxy auth errors / 407 | Credentials on request.get, or SOCKS5 with auth | Use sessions.create with an http:// proxy |
| Container exits at start | Browser self-test failed | Check logs, libseccomp2 on Debian, TEST_URL reachability |
| Memory climbs over time | Sessions not destroyed | sessions.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 shortWhat 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.



