Skip to main content

Web access for LLM agents. One static binary. No Chrome.

Project description

unbrowser

Web access for LLM agents. One static binary. No Chrome.

Single-file native headless browser optimized for LLM agents. Runs JavaScript via QuickJS, returns a low-token page summary on every navigate, and gives you stable element refs for click/type/submit. Tens of MB RAM per session, no Chrome dependency.

pip install pyunbrowser   # PyPI name; the import is `from unbrowser import ...`

The wheel ships the native binary for your platform — there's nothing else to install.

For transparent bot-wall cookie handoff through local Chrome, install the optional solver extra:

pip install 'pyunbrowser[solver]'  # includes unchainedsky-cli
unbrowser cookie-service --headless --profile unbrowser-cookie-service
unbrowser router https://example.com/protected

The solver service binds to 127.0.0.1 by default and returns cookies from the user's local Chrome/unchained session. It does not fabricate challenge tokens. Private/reserved/internal hosts are rejected unless explicitly allowed with --allow-host. Non-loopback binds are rejected unless --allow-remote-bind is passed because /solve is unauthenticated and can return browser cookies. Router refuses non-loopback cookie service URLs by default because it sends target URLs and challenge metadata to that service; use --allow-remote-cookie-service only for a trusted remote solver.

Quick start

from unbrowser import Client

with Client() as ub:
    r = ub.navigate("https://news.ycombinator.com")
    for s in ub.query(".titleline > a")[:3]:
        print(s["text"], s["attrs"]["href"])

Why

curl This Playwright / headless Chrome
Static / SSR pages ✅ but token-heavy ✅ low-token BlockMap overkill
SPA-shell sites (with exec_scripts) ⚠️ partial
Bot-walled (cookie handoff)
Run in Lambda / Workers / edge ❌ Chrome too big
Per-page cost at 100K/day ~free ~free $$$
LLM-shaped output DIY parse ✅ inline BlockMap DIY parse

What it does

  • navigate(url) — fetch, parse, return {status, url, bytes, headers, blockmap, challenge}. With exec_scripts=True, runs page JS in QuickJS (bounded by a 30s watchdog so it can't wedge).
  • query(selector) — CSS query → [{ref, tag, attrs, text, text_chars, text_truncated}]. Refs are stable handles for click/type/submit.
  • query_debug(selector) — diagnose selector misses with match counts, samples, DOM summary, and selector hints.
  • extract() — auto-strategy structured data: tries JSON-LD → __NEXT_DATA__ → Nuxt → OpenGraph → microdata → text fallback, returns highest-confidence hit.
  • extract_table(selector) / table_to_json(selector="table") — normalize HTML tables into headers, rows, and row count.
  • click(ref) / type(ref, text) / submit(ref) — interaction. GET and application/x-www-form-urlencoded POST forms supported; multipart is not yet supported. Checked checkbox/radio values are serialized.
  • cookies_set(...) — paste cookies from a real Chrome session to bypass bot detection (Cloudflare, PerimeterX, Datadome). Solve once, replay forever.

Full RPC reference, BlockMap shape, challenge detection, profile system, and architecture: github.com/protostatis/unbrowser.

Honest limits

  • Heavy framework SPAs (Ember/React) often don't auto-mount inside QuickJS even with exec_scripts=True — the watchdog ensures it returns, check density.likely_js_filled to decide whether to escalate.
  • No screenshots (out of scope by design).
  • Hardest-tier anti-bot (FingerprintJS Pro, Kasada, advanced Akamai BMP) needs the cookie handoff path. The binary detects and labels the challenge for you.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyunbrowser-0.0.17-py3-none-manylinux_2_35_aarch64.whl (4.4 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ ARM64

pyunbrowser-0.0.17-py3-none-manylinux_2_31_x86_64.whl (4.5 MB view details)

Uploaded Python 3manylinux: glibc 2.31+ x86-64

pyunbrowser-0.0.17-py3-none-macosx_11_0_arm64.whl (4.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

pyunbrowser-0.0.17-py3-none-macosx_10_12_x86_64.whl (4.4 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file pyunbrowser-0.0.17-py3-none-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.17-py3-none-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 d2513a9dc9b1c1ad32b94f7c4c69c177ca1cd96a43574b9a51376b00ac09a277
MD5 6476a90e05ae4f1a87f4868f88e8d4fd
BLAKE2b-256 9007a580857ef731edc34c7d4c12ab50f8bf836e71accf5011146d70080138ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.17-py3-none-manylinux_2_35_aarch64.whl:

Publisher: release.yml on protostatis/unbrowser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyunbrowser-0.0.17-py3-none-manylinux_2_31_x86_64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.17-py3-none-manylinux_2_31_x86_64.whl
Algorithm Hash digest
SHA256 38b00856ae2828e05ad8d66e22f62f20d6cfb66bd4807c5be14a1eb03665e0a8
MD5 d4432c161c55ebbc80c6ebf38d77d0fd
BLAKE2b-256 74994ec203ceb8fbfc763702f64bb2cd3a8c404bbe24f39eb378836f3b100282

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.17-py3-none-manylinux_2_31_x86_64.whl:

Publisher: release.yml on protostatis/unbrowser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyunbrowser-0.0.17-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.17-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2907dd899710bb557808f5139d7497f1519042e29fc8f74dcbf6f63ff051a74e
MD5 08679cf7c46869b1a3099cdab24d9d8c
BLAKE2b-256 6c9a386ea79f0b126128df91b96e95ebab3af172927d59a2a981339fcee7c2c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.17-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on protostatis/unbrowser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyunbrowser-0.0.17-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.17-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ffeb0d18efd716c3488c2a7d497636e617546bb4689500e72b422eafe2bac3e6
MD5 e07ee3f23e798e95b8da091f8e1226f1
BLAKE2b-256 bae1ca23163c3e02540f4498bd0f93c70e3b59e98145ed8a993b01efedb0df5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.17-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on protostatis/unbrowser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page