sandboxed-browser-mcp
A twelve-tool MCP server that lets an agent drive a real Chromium browser and read pages back as short, model-ready text.
browser_navigate/browser_back— load a URL or step back in history, returning the page as text with actionable refs.browser_snapshot— re-read the current viewport as accessible text (or controls-onlyindexmode) without moving.browser_click— click or double-click any element by ref, reporting what changed or which page/tab opened.browser_type— fill inputs, text areas and editable regions, optionally pressing Enter to submit.browser_select— pick a native dropdown option by its visible text (refuses unknown options with the valid list).browser_key— send a single key or combination (Enter, Tab, PageDown, ctrl+a, cmd+shift+t) to the focused element.browser_scroll— move the page or an inner panel by screens, or scroll a specific element into view.browser_find— search the whole page (on screen or not) for elements matching all given words, ranked by distance.browser_get_text— read an element's full text in paginatedmax_charschunks via anoffset.browser_screenshot— capture the viewport or a single element as JPEG when layout, images or canvas matter.browser_upload— attach local files (absolute or~/) to a file input, its label or its chooser button, with a credential/key denylist.Per-call
profile— target a separate signed-in browser session (e.g. a work profile) instead of the default.Safety by design — page text is returned marked as untrusted, and an allowed-hosts fence keeps the browser on listed sites.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@sandboxed-browser-mcp open example.com and take a screenshot"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
You ask your agent to read the docs of a new API, check a page you just deployed, or fill in a form. It needs a browser. A browser holds your logins and can reach anything, and the pages it reads can try to give your agent orders.
sandboxed-browser-mcp is an MCP server with twelve browser tools. They drive Chromium inside a Docker container, answer with the page as short text a model can use, and, when you list allowed hosts, keep the browser on them: the browser's own policy, a guard on every page request and a check after every action each refuse the rest. Everything read from a page comes back marked as untrusted.
Contributing
The most useful help right now:
Try it with your agent and open an issue for anything that surprised you: a page the tools read badly, an action that missed, a host the fence let through.
Add a client: if your MCP client needs a different command or setting, a note in Configuration helps the next person.
Tighten the fence: a way past the allowlist for something it says it covers, with a test that shows it.
Read CONTRIBUTING.md before your first pull request.
More detail: How it works · Configuration · Security · Testing · FAQ · Changelog
Related MCP server: Playwright MCP Server
Quick start
curl -fsSL https://raw.githubusercontent.com/smkamranqadri/sandboxed-browser-mcp/main/install.sh \
| bash -s -- install --client claude --hosts 'docs.example.com,*.example.org'This builds the newest release in ~/.local/share/sandboxed-browser-mcp, starts the browser in Docker, and adds it
to Claude Code as browser (--client codex and --client pi work too; list several with commas). Leave out
--hosts to allow any host. Then open https://127.0.0.1:3101 (user agent, password in the install's
docker/.env) and sign in to the sites you want the agent to use, or leave it signed out.
Requirements: Linux, git, Node 22.4 or later, Docker with Compose. macOS and Windows are untested. To set it up by hand instead, see Configuration.
What you get
A real Chromium, in a container. It keeps its own profile, so the agent browses with the sessions you signed in to, and you can watch it, or take over, in a web page at
https://127.0.0.1:3101.Answers sized for a model. A page is its viewport as text, one line per element with a ref to act on. A click or a typed field answers with what changed on screen, not the whole page again.
Twelve tools:
browser_navigate,browser_back,browser_snapshot,browser_click,browser_type,browser_select,browser_key,browser_scroll,browser_find,browser_get_text,browser_screenshot,browser_upload.File upload from your machine:
browser_uploadgives a page's file input files from under your home folder, through the input, its label or the button that opens its chooser, with no file dialog and no folder shared with the container.Several browsers, if you want them.
install.sh profile add workstarts a separate browser with its own logins and its own allowed hosts; the agent names the profile per call, and a client entry can be limited to some of them.A fence, when you want one. List the hosts the agent may use, and three layers each refuse the rest: the browser's own policy, a guard on every page request, and a check of where every action ended up.
Page text marked as untrusted, every time, with a warning line when it looks like an attempt to steer the agent.
One command to install, check for updates, update and uninstall.
Supported agents
Agent | Added with | Notes |
Claude Code |
| in every project |
Codex |
| asks before each tool call; may prefer its own browser (below) |
pi |
| lists the twelve tools as they are |
The install script runs these for you with --client. Any other MCP client works too: it runs
node <install dir>/dist/server.js over stdio. Each was checked with one real session; see
Testing.
Codex has a browser of its own, and its model may reach for that one instead: name this one in the prompt ("use the
browser MCP server") when it matters. To let its calls run without asking, add to ~/.codex/config.toml:
[mcp_servers.browser]
default_tools_approval_mode = "approve"Everyday use
Ask for what you want; the agent picks the tools:
Open docs.example.com and find how to rotate an API key.
Check the pricing page on our staging site and tell me if the new plan shows.
Fill in the signup form on example.org with these details, but stop before you submit.
Attach ~/Documents/seed-list.csv to the import form.Watch it work, or take over, at
https://127.0.0.1:3101. An arrow shows where the agent is about to click.Change the allowed hosts in two places: the install's
docker/.env(thendocker compose -f <install dir>/docker/compose.yaml up -d) and the client's entry. See Configuration.install.sh checkandinstall.sh updatekeep you current;install.sh uninstallremoves it, and--purgealso deletes the browser profiles with your sessions.Separate sessions:
install.sh profile add work --hosts 'docs.example.com', then ask for "the work profile". See Configuration; a client that can use two profiles can act in both (see Security).
Privacy and safety
Everything runs on your machine. The browser's ports are bound to
127.0.0.1.Your passwords and cookies stay in the container's profile. The agent gets page text and screenshots, not cookies.
The fence is a filter, not a wall: an allowed page's own images, scripts and requests may reach any host, and the container has ordinary network access. Keep the list tight, and keep accounts you cannot afford to lose out of the profile.
Uploads read files from your machine: only regular files under your home folder, never credential, key, history or browser-profile files (a denylist), and the page then has their bytes and can send them anywhere. Linux only.
Anything on your machine that can reach
127.0.0.1:9322can drive the browser (and the same for each profile's port).
The full threat model, with what is and is not covered: Security.
FAQ
Does the agent see my passwords? No. You sign in by hand in the browser; the agent works in the signed-in pages and gets their text, but the tools do not return cookies or stored passwords. A page itself can still show the agent whatever it shows you.
Why Docker? The browser keeps its own profile, apart from the one you use every day, and you can delete it with one command. The container is not a network sandbox, though; see Security.
Can I use my own Chrome instead? Yes: point BROWSER_CDP_URL at any Chrome with remote debugging on. See
Configuration for the flag it needs and what you give up.
Why does the agent say a page is "not an allowed host" before it has done anything? A fresh browser opens on its new-tab page, which is not on your list. Ask the agent to open an address first.
Is the allowlist a security boundary? No. It keeps a well-meaning agent where you want it and makes a tricked one much less useful, but an allowed page can still talk to other hosts. See Security.
How do I undo it? install.sh uninstall --purge stops the browser, removes the client entries it added and deletes
the install and the browser profile.
Development
git clone https://github.com/smkamranqadri/sandboxed-browser-mcp.git && cd sandboxed-browser-mcp
npm ci
npm run test:unit # no browser needed
./install.sh install --source . --dir /tmp/sbm-dev # install your working copyThe integration tests drive a real Chromium in a separate test stack; see Testing. This
repository also carries its own project memory in kis/.
License
Available Tools
12 toolsbrowser_backBackA
Steps back one page in the tab's history and returns that page as text. When the tab has no earlier page, it answers with an error and stays put.
Inputs: profile.
browser_clickClickA
Clicks, or with double: true double-clicks, the element with the given ref. Reports the changes on screen, or the new page when the tab moved, or the new tab when one opened.
Inputs: ref (required), double, profile.
browser_findFindARead-only
Looks through the whole page, on screen or not, for elements whose name or text holds every given word. Lists up to 15, closest to the view first, each with its ref and its distance from the view, ready to act on.
Inputs: query (required), profile.
browser_get_textGet textARead-only
Returns the complete text of an element by ref (an article, a section, a long paragraph) as plain text, max_chars at a time, with a footer giving the offset of the next part. The way to read long text, instead of scrolling or screenshots.
Inputs: ref (required), offset, profile, max_chars.
browser_keyKeyA
Sends one key or a combination to the element that has the focus: Enter, Escape, Tab, ArrowDown, PageDown, ctrl+a, cmd+shift+t. Reports the changes on screen.
Inputs: key (required), profile.
browser_screenshotScreenshotARead-only
Takes a JPEG picture of the viewport, or of one element by ref. Meant for when layout, images or a canvas matter; for everything else the text tools say more for less.
Inputs: ref, profile.
browser_scrollScrollA
Moves the view down or up by a number of screens (the page, or a panel that scrolls on its own in the middle of the window) and returns the new view, or says the end was already reached. With a ref, scrolls that element into view. To look for something, browser_find is faster.
Inputs: ref, profile, screens, direction.
browser_selectSelectA
Picks an option of a native dropdown by the option's visible text, and reports the changes on screen. An option that is not there is refused at once, with the list of those that are.
Inputs: ref (required), option (required), profile.
browser_snapshotSnapshotARead-only
Returns what is on screen now, as text: one line per element in and near the viewport (role, name, text, [ref], states) and counts of what lies above and below. With mode "index", only the controls. Actions already report their changes, so this is rarely needed right after one.
Inputs: mode, profile.
browser_typeTypeA
Puts text into a field by ref, replacing what it held (inputs, text areas, editable regions); submit: true presses Enter afterwards. Reports the changes on screen. Dropdowns take browser_select instead.
Inputs: ref (required), text (required), submit, profile.
browser_uploadUploadA
Attaches files from this machine to a file input by ref: the input, its label, or the button that opens its file chooser. Use it instead of clicking a file input. Paths are absolute or ~/, inside the server's home; credential, key, history and browser-profile files are refused. Reports each file attached and the changes on screen.
Inputs: ref (required), files (required), profile.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 12 tools
Each tool maps to a distinct browser action, and descriptions actively resolve the few plausible overlaps (browser_navigate vs browser_snapshot vs browser_back; browser_scroll vs browser_find, with explicit guidance that find is faster for searching). Interaction tools are also cleanly separated: browser_type for text fields, browser_select for native dropdowns, browser_key for focused key presses, browser_upload instead of clicking file inputs. An agent can pick the right tool without guessing.
All twelve tools share the browser_ prefix followed by a short snake_case action (navigate, back, snapshot, click, type, select, key, scroll, find, get_text, screenshot, upload). The pattern is predictable and stable, with no camelCase or style mixing. Prefixing also cleanly namespaces the toolset.
Twelve tools is well within the ideal 3-15 range and every tool earns its place: navigation, perception, interaction, and file I/O each get focused coverage without redundancy. Nothing feels padded or missing at the count level.
The surface covers the full agent loop: navigate/back/snapshot for movement, find/get_text/screenshot for reading, click/type/select/key/scroll for acting, and upload for file inputs. Minor gaps remain for hover interactions, drag-and-drop, and explicit tab switching (tabs are mentioned in click's output but no tool manages them), which could block some workflows. These are workarounds-mostly gaps rather than dead ends.
Maintenance
Related MCP Connectors
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Official Browserless MCP server: browser automation, scraping, screenshots and PDFs for AI agents.
Browserless MCP — wraps the Browserless headless-Chromium REST API (browserless.io)
Baizhi Cloud Browser (CapyBrowser): cloud sessions via MCP; page actions use a CDP client.
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables MCP clients to drive a real Chromium browser for automation, including navigation, JavaScript execution, CDP commands, network capture, and multi-tab control.730 PyPIGPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents and clients to control a real Chromium browser through MCP tool calls, including navigation, clicking, typing, JavaScript evaluation, screenshots, and DOM snapshots. Supports multiple isolated sessions over authenticated HTTP with no disk writes.Apache 2.0
- AlicenseAqualityBmaintenanceEnables AI agents to drive a Chromium browser through MCP, with persistent sessions, compact page snapshots, guarded actions, batched operations, and explicit result verification.16MIT
- AlicenseBqualityCmaintenanceEnables an LLM to control a hosted headless Chromium browser over HTTP, navigating pages, clicking, typing, and reading structured accessibility snapshots so any MCP client can perform browser automation without local installation.2310,630,264 npmApache 2.0