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.15-py3-none-manylinux_2_35_aarch64.whl (4.4 MB view details)

Uploaded Python 3manylinux: glibc 2.35+ ARM64

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

Uploaded Python 3manylinux: glibc 2.31+ x86-64

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

Uploaded Python 3macOS 11.0+ ARM64

pyunbrowser-0.0.15-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.15-py3-none-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.15-py3-none-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 f5ccb9de4e6379c2b76269df32b24ac72e9d6f79c660bc24fb4bdd21d8ada355
MD5 ce1591eaede1af46fa1a96179b0f21b7
BLAKE2b-256 4ed04c862df00414c68c7abaf9447b9104582d9421c8d33b13f7522c324c35c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.15-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.15-py3-none-manylinux_2_31_x86_64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.15-py3-none-manylinux_2_31_x86_64.whl
Algorithm Hash digest
SHA256 b597ae709eb9b35049f59159779de4a6ca0aef4ad7d8ec074b03294d11f2ab29
MD5 bc80b16a9c5592bedaa886ebb98bc21b
BLAKE2b-256 5bab00313b5ab27275f354bb66e7adf92996ec87d0d16aed41757aab0097f2bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.15-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.15-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.15-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 127fd1cbd1be69f7cbf2122c47a7c5512e4ba1db958bac67f1160476f8824bbb
MD5 2b5837ce5b2166b58607b22c55861083
BLAKE2b-256 40cab7bf1e98e6e4f2cfc66d69c20b62ba69827b429247e5e4b465ca6db3aa93

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.15-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.15-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.15-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 53a216fac6f6cb42c51b2630799309530b78e8238c97d264d2bc2863526237d7
MD5 00dcf202043998f3cd1a56e345a63fcc
BLAKE2b-256 03a8d90365fe2a1da32ac448add1870d1899cf7802abd38651c07aa4a42592e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyunbrowser-0.0.15-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