{"_id":"@aquintanar/browser39","_rev":"6-ec635821789f68d27f3067888378dd9d","name":"@aquintanar/browser39","dist-tags":{"latest":"1.8.0"},"versions":{"1.6.0":{"name":"@aquintanar/browser39","version":"1.6.0","keywords":["browser","ai","mcp","headless","markdown","agent"],"license":"Apache-2.0","_id":"@aquintanar/browser39@1.6.0","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"homepage":"https://github.com/alejandroqh/browser39","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"bin":{"browser39":"bin.js"},"dist":{"shasum":"826b66acf2ce40ad5e0975a8d771e03adc52a645","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.6.0.tgz","fileCount":4,"integrity":"sha512-Xjripd4cjt0lvVP4NakxoN0dSFXufOTLn4rvHoC2g5T3mAsDVDRoY7+2BLX8NIlx/B1+1tfwPkNOxzuiFo+u5Q==","signatures":[{"sig":"MEUCICg5hg3WaU+7FUExTuwu0MIsnQZpGXyuPJR4iaUvnkxEAiEAuJMepoMyv67kAOHE9yrufcZBLDpF6R1aUci0XbDaUWM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2117},"main":"index.js","types":"index.d.ts","gitHead":"abc8b92bfb1830696ee258e9ecae4efe09c15a10","_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"repository":{"url":"git+https://github.com/alejandroqh/browser39.git","type":"git"},"_npmVersion":"11.6.4","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"optionalDependencies":{"@aquintanar/browser39-linux-x64":"1.6.0","@aquintanar/browser39-darwin-x64":"1.6.0","@aquintanar/browser39-linux-arm64":"1.6.0","@aquintanar/browser39-darwin-arm64":"1.6.0"},"_npmOperationalInternal":{"tmp":"tmp/browser39_1.6.0_1776009378580_0.2848602973887382","host":"s3://npm-registry-packages-npm-production"}},"1.6.1":{"name":"@aquintanar/browser39","version":"1.6.1","keywords":["browser","ai","mcp","headless","markdown","agent"],"license":"Apache-2.0","_id":"@aquintanar/browser39@1.6.1","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"homepage":"https://github.com/alejandroqh/browser39","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"bin":{"browser39":"bin.js"},"dist":{"shasum":"1b900b167629ba6905d5c19d98caab5b484359bf","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.6.1.tgz","fileCount":5,"integrity":"sha512-KrqCoIlc2RKrDguprnnUD574eSB81f3sCzinhKUQJoEgZYo0H/ewPGggdi0I7sTXapyx+9obs4U8e8t/KQPyVQ==","signatures":[{"sig":"MEUCIQDsWYHlMllj5HBODk0jvLB+KkNuvbucGUjw5MIIS3zsAAIgVZqsQLG8wjCPORC0J7Gy2xfZL7Bx1JkbTj7Mo3nMtHk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15255},"main":"index.js","types":"index.d.ts","gitHead":"7192105e5b78da6ef014c00cd0f40d025f5bfc90","_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"repository":{"url":"git+https://github.com/alejandroqh/browser39.git","type":"git"},"_npmVersion":"11.6.4","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"optionalDependencies":{"@aquintanar/browser39-linux-x64":"1.6.1","@aquintanar/browser39-win32-x64":"1.6.1","@aquintanar/browser39-darwin-x64":"1.6.1","@aquintanar/browser39-linux-arm64":"1.6.1","@aquintanar/browser39-darwin-arm64":"1.6.1"},"_npmOperationalInternal":{"tmp":"tmp/browser39_1.6.1_1776010587336_0.3915904313572067","host":"s3://npm-registry-packages-npm-production"}},"1.6.3":{"name":"@aquintanar/browser39","version":"1.6.3","keywords":["browser","ai","mcp","headless","markdown","agent"],"license":"Apache-2.0","_id":"@aquintanar/browser39@1.6.3","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"homepage":"https://github.com/alejandroqh/browser39","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"bin":{"browser39":"bin.js"},"dist":{"shasum":"5627522c24d77ddeefff5fdc2730d9201e588012","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.6.3.tgz","fileCount":5,"integrity":"sha512-NxfN62pUk7HBIbvdHy2EAWNGYzbcYlgXL6SqbxfKFryKz2SVtwSYxo8uqta2W1YzvpoUQQCv/ZWadLY97CNSiw==","signatures":[{"sig":"MEUCIDPw/1vk4pKL4Js3Q2KVFoIphOEMipYNhhh/Ykv93LyLAiEAyUMYe51iKSKbvy8clO2C+b8AWkBZwaQCMGH56QyO8sY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12710},"main":"index.js","types":"index.d.ts","gitHead":"bcb2570ed2885dda90d054820c24783e2d2820dc","_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"repository":{"url":"git+https://github.com/alejandroqh/browser39.git","type":"git"},"_npmVersion":"11.13.0","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"optionalDependencies":{"@aquintanar/browser39-linux-x64":"1.6.3","@aquintanar/browser39-win32-x64":"1.6.3","@aquintanar/browser39-darwin-x64":"1.6.3","@aquintanar/browser39-linux-arm64":"1.6.3","@aquintanar/browser39-darwin-arm64":"1.6.3"},"_npmOperationalInternal":{"tmp":"tmp/browser39_1.6.3_1777147189199_0.4917282281791924","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"name":"@aquintanar/browser39","version":"1.7.0","keywords":["browser","ai","mcp","headless","markdown","agent"],"license":"Apache-2.0","_id":"@aquintanar/browser39@1.7.0","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"homepage":"https://github.com/alejandroqh/browser39","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"bin":{"browser39":"bin.js"},"dist":{"shasum":"63fb7edbcb35480514edc241d26f36731f18cd6b","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.7.0.tgz","fileCount":5,"integrity":"sha512-xiKbZFs+hNZKhZ20DnrAIqFWXO9XT0cW8CGJMjL/k+AnVfIacAFzzkwkMwOFvb2Z7sgifD3gVNDPhUqOmPbdQw==","signatures":[{"sig":"MEUCIQDa2Sq8fM2tGH0r4vA63kYmR1riiS5foDXkG9FTpXYHiAIgIGXoPUbqV0bN9PCp1TO/6I909rrYJWbxY1cdwvrTGeM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12710},"main":"index.js","types":"index.d.ts","gitHead":"adf8ecbe8277d336e37dbd292b86db461f526c8a","_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"repository":{"url":"git+https://github.com/alejandroqh/browser39.git","type":"git"},"_npmVersion":"11.13.0","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"optionalDependencies":{"@aquintanar/browser39-linux-x64":"1.7.0","@aquintanar/browser39-win32-x64":"1.7.0","@aquintanar/browser39-darwin-x64":"1.7.0","@aquintanar/browser39-linux-arm64":"1.7.0","@aquintanar/browser39-darwin-arm64":"1.7.0"},"_npmOperationalInternal":{"tmp":"tmp/browser39_1.7.0_1777496194195_0.32115440815185714","host":"s3://npm-registry-packages-npm-production"}},"1.7.1":{"name":"@aquintanar/browser39","version":"1.7.1","keywords":["browser","ai","mcp","headless","markdown","agent"],"license":"Apache-2.0","_id":"@aquintanar/browser39@1.7.1","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"homepage":"https://github.com/alejandroqh/browser39","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"bin":{"browser39":"bin.js"},"dist":{"shasum":"6a3946bafbb3bafb3ce956a8598dead4164f9eee","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.7.1.tgz","fileCount":5,"integrity":"sha512-jYE1hD8Q4c3QMMaVbO7oGs6n9iWlFTVuI8jlVR9WjCg8xwmJLFO1gBo+CyJEzbdEKMoZ8pyim/zgMUv9xisHFw==","signatures":[{"sig":"MEYCIQDhToez37n3sU/pbPfqlQDplb5Rufh9xi9pQNQT61skvwIhALj1/FPGEf8XBtP+3s+9RIyNnYHlDnHLaEkgQsIKkrfy","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12710},"main":"index.js","types":"index.d.ts","gitHead":"7576c14c67c29a36fc47ab173459b0e85af27e55","_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"repository":{"url":"git+https://github.com/alejandroqh/browser39.git","type":"git"},"_npmVersion":"11.13.0","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","directories":{},"_nodeVersion":"22.17.1","_hasShrinkwrap":false,"optionalDependencies":{"@aquintanar/browser39-linux-x64":"1.7.1","@aquintanar/browser39-win32-x64":"1.7.1","@aquintanar/browser39-darwin-x64":"1.7.1","@aquintanar/browser39-linux-arm64":"1.7.1","@aquintanar/browser39-darwin-arm64":"1.7.1"},"_npmOperationalInternal":{"tmp":"tmp/browser39_1.7.1_1778144709067_0.05851773958910833","host":"s3://npm-registry-packages-npm-production"}},"1.8.0":{"name":"@aquintanar/browser39","version":"1.8.0","description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/alejandroqh/browser39.git"},"homepage":"https://github.com/alejandroqh/browser39","keywords":["browser","ai","mcp","headless","markdown","agent"],"main":"index.js","types":"index.d.ts","bin":{"browser39":"bin.js"},"optionalDependencies":{"@aquintanar/browser39-darwin-arm64":"1.8.0","@aquintanar/browser39-darwin-x64":"1.8.0","@aquintanar/browser39-linux-x64":"1.8.0","@aquintanar/browser39-linux-arm64":"1.8.0","@aquintanar/browser39-win32-x64":"1.8.0"},"gitHead":"c264ae4da6ffc1689ddcf1de67586f2b1f49b63d","_id":"@aquintanar/browser39@1.8.0","bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"_nodeVersion":"22.17.1","_npmVersion":"11.13.0","dist":{"integrity":"sha512-vvXCdVAlS9tuJOp3PJB7XAN/mvTsauEoi8Bp38rI8lJJNjhV+7rmAJzh2KZo32rUJDaRvKxPF6TQ5iLe/18BmQ==","shasum":"09ca37d62a998c224288944337c2387887223c7f","tarball":"https://registry.npmjs.org/@aquintanar/browser39/-/browser39-1.8.0.tgz","fileCount":5,"unpackedSize":14329,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIE19Clbm+rwlPeZqTNsBN7P/XP8di+hTn7qtFioOdzmgAiEAkNuWKU+3W6To1nLfHPcl4/kohYU9eveXWMyGgotYz3c="}]},"_npmUser":{"name":"aquintanar","email":"alejandro@quihel.net"},"directories":{},"maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/browser39_1.8.0_1779307737229_0.6768883816339897"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-12T15:56:18.435Z","modified":"2026-05-20T20:08:57.473Z","1.6.0":"2026-04-12T15:56:18.706Z","1.6.1":"2026-04-12T16:16:27.454Z","1.6.3":"2026-04-25T19:59:49.344Z","1.7.0":"2026-04-29T20:56:34.394Z","1.7.1":"2026-05-07T09:05:09.269Z","1.8.0":"2026-05-20T20:08:57.377Z"},"bugs":{"url":"https://github.com/alejandroqh/browser39/issues"},"license":"Apache-2.0","homepage":"https://github.com/alejandroqh/browser39","keywords":["browser","ai","mcp","headless","markdown","agent"],"repository":{"type":"git","url":"git+https://github.com/alejandroqh/browser39.git"},"description":"A headless web browser for AI agents. Converts pages to token-optimized Markdown. Single binary, no external browser.","maintainers":[{"name":"aquintanar","email":"alejandro@quihel.net"}],"readme":"<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/alejandroqh/browser39/main/docs/logo.png\" alt=\"browser39\" width=\"500\">\n</p>\n\n# browser39\n\nA headless browser for AI agents that fetches modern web pages, runs JavaScript, manages sessions, and returns token-efficient Markdown.\n\n- **Handles modern sites.** Executes JavaScript, fills forms, queries the DOM, persists cookies and sessions across runs.\n- **LLM-usable output.** Compact Markdown with content preselection, so the agent reads the section it needs, not the whole page.\n- **Local-only.** No data sent to third-party services.\n- **Single binary.** No Chrome, no Puppeteer. ~52MB. macOS, Linux, Windows.\n\n## Comparison\n\n|  | browser39 | Playwright / Puppeteer | Raw HTTP (requests, ureq) |\n|--|-----------|----------------------|---------------------------|\n| External browser | None (single binary) | Requires Chrome/Chromium | None |\n| Binary size | ~52MB | ~280MB with browser | N/A (library) |\n| Platforms | macOS, Linux, Windows | macOS, Linux, Windows | Any |\n| JavaScript | Yes (V8 via deno_core) | Yes (full V8) | No |\n| HTML to Markdown | Built-in, token-optimized | No (raw HTML or screenshots) | DIY |\n| Token preselection | Content sections, agent picks what to read | No | No |\n| Cookies & sessions | Automatic, persisted, encrypted | Manual | Manual |\n| DOM queries | CSS selectors + full JS DOM API | Full DOM API | No |\n| Forms | fill + submit | Full interaction | Manual POST |\n| Auth & secrets | Profiles, redaction, opaque handles | Manual | Manual |\n| Transports | MCP (stdio + HTTP), JSONL, CLI | Library API | Library API |\n\n### Token savings in practice\n\nReal test: extracting the \"Optical communications\" section from [Artemis II on Wikipedia](https://en.wikipedia.org/wiki/Artemis_II) (full page: ~14,600 tokens).\n\n| | Raw HTTP | WebFetch (Claude Code built-in) | [Mistral Web Search](https://docs.mistral.ai/agents/tools/built-in/websearch) | browser39 |\n|--|----------|--------------------------------|-------------------|-----------|\n| **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 |\n| **Tokens consumed** | ~1,000 (truncated) | ~14,600 (processed by intermediate model) | Cloud processed, not disclosed | **196** |\n| **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 |\n| **Content quality** | Nav menus, infobox, article intro | Paraphrased, no links, no references | Summary with citations | Lossless markdown with links and citations |\n| **Session state** | None | None | None | Cookies, history, follow-up queries free |\n| **Data processing** | Local | Processed remotely | Processed remotely | Local |\n| **Cost per call** | Free | Bundled | [$30 / 1,000 calls](https://mistral.ai/pricing#api) | Free |\n| **Retries needed** | Pagination to find it | None, but no control over output | May not find specific section | None. Agent sees structure first |\n\nbrowser39 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.\n\n## Install\n\n```bash\nnpm install @aquintanar/browser39\n```\n\nOr via Cargo:\n\n```bash\ncargo install browser39\n```\n\n### Install for any AI CLI / IDE\n\nInstalls the binary and auto-configures it for every MCP client detected: **Claude Code**, **Claude Desktop**, **Codex**, **OpenCode**, **OpenClaw**.\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/alejandroqh/marketplace/main/h39.sh | bash\n```\n\nPre-built binaries available on the [releases page](https://github.com/alejandroqh/browser39/releases).\n\n## Quick Start\n\n### MCP config\n\nAdd to your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"browser39\": {\n      \"command\": \"browser39\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n29 tools available instantly: `browser39_fetch`, `browser39_click`, `browser39_links`, `browser39_dom_query`, `browser39_fill`, `browser39_submit`, `browser39_search`, cookies, storage, history, config management, and more.\n\n### CLI: one-shot fetch\n\n```bash\nbrowser39 fetch https://example.com\n```\n\n```\n# Example Domain\nThis domain is for use in documentation examples without needing permission.\n\n[Learn more](https://iana.org/domains/example)\n```\n\n### CLI: one-shot search\n\nSearch the web using the configured search engine:\n\n```bash\nbrowser39 search \"rust async traits\"\n```\n\nAdd `--output json` for structured results suitable for piping into other tools.\n\n### CLI: agent integration (watch mode)\n\nLong-running subprocess that any language can talk to via JSONL files:\n\n```bash\ntouch commands.jsonl\nbrowser39 watch commands.jsonl --output results.jsonl\n```\n\n```bash\n# From your agent (Python, Node, Rust, shell, anything):\necho '{\"id\":\"1\",\"action\":\"fetch\",\"v\":1,\"seq\":1,\"url\":\"https://example.com\"}' >> commands.jsonl\n```\n\nDrop-in `web_search` and `visit_website` tool examples: **[Python](examples/browser39_tools.py)** | **[TypeScript](examples/browser39_tools.ts)** | **[Rust](examples/browser39_tools.rs)**\n\nSee [docs/install-cli.md](docs/install-cli.md) for the full integration guide.\n\n### Rust library\n\nEmbed browser39 directly in a Rust application — no subprocess, no IPC.\n\n```toml\n[dependencies]\nbrowser39 = \"1.8\"\ntokio = { version = \"1\", features = [\"full\"] }\nanyhow = \"1\"\n```\n\n```rust\nuse std::collections::HashMap;\n\nuse browser39::{BrowserService, Config, HttpMethod, InMemoryStore, SessionStore};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let store: Box<dyn SessionStore> = Box::new(InMemoryStore);\n    let mut service = BrowserService::new(Config::default(), store).await?;\n\n    let options = service.default_fetch_options();\n    let page = service\n        .fetch(\n            \"https://example.com\",\n            &HttpMethod::Get,\n            &HashMap::new(),\n            None,\n            None,\n            &options,\n        )\n        .await?;\n\n    println!(\"{}\", page.markdown);\n    Ok(())\n}\n```\n\nThe crate root re-exports the common types: `BrowserService`, `Config`, `PersistenceMode`, `FetchOptions`, `HttpMethod`, `SessionStore`, `InMemoryStore`, `create_session_store`. Lower-level modules (`browser39::core`, `browser39::cli`, `browser39::mcp`) are also public if you need direct access to the HTML→Markdown engine, JSONL runner, or MCP server.\n\n## Features\n\n### Token optimization\n\nbrowser39 minimizes token usage when feeding web content to LLMs:\n\n- **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`.\n- **Heading auto-expand**: `selector: \"#Astronauts\"` returns the full section until the next same-level heading, not just the heading text.\n- **HTML to Markdown**: strips scripts, styles, and non-content elements.\n- **Compact link references** (JSON mode): `[text][N]` instead of inline URLs, with full URLs in the `links` array.\n- **Same-origin URL shortening**: links on the same domain show path-only.\n- **Link deduplication**: same-URL links (image + headline cards) emitted once.\n\n### JavaScript execution\n\nV8 (via deno_core) runs JavaScript against a full DOM environment:\n\n- **Traversal**: `parentElement`, `children`, `firstChild`, `lastChild`, `nextSibling`, `previousSibling`, `closest()`, `matches()`, `contains()`\n- **Lookup**: `getElementById`, `getElementsByClassName`, `getElementsByTagName`, `getElementsByName`\n- **Mutation**: `createElement`, `createTextNode`, `appendChild`, `removeChild`, `insertBefore`, `setAttribute`, `removeAttribute`, `textContent`/`innerHTML` setters\n- **Events**: `addEventListener`, `removeEventListener`, `dispatchEvent`, `new Event`/`CustomEvent`/`MouseEvent`/`KeyboardEvent`/`InputEvent`\n- **Web APIs**: `localStorage`, `document.cookie`, `console.log` (captured), `setTimeout`, `atob`/`btoa`, `getComputedStyle`, `MutationObserver`\n- **Forms**: `element.value` get/set, `element.click()`, `form.submit()`\n\n```json\n{\"action\": \"dom_query\", \"script\": \"document.querySelectorAll('a').length\"}\n{\"action\": \"dom_query\", \"script\": \"document.getElementById('content').closest('section').textContent\"}\n{\"action\": \"dom_query\", \"script\": \"document.querySelector('h1').setAttribute('class', 'modified')\"}\n```\n\n### Session persistence\n\nCookies, 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.\n\nDisable with `--no-persist` or config:\n\n```toml\n[session]\npersistence = \"memory\"\n```\n\n### Forms\n\nFill fields by CSS selector and submit. browser39 handles `enctype`, builds the HTTP request, and returns the response page:\n\n```json\n{\"action\": \"fill\", \"fields\": [{\"selector\": \"#user\", \"value\": \"agent\"}, {\"selector\": \"#pass\", \"value\": \"secret\", \"sensitive\": true}]}\n{\"action\": \"submit\", \"selector\": \"form#login\"}\n```\n\n### Security\n\nAuth profiles keep credentials out of the LLM conversation. The agent references a profile name and never sees the token:\n\n```toml\n[auth.github]\nheader = \"Authorization\"\nvalue_env = \"GITHUB_TOKEN\"\nvalue_prefix = \"Bearer \"\ndomains = [\"api.github.com\"]\n```\n\n```json\n{\"action\": \"fetch\", \"url\": \"https://api.github.com/repos\", \"auth_profile\": \"github\"}\n```\n\n### Config management via MCP\n\nAgents can manage browser39's configuration directly through MCP tools: change the search engine, store credentials, manage auth profiles, cookies, storage, and headers. Sensitive values are stored securely on disk but **never returned** via MCP; `config_show` masks them with `••••••`.\n\n```\n> browser39_config_set key=\"search.engine\" value=\"https://www.google.com/search?q={}\"\nSet search.engine = https://www.google.com/search?q={}\n\n> browser39_config_auth_set name=\"github\" header=\"Authorization\" value=\"Bearer ghp_...\" domains=[\"api.github.com\"]\nAuth profile 'github' saved\n\n> browser39_config_show section=\"auth\"\n{\"auth\": {\"github\": {\"header\": \"Authorization\", \"value\": \"••••••\", ...}}}\n```\n\n10 config tools: `config_show`, `config_set`, `config_auth_set/delete`, `config_cookie_set/delete`, `config_storage_set/delete`, `config_header_set/delete`.\n\n### All transports\n\n| Transport | Command | Use case |\n|-----------|---------|----------|\n| MCP (stdio) | `browser39 mcp` | Local MCP clients |\n| MCP (HTTP) | `browser39 mcp --transport sse --port 8039` | Remote agents, cloud deployments |\n| JSONL watch | `browser39 watch commands.jsonl` | Any language, long-running agent IPC |\n| JSONL batch | `browser39 batch commands.jsonl` | One-shot scripted operations |\n| CLI fetch | `browser39 fetch <url>` | Quick page retrieval, shell scripts |\n| CLI search | `browser39 search <query>` | Quick web search from shell scripts |\n| Rust library | `cargo add browser39` | Embed in Rust apps, no subprocess |\n\n## Configuration\n\n```bash\nbrowser39 --config path/to/config.toml fetch https://example.com\n```\n\nPrecedence: `--config` flag > `BROWSER39_CONFIG` env > `~/.config/browser39/config.toml`\n\nSee [docs/config.md](docs/config.md) for the full reference.\n\n## Documentation\n\n| Doc | Description |\n|-----|-------------|\n| [install-cli.md](docs/install-cli.md) | CLI integration guide with Rust, Python, TypeScript examples |\n| [jsonl-protocol.md](docs/jsonl-protocol.md) | Full JSONL protocol specification |\n| [config.md](docs/config.md) | Configuration reference |\n\n## Development\n\n```bash\ncargo build              # Build\ncargo run                # Run\ncargo test               # Run all tests\ncargo clippy             # Lint\ncargo fmt                # Format\n```\n\n## Contributors\n\n[@nathan-widjaja](https://github.com/nathan-widjaja)\n\n[@janpauldahlke](https://github.com/janpauldahlke)\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}