Follow-up to the earlier CI fix, after A/B-ing every change against main and
against this branch's original commit.
What measurably changed, and what did not:
- The solver's retry loop was unbounded (max_attempts = sys.maxsize). On a
challenge it cannot clear it retried ~1300 times per request and the caller
waited out the entire max_timeout for a 408 it was always going to get.
_solve_challenge now clicks, waits for the challenge markup to actually
disappear, and gives up when the budget does.
- That wait exists because the solver's own verdict is worthless here: it
judges its click with wait_for_load_state("networkidle"), which returned 9ms
after the click while Cloudflare was still showing "verifying you are
human", and then reported failure.
- The "is it still up?" check cannot use detect_cloudflare_challenge alone.
That matches any script under /cdn-cgi/challenge-platform/, and Cloudflare
serves its jsd bot-scoring beacon from the same path on cleared pages. Nor
can it use the widget iframe: a cleared nowsecure.nl carries two of those
with no challenge present. CHALLENGE_MARKERS matches the challenge
orchestrator script and the interstitial's own markup.
- test_tls_handshake_looks_like_firefox pins what this branch is actually for.
Measured through /v1 on the same host: main offers 52 cipher suites, this
branch 16, and real Firefox offers 16. route.fetch() was re-issuing
navigations through Playwright's HTTP client, and that is a fingerprint no
header spoofing hides. Unlike a Cloudflare verdict the count is
deterministic, so it is the one assertion here that cannot flake.
- Disabling COOP/COEP does let the solver reach and click the checkbox for the
first time (Cloudflare advances to "verifying you are human"), but it changed
no outcome across eight sites, and real Firefox ships those policies on.
Recorded in a comment rather than shipped.
test_bypass keeps a hard assertion against targets that clear from any network.
The four Cloudflare guards hardest move to xfail rather than skip: they still
run and still report, but Cloudflare's opinion of the runner's IP cannot turn
the build red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Byparr
Important
This software does not guarantee (only greatly increases the chance) that any challenge will be bypassed. While this tool passes the initial browser check, Cloudflare and other captcha providers likely require valid network traffic originating from the user’s public IP address to mark a connection as legitimate. If any website does not pass the challenge, please run troubleshooting steps and check if other websites work before you create an GitHub issue.
Options
| Environment Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Host address to bind the server to. Use 0.0.0.0 to bind to all IPv4 interfaces, :: for all IPv6 interfaces, or 127.0.0.1/localhost for local access only. |
PORT |
8191 |
Port to bind the server to. |
PROXY_SERVER |
None | Proxy to use in format: protocol://host:port. |
PROXY_USERNAME |
None | Username for proxy authentication. |
PROXY_PASSWORD |
None | Password for proxy authentication. |
OWUI_API_KEY |
None | Bearer token for /load endpoint authentication. Must match EXTERNAL_WEB_LOADER_API_KEY in Open WebUI. |
BROWSER_LOCALE |
None | Override the browser's language with a BCP-47 tag, e.g. en-US, de-DE, fr-FR. When unset, the locale is derived from the egress country. |
Browser language
Set BROWSER_LOCALE to a BCP-47 language tag like en-US, de-DE, fr-FR, pl-PL, or zh-CN to fix the browser's language and Accept-Language header. When unset, Byparr derives the locale from the egress country (e.g. a French proxy → fr-FR), keeping the browser language consistent with the exit IP.
Valid tags are maintained in the IANA Language Subtag Registry. For a friendlier list, see List of ISO 639-1 codes (language) combined with an ISO 3166-1 alpha-2 region code for the full tag, e.g. pt-BR.
Proxy Recommendation
Recently I've partnered with a new in town proxy service - ProxyBase - to offer affordable proxy services that seems to work seamlessly with Byparr! Using my affiliate code byparr (case sensitive!) when signing up will not only get you access to their cost-effective ($0.69/GB with occasional promotions at the time of writing) proxy network but will also help support the continued development of this project. ProxyBase's proxies can significantly improve your success rate when bypassing anti-bot challenges. Check out ProxyBase and enhance your Byparr experience!
Tags
v*.*.*/latest- Releases considered stablemain- Latest release from main branch (untested)pr-{number}- Pull request images for testing (automatically cleaned up when PR closes)
Usage
Important
Support for NAS devices (like Synology) is minimal. Please report issues, but do not expect it to be fixed quickly. The only ARM device I have is a free Ampere Oracle VM, so I can only test ARM support on that. See #22 and #3
Docker Compose setup
- Review settings in
compose.yaml. - Start the service:
docker compose up -d
Docker install
-
Pull and run the image:
docker run -p 8191:8191 ghcr.io/thephaseless/byparr:latest -
Optional: set env vars using
-eor--env-file.
Local install
- Install (or update when Python version changes) uv.
- Clone this repo -
git clone https://github.com/ThePhaseless/Byparr - Run
uv run main.py - Enjoy!
API Docs
Once running, open:
http://localhost:8191/docshttp://localhost:8191/(redirects to/docs)
Open WebUI Integration
Byparr can serve as an external web loader for Open WebUI, allowing it to fetch web content through Byparr's anti-bot bypassing capabilities.
Configure Open WebUI with these environment variables:
WEB_LOADER_ENGINE=external
EXTERNAL_WEB_LOADER_URL=http://byparr:8191/load
EXTERNAL_WEB_LOADER_API_KEY=your-secret-key # Optional, must match OWUI_API_KEY
The /load endpoint accepts POST requests with {"urls": ["https://..."]} and returns extracted text content for RAG pipelines.
Troubleshooting
Docker troubleshooting
- Clone repo to the host that has issues with Byparr.
- Run
docker build --target test . - Depending of the build success:
- If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies
- If build fails, try troubleshooting on another host/using other method
Proxmox OCI / LXC browser launch errors
If you are running Byparr as an OCI container in Proxmox (or another LXC-based setup) and see a FileNotFoundError from multiprocessing.synchronize/camoufox when processing requests, increase the service's shared memory in compose.yaml:
services:
byparr:
shm_size: 512mb
stdin_open: true
tty: true
shm_size: 512mb is usually enough; stdin_open and tty are only needed if your orchestrator runs the container without a TTY.
Local troubleshooting
- Download uv
- Download dependencies using
uv sync --group test - Run tests with
uv run pytest --retries 3(You can add-n autofor parallelization) - If you see any
Fcharacter in terminal, that means test failed even after retries. - Depending of the test success:
- If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies
- If test fails, try troubleshooting on another host/using other method