Public Browser is an MCP server that lets Claude Code, Cursor, and any MCP-compatible client drive a Chrome browser. It communicates with Chrome directly through the Chrome DevTools Protocol (CDP), without relying on Playwright, an extension bridge, or needing to execute shell commands for every step. Installation takes a single command, with zero configuration.
Main capabilities
- Lower token consumption: every tool call makes the model re-read the previous conversation, so the total session token count is the real cost. On the benchmark page, Public Browser 3.0's median token count across five runs was 3.0M, while agent-browser needed 4.5M. Its advantage comes from fewer, denser steps: run_plan can execute multiple actions with variables and conditions in a single call; since 3.0, responses reduce repetition, diffs show only what changed, text already shown in a parent line is no longer repeated, and hints appear only once per session.
- Explicit failure instead of silent failure: a CSS selector that matches multiple elements does not perform any action, but instead returns the candidate elements and their refs. Refs are saved per tab and never reused, so a ref from a page you have left reports a stale ref instead of clicking the node currently occupying that number. When a drag has no effect, it returns Drag not confirmed, and when a click opens a new tab, it indicates the new tab.
- Support for nested cross-origin iframes and shadow DOM: clicks can reach elements inside a cross-origin iframe that is itself inside another cross-origin iframe; open and closed shadow roots can also be read.
- Two ways to integrate without an LLM: the Node library (createSession()) and the Python client (pip install publicbrowser) run the same tool handlers as the MCP server.
How to use Install in Claude Code: a single command installs it globally for all projects. After installation, you must fully quit and reopen Claude Code; /mcp reconnect is not enough, because Claude Code only reads the mcpServers configuration at the start of a session and caches it. After restarting, the first tool call automatically launches a visible Chrome, no headless or port setup required. To enable parallel Python Script API access, add --script to the arguments. Install in Cursor: add to ~/.cursor/mcp.json. Install in Cline: add to cline_mcp_settings.json. Other MCP clients: any client that supports stdio MCP servers, using npx -y public-browser@latest with no arguments.
Chrome profile By default, Public Browser launches Chrome with a fresh temporary profile, with no cookies, logins, or extensions. You can also launch with your own Chrome profile. Chrome refuses remote control on its default data directory, so Public Browser creates a lightweight wrapper directory containing a symlink to the profile folder and launches Chrome on that directory. The wrapper directory is deleted when Public Browser closes Chrome, and wrapper directories left over from crashes are deleted on the next launch; the profile folder itself is never deleted. Bookmarks, history, extensions, and Chrome's own Google login are preserved, so Google sites are logged in. Other sites do not stay logged in on macOS: current Chrome does not load the profile's cookies through the symlink, sites start logged out, and logins made during the session are not saved to the profile. Linux and Windows are untested.
No open debugging port The real profile is driven through --remote-debugging-pipe: CDP runs through a pipe held only by Public Browser, with no TCP port listening, so other programs cannot take over the browser. The tradeoff is that --attach and the Script API escape hatch (page.cdp) are unavailable with a real profile. If Chrome refuses the pipe, Public Browser restarts with a random debugging port (never 9222) and explains this in stderr and the next tool response.
If Chrome is already open Public Browser uses a lockFile checking detects this. If Chrome has remote debugging enabled, attach via CDP. If not, show a clear error requiring Chrome to be closed first. A profile can only be open in one Public Browser at a time: a second instance stops and errors, indicating the PID of the Chrome holding that profile.
Script API (Python) A second usage mode: deterministic browser automation from Python, with no LLM involved. Scripts use the same tool implementations as the MCP server (Shared Core), so every improvement to click, navigate, fill_form, etc. automatically benefits scripts. The MCP server handles AI-driven workflows; the Script API is for repeatable scripts you write yourself. Chrome.connect() automatically starts the Public Browser server as a subprocess via the local public-browser binary or an npx fallback, with no need to manually start Chrome or set a port. Scripts send HTTP requests to the Public Browser server on port 9223. The server runs exactly the same tool handlers as the MCP server—one codebase, one test suite (2,700+ tests), two access paths. The Script API only answers requests carrying its key (Authorization: Bearer <key>), so web pages and programs running under other user accounts cannot drive the browser through it.
Use cases
- Let AI coding assistants such as Claude Code and Cursor drive Chrome via MCP to perform tasks such as web operations, form filling, and data extraction.
- Provide browser-side support for decision models (such as Jev): Jev receives program state and a bounded set of options and returns a typed choice with a calibrated probability; it cannot generate free text, so it will not invent selectors that do not exist. Public Browser provides it with menu-style options.
- Write deterministic, repeatable browser automation scripts in Python, with no LLM.
- Scenarios that require handling complex page structures such as nested cross-origin iframes and shadow DOM.
Limitations
- In real profile mode, --attach and the Script API escape hatch is unavailable.
- On macOS, when using a real profile, login states for other sites are not preserved.
- Profile behavior on Linux and Windows is untested.
- A profile can only be open in one Public Browser instance at a time.
- The project is MIT-licensed, with no paid tier.
- Benchmark data comes from a specific environment (Claude Code 2.1.281, Claude Opus 5, Chrome 153, 2026-09-23/24), and the test pages are self-owned pages.