Skip to main content

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.

unbrowser is the lightweight browser tier from Unchained. Run the live public-web demo before installing; no account is required, and the demo accepts only the fixed public source sets shown on the page.

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.

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

Uploaded Python 3manylinux: glibc 2.35+ ARM64

pyunbrowser-0.0.20-py3-none-manylinux_2_31_x86_64.whl (4.6 MB view details)

Uploaded Python 3manylinux: glibc 2.31+ x86-64

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

Uploaded Python 3macOS 11.0+ ARM64

pyunbrowser-0.0.20-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.20-py3-none-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for pyunbrowser-0.0.20-py3-none-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 46392d57c7359868302d144fabc9dc8c14207735923cd7fdf1f865441db15bc9
MD5 8204ca0f13143d2482e82d719117e5a4
BLAKE2b-256 7c51bb47f03e0f918f629c0898b5770668818238944f4fd84b3f94b9180421ad

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyunbrowser-0.0.20-py3-none-manylinux_2_31_x86_64.whl
Algorithm Hash digest
SHA256 e2f056575835b47d8c3a2d6e8b2bee024384a865da00a57e7fc5c43e89284f73
MD5 09f88c618ff26b9412c2bd68e89d8350
BLAKE2b-256 a2dc8f482f2dd9c9ef807571b9a8426890e6561c0bb9a3f64a76e55fb69804d6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyunbrowser-0.0.20-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 856ee4118371ef7341ee80620612ea675cd2518ca1ab6f0c4ecb85a9fdbcc907
MD5 12c098ac5ce7d038b090c44e1d26bd7b
BLAKE2b-256 65e6193f4f1e8f05ad38e28c2278fe2cf39547e5d17cf42d52d8422539c56c93

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pyunbrowser-0.0.20-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 722c0cd7b80e66f00dc0d51cdddb459fee11ae3694d77f45f81173754e4b965f
MD5 c2ccf4045292bd1c643eb18336f6921f
BLAKE2b-256 e7f1d66e7388b788850953427dfc424cb6f3cd5d8bb4b2f5d837c53eee123a5e

See more details on using hashes here.

Provenance

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

Release history Release notifications | RSS feed

0.0.21

4 files

This release

0.0.20 This release

4 files

0.0.19

4 files

0.0.18

4 files

0.0.17

4 files

0.0.16

4 files

0.0.15

4 files

0.0.14

4 files

0.0.13

4 files

0.0.12

4 files

0.0.11

5 files

0.0.10

5 files

0.0.9

5 files

0.0.8

5 files

0.0.6

4 files

0.0.5

4 files

0.0.4

3 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page