# Byparr [![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?logo=github-sponsors)](https://github.com/sponsors/ThePhaseless)

Byparr logo

> [!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](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) tag, e.g. `en-US`, `de-DE`, `fr-FR`. When unset, the locale is derived from the egress country. | | `BROWSER_TIMEZONE` | None | Override the browser's timezone with an [IANA](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) name, e.g. `Europe/Berlin`, `Asia/Shanghai`. When unset, the timezone is derived from the egress IP. | #### Browser language Set `BROWSER_LOCALE` to a [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) 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](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). For a friendlier list, see [List of ISO 639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (language) combined with an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) region code for the full tag, e.g. `pt-BR`. #### Browser timezone Set `BROWSER_TIMEZONE` to an [IANA timezone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) like `Europe/Berlin` or `Asia/Shanghai` to fix the browser's timezone. An explicit value is used as is, also behind a proxy. When Byparr starts, it downloads the GeoIP database from GitHub before it accepts requests. The image does not include the database, so every new container downloads it once. Without `PROXY_SERVER`, Byparr also looks up its public IP through `api.ipify.org`, `icanhazip.com` or `checkip.amazonaws.com` at the same time. When `BROWSER_TIMEZONE` or `BROWSER_LOCALE` is unset, the database maps that IP to a timezone and language. Byparr keeps both results until it restarts, so restart it if its public IP moves to another country or to get a newer database. This usually adds a few seconds to start-up, and the port stays closed until it is done. If GitHub is unreachable it can take about a minute, and a stalled download a few minutes. A download that keeps going but crawls is capped by `INVISIBLE_DOWNLOAD_DEADLINE`, in seconds per attempt (default 1800, up to 3 attempts). Because an open port means Byparr is ready, a TCP readiness probe on `PORT` (or an HTTP probe on `/docs`) keeps traffic away from a container that is still starting. If the lookup or the download fails, Byparr starts anyway and logs a warning. Browsers then get the host timezone (`TZ`, otherwise the system's, otherwise UTC) and `en-US`. Byparr tries the public IP again on the first request at least 10 minutes after the failure. The database is retried sooner, on the first request at least 30 seconds after; each failure in a row doubles that wait, up to 10 minutes. With a proxy (`PROXY_SERVER` or the `X-Proxy-Server` header), Byparr looks up the public IP through the proxy for every request, and all requests share the one database. If the database download failed, proxied requests fail until a retry succeeds, unless `BROWSER_TIMEZONE` is set. If those hosts are slow or blocked on your network, set both `BROWSER_TIMEZONE` and `BROWSER_LOCALE`. Byparr still looks up the public IP once at start, because the browser uses it for WebRTC and geolocation, but a failed lookup keeps the values you set. ## 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](https://client.proxybase.org/signup?ref=byparr) and enhance your Byparr experience! ## Tags - `v*.*.*`/`latest` - Releases considered stable - `main` - 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](https://github.com/ThePhaseless/Byparr/issues/22) and [#3](https://github.com/ThePhaseless/Byparr/issues/3) ### Docker Compose setup 1. Review settings in `compose.yaml`. 2. Start the service: ```bash docker compose up -d ``` > [!WARNING] > Byparr performs a *lot* of R/W operations on your disk. To reduce disk wear, it is recommended to allocate temp storage in RAM by adding the following snippet to your Docker Compose configuration: > > ```yaml > shm_size: "1gb" > tmpfs: > - /tmp:exec,mode=1777,size=1G >``` > > Do not mount a tmpfs over `/cache`: it holds the browser baked into the image, and hiding it makes Byparr download it again on every start. ### Docker install 1. Pull and run the image: ```bash docker run -p 8191:8191 ghcr.io/thephaseless/byparr:latest ``` 2. Optional: set env vars using `-e` or `--env-file`. ### Local install 1. Install ([or update when Python version changes](https://github.com/astral-sh/uv/issues/17887)) [uv](https://docs.astral.sh/uv/getting-started/installation/). 2. Clone this repo - `git clone https://github.com/ThePhaseless/Byparr` 3. Run `uv run main.py` 4. Enjoy! ### API Docs Once running, open: - `http://localhost:8191/docs` - `http://localhost:8191/` (redirects to `/docs`) ### Open WebUI Integration Byparr can serve as an external web loader for [Open WebUI](https://github.com/open-webui/open-webui), allowing it to fetch web content through Byparr's anti-bot bypassing capabilities. Configure Open WebUI with these environment variables: ```bash 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 1. Clone repo to the host that has issues with Byparr. 2. Run `docker build --target test .` 3. Depending of the build success: 1. If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies 2. 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`: ```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 1. Download [uv](https://docs.astral.sh/uv/getting-started/installation/) 2. Download dependencies using `uv sync --group test` 3. Run tests with `uv run pytest --retries 3` (You can add `-n auto` for parallelization) 4. If you see any `F` character in terminal, that means test failed even after retries. 5. Depending of the test success: 1. If run successfully, try updating container or if already on newest stable release create an issue for creating new release with new dependencies 2. If test fails, try troubleshooting on another host/using other method