browser39

agent
Security Audit
Fail
Health Warn
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 6 GitHub stars
Code Fail
  • network request — Outbound network request in examples/browser39_tools.py
  • execSync — Synchronous shell command execution in examples/browser39_tools.ts
  • network request — Outbound network request in examples/browser39_tools.ts
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This tool provides a headless web browser designed for AI agents. It fetches web pages, runs JavaScript, and converts HTML into token-optimized Markdown locally without requiring an external browser.

Security Assessment
The core Rust binary is self-contained and does not request dangerous system permissions. However, there are notable risks in the codebase. Example files include outbound network requests, which is expected given the tool's function. More concerning is a failed security check: the repository uses synchronous shell command execution in one of its example scripts (`examples/browser39_tools.ts`). While the primary engine keeps data processing strictly local and avoids sending information to third-party cloud services, executing shell commands introduces potential vulnerabilities depending on how they are implemented. Overall risk is rated as Medium.

Quality Assessment
The project is licensed under Apache-2.0 and is actively maintained, with its most recent code push happening today. Despite active development, the tool suffers from extremely low community visibility, currently sitting at only 6 GitHub stars. Consequently, the project has not undergone the extensive peer review, testing, or community trust-building that more popular open-source tools benefit from.

Verdict
Use with caution — the tool is actively maintained and keeps data local, but low community adoption and the presence of synchronous shell command execution in the examples warrant a careful code review before integrating into production environments.
SUMMARY

A headless web browser for AI agents. Converts pages to token-optimized Markdown locally. Single binary, no external browser, no fees.

README.md

browser39

browser39

A headless open source web browser for AI agents. Converts pages to token-optimized Markdown locally. Single binary, no external browser, no fees.

browser39 fetches web pages and converts them to token-optimized Markdown that LLMs can actually consume. It runs JavaScript, manages cookies and sessions, queries the DOM, and fills forms. All processing happens locally, no data is sent to third-party services.

Works with: Claude Desktop & Claude Code | OpenClaw | Any agent via CLI

Comparison

browser39 Playwright / Puppeteer Raw HTTP (requests, ureq)
External browser None (single binary) Requires Chrome/Chromium None
Binary size ~22MB ~280MB with browser N/A (library)
Platforms macOS, Linux, Windows macOS, Linux, Windows Any
JavaScript Yes (boa_engine) Yes (full V8) No
HTML to Markdown Built-in, token-optimized No (raw HTML or screenshots) DIY
Token preselection Content sections, agent picks what to read No No
Cookies & sessions Automatic, persisted, encrypted Manual Manual
DOM queries CSS selectors + JS expressions Full DOM API No
Forms fill + submit Full interaction Manual POST
Auth & secrets Profiles, redaction, opaque handles Manual Manual
Transports MCP (stdio + HTTP), JSONL, CLI Library API Library API

Token savings in practice

Real test: extracting the "Optical communications" section from Artemis II on Wikipedia (full page: ~14,600 tokens).

Raw HTTP WebFetch (Claude Code built-in) Mistral Web Search browser39
How it works Fetch full page, truncate to ~1,000 tokens Send full page (~14,600 tokens) to intermediate model with extraction prompt Cloud API: search + page processing by Mistral model Fetch → content selectors list → targeted section fetch
Tokens consumed ~1,000 (truncated) ~14,600 (processed by intermediate model) Cloud processed, not disclosed 196
Found the section? No. Section is at token ~6,320, truncated away Yes, but returns a lossy summary Depends on search ranking Yes. Exact original content
Content quality Nav menus, infobox, article intro Paraphrased, no links, no references Summary with citations Lossless markdown with links and citations
Session state None None None Cookies, history, follow-up queries free
Data processing Local Processed remotely Processed remotely Local
Cost per call Free Bundled $30 / 1,000 calls Free
Retries needed Pagination to find it None, but no control over output May not find specific section None. Agent sees structure first

browser39 returns the exact section in 196 tokens at zero cost. The raw approach misses it entirely, WebFetch burns 75x more tokens through an intermediate model, and cloud tools like Mistral's charge $0.03 per call.

Install

cargo install browser39

Pre-built binaries available on the releases page.

Auto-install prompts

Copy and paste into your agent to install browser39 automatically:

Claude Code

Install browser39 as an MCP server. Clone https://github.com/alejandroqh/browser39.git, build with cargo build --release, copy the binary to /usr/local/bin/browser39, then add it to MCP settings with command "browser39" and args ["mcp"].

OpenClaw

Install the browser39 plugin: openclaw plugins install https://github.com/alejandroqh/browser39.git && openclaw gateway restart

Quick Start

Claude Desktop / Claude Code (MCP)

Add to your MCP settings:

{
  "mcpServers": {
    "browser39": {
      "command": "browser39",
      "args": ["mcp"]
    }
  }
}

19 tools available instantly: browser39_fetch, browser39_click, browser39_links, browser39_dom_query, browser39_fill, browser39_submit, browser39_search, cookies, storage, history, and more.

See docs/install-claude.md for the full guide.

OpenClaw

openclaw plugins install https://github.com/alejandroqh/browser39.git
openclaw gateway restart

See docs/install-openclaw.md for bundle vs native plugin setup.

CLI: one-shot fetch

browser39 fetch https://example.com
# Example Domain
This domain is for use in documentation examples without needing permission.

[Learn more](https://iana.org/domains/example)

CLI: agent integration (watch mode)

Long-running subprocess that any language can talk to via JSONL files:

touch commands.jsonl
browser39 watch commands.jsonl --output results.jsonl
# From your agent (Python, Node, Rust, shell, anything):
echo '{"id":"1","action":"fetch","v":1,"seq":1,"url":"https://example.com"}' >> commands.jsonl

Drop-in web_search and visit_website tool examples: Python | TypeScript | Rust

See docs/install-cli.md for the full integration guide.

Features

Token optimization

browser39 minimizes token usage when feeding web content to LLMs:

  • Content preselection: on first fetch, returns available content sections with token estimates instead of dumping the full page. The agent picks the relevant section and re-fetches with a targeted selector.
  • Heading auto-expand: selector: "#Astronauts" returns the full section until the next same-level heading, not just the heading text.
  • HTML to Markdown: strips scripts, styles, and non-content elements.
  • Compact link references (JSON mode): [text][N] instead of inline URLs, with full URLs in the links array.
  • Same-origin URL shortening: links on the same domain show path-only.
  • Link deduplication: same-URL links (image + headline cards) emitted once.

JavaScript execution

boa_engine runs JS expressions against the parsed DOM. Supports document.querySelector, document.querySelectorAll, element properties, localStorage, document.cookie, form.submit(), and element.click().

{"action": "dom_query", "script": "document.querySelectorAll('a').length"}

Session persistence

Cookies, localStorage, and browsing history are persisted to disk by default (~/.local/share/browser39/session.enc, AES-256-GCM encrypted). An agent can log in once and stay authenticated across restarts.

Disable with --no-persist or config:

[session]
persistence = "memory"

Forms

Fill fields by CSS selector and submit. browser39 handles enctype, builds the HTTP request, and returns the response page:

{"action": "fill", "fields": [{"selector": "#user", "value": "agent"}, {"selector": "#pass", "value": "secret", "sensitive": true}]}
{"action": "submit", "selector": "form#login"}

Security

Auth profiles keep credentials out of the LLM conversation. The agent references a profile name and never sees the token:

[auth.github]
header = "Authorization"
value_env = "GITHUB_TOKEN"
value_prefix = "Bearer "
domains = ["api.github.com"]
{"action": "fetch", "url": "https://api.github.com/repos", "auth_profile": "github"}

All transports

Transport Command Use case
MCP (stdio) browser39 mcp Claude Desktop, Claude Code, local MCP clients
MCP (HTTP) browser39 mcp --transport sse --port 8039 Remote agents, cloud deployments
JSONL watch browser39 watch commands.jsonl Any language, long-running agent IPC
JSONL batch browser39 batch commands.jsonl One-shot scripted operations
CLI fetch browser39 fetch <url> Quick page retrieval, shell scripts

Configuration

browser39 --config path/to/config.toml fetch https://example.com

Precedence: --config flag > BROWSER39_CONFIG env > ~/.config/browser39/config.toml

See docs/config.md for the full reference.

Documentation

Doc Description
install-claude.md Claude Desktop and Claude Code setup
install-openclaw.md OpenClaw bundle and native plugin
install-cli.md CLI integration guide with Rust, Python, TypeScript examples
jsonl-protocol.md Full JSONL protocol specification
config.md Configuration reference

Development

cargo build              # Build
cargo run                # Run
cargo test               # Run all tests
cargo clippy             # Lint
cargo fmt                # Format

Reviews (0)

No results found