2025-12-19 23:57:35 +00:00
---
2026-01-27 03:23:42 +00:00
summary: "Integrated browser control service + action commands"
2025-12-19 23:57:35 +00:00
read_when:
- Adding agent-controlled browser automation
2026-01-30 03:15:10 +01:00
- Debugging why openclaw is interfering with your own Chrome
2025-12-19 23:57:35 +00:00
- Implementing browser settings + lifecycle in the macOS app
2026-01-31 16:04:03 -05:00
title: "Browser (OpenClaw-managed)"
2025-12-19 23:57:35 +00:00
---
2026-01-30 03:15:10 +01:00
# Browser (openclaw-managed)
2025-12-19 23:57:35 +00:00
2026-01-30 03:15:10 +01:00
OpenClaw can run a **dedicated Chrome/Brave/Edge/Chromium profile ** that the agent controls.
2026-01-08 23:06:56 +01:00
It is isolated from your personal browser and is managed through a small local
2026-01-27 03:23:42 +00:00
control service inside the Gateway (loopback only).
2025-12-19 23:57:35 +00:00
2026-01-11 01:24:02 +01:00
Beginner view:
2026-01-31 21:13:13 +09:00
2026-01-11 01:24:02 +01:00
- Think of it as a **separate, agent-only browser ** .
2026-01-30 03:15:10 +01:00
- The `openclaw` profile does **not ** touch your personal browser profile.
2026-01-11 01:24:02 +01:00
- The agent can **open tabs, read pages, click, and type ** in a safe lane.
2026-03-15 23:56:08 -07:00
- The built-in `user` profile attaches to your real signed-in Chrome session via Chrome MCP.
2026-01-11 01:24:02 +01:00
2026-01-08 23:06:56 +01:00
## What you get
2025-12-19 23:57:35 +00:00
2026-01-30 03:15:10 +01:00
- A separate browser profile named **openclaw ** (orange accent by default).
2026-01-08 23:06:56 +01:00
- Deterministic tab control (list/open/focus/close).
- Agent actions (click/type/drag/select), snapshots, screenshots, PDFs.
2026-01-30 03:15:10 +01:00
- Optional multi-profile support (`openclaw` , `work` , `remote` , ...).
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
This browser is **not ** your daily driver. It is a safe, isolated surface for
agent automation and verification.
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
## Quick start
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
``` bash
2026-01-30 03:15:10 +01:00
openclaw browser --browser-profile openclaw status
openclaw browser --browser-profile openclaw start
openclaw browser --browser-profile openclaw open https://example.com
openclaw browser --browser-profile openclaw snapshot
2026-01-08 23:06:56 +01:00
```
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
If you get “Browser disabled”, enable it in config (see below) and restart the
Gateway.
2026-01-04 03:32:40 +00:00
2026-03-29 22:19:22 +09:00
If `openclaw browser` is missing entirely, or the agent says the browser tool
is unavailable, jump to [Missing browser command or tool ](/tools/browser#missing-browser-command-or-tool ).
2026-03-26 22:18:41 +00:00
## Plugin control
The default `browser` tool is now a bundled plugin that ships enabled by
default. That means you can disable or replace it without removing the rest of
OpenClaw's plugin system:
``` json5
{
plugins: {
entries: {
browser: {
enabled: false,
},
},
},
}
```
Disable the bundled plugin before installing another plugin that provides the
same `browser` tool name. The default browser experience needs both:
- `plugins.entries.browser.enabled` not disabled
- `browser.enabled=true`
If you turn off only the plugin, the bundled browser CLI (`openclaw browser` ),
gateway method (`browser.request` ), agent tool, and default browser control
service all disappear together. Your `browser.*` config stays intact for a
replacement plugin to reuse.
The bundled browser plugin also owns the browser runtime implementation now.
Core keeps only shared Plugin SDK helpers plus compatibility re-exports for
2026-03-29 22:19:22 +09:00
older internal import paths. In practice, removing or replacing the browser
plugin package removes the browser feature set instead of leaving a second
core-owned runtime behind.
2026-03-26 22:18:41 +00:00
Browser config changes still require a Gateway restart so the bundled plugin
can re-register its browser service with the new settings.
2026-03-29 22:19:22 +09:00
## Missing browser command or tool
If `openclaw browser` suddenly becomes an unknown command after an upgrade, or
the agent reports that the browser tool is missing, the most common cause is a
restrictive `plugins.allow` list that does not include `browser` .
Example broken config:
``` json5
{
plugins: {
allow: ["telegram"],
},
}
```
Fix it by adding `browser` to the plugin allowlist:
``` json5
{
plugins: {
allow: ["telegram", "browser"],
},
}
```
Important notes:
- `browser.enabled=true` is not enough by itself when `plugins.allow` is set.
- `plugins.entries.browser.enabled=true` is also not enough by itself when `plugins.allow` is set.
- `tools.alsoAllow: ["browser"]` does **not ** load the bundled browser plugin. It only adjusts tool policy after the plugin is already loaded.
- If you do not need a restrictive plugin allowlist, removing `plugins.allow` also restores the default bundled browser behavior.
Typical symptoms:
- `openclaw browser` is an unknown command.
- `browser.request` is missing.
- The agent reports the browser tool as unavailable or missing.
2026-03-15 23:56:08 -07:00
## Profiles: `openclaw` vs `user`
2026-01-16 06:57:20 +00:00
2026-01-30 03:15:10 +01:00
- `openclaw` : managed, isolated browser (no extension required).
2026-03-14 04:15:25 +00:00
- `user` : built-in Chrome MCP attach profile for your **real signed-in Chrome **
session.
2026-01-16 06:57:20 +00:00
2026-03-14 03:46:34 +00:00
For agent browser tool calls:
- Default: use the isolated `openclaw` browser.
2026-03-14 04:15:25 +00:00
- Prefer `profile="user"` when existing logged-in sessions matter and the user
is at the computer to click/approve any attach prompt.
- `profile` is the explicit override when you want a specific browser mode.
2026-03-14 03:46:34 +00:00
2026-01-30 03:15:10 +01:00
Set `browser.defaultProfile: "openclaw"` if you want managed mode by default.
2026-01-16 06:57:20 +00:00
2026-01-08 23:06:56 +01:00
## Configuration
2026-01-04 03:32:40 +00:00
2026-01-30 03:15:10 +01:00
Browser settings live in `~/.openclaw/openclaw.json` .
2026-01-04 03:32:40 +00:00
2026-01-08 23:06:56 +01:00
``` json5
2026-01-04 03:32:40 +00:00
{
2026-01-08 23:06:56 +01:00
browser: {
2026-01-31 21:13:13 +09:00
enabled: true, // default: true
2026-02-24 01:51:44 +00:00
ssrfPolicy: {
dangerouslyAllowPrivateNetwork: true, // default trusted-network mode
// allowPrivateNetwork: true, // legacy alias
// hostnameAllowlist: ["*.example.com", "example.com"],
// allowedHostnames: ["localhost"],
},
2026-01-27 03:23:42 +00:00
// cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override
2026-01-31 21:13:13 +09:00
remoteCdpTimeoutMs: 1500, // remote CDP HTTP timeout (ms)
2026-01-16 09:01:25 +00:00
remoteCdpHandshakeTimeoutMs: 3000, // remote CDP WebSocket handshake timeout (ms)
2026-03-14 03:46:34 +00:00
defaultProfile: "openclaw",
2026-01-08 23:06:56 +01:00
color: "#FF4500",
headless: false,
noSandbox: false,
attachOnly: false,
2026-01-16 03:24:53 +00:00
executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
2026-01-08 23:06:56 +01:00
profiles: {
2026-01-30 03:15:10 +01:00
openclaw: { cdpPort: 18800, color: "#FF4500" },
2026-01-08 23:06:56 +01:00
work: { cdpPort: 18801, color: "#0066CC" },
2026-03-14 04:15:25 +00:00
user: {
2026-03-13 20:08:42 +00:00
driver: "existing-session",
attachOnly: true,
color: "#00AA00",
},
2026-03-16 14:21:22 +01:00
brave: {
driver: "existing-session",
attachOnly: true,
userDataDir: "~/Library/Application Support/BraveSoftware/Brave-Browser",
color: "#FB542B",
},
2026-01-31 21:13:13 +09:00
remote: { cdpUrl: "http://10.0.0.42:9222", color: "#00AA00" },
},
},
2026-01-04 03:32:40 +00:00
}
```
2026-01-08 23:06:56 +01:00
Notes:
2026-01-31 21:13:13 +09:00
2026-01-27 03:23:42 +00:00
- The browser control service binds to loopback on a port derived from `gateway.port`
2026-03-15 23:56:08 -07:00
(default: `18791` , which is gateway + 2).
2026-01-30 03:15:10 +01:00
- If you override the Gateway port (`gateway.port` or `OPENCLAW_GATEWAY_PORT` ),
2026-01-27 03:23:42 +00:00
the derived browser ports shift to stay in the same “family”.
2026-03-15 23:56:08 -07:00
- `cdpUrl` defaults to the managed local CDP port when unset.
2026-01-16 09:01:25 +00:00
- `remoteCdpTimeoutMs` applies to remote (non-loopback) CDP reachability checks.
- `remoteCdpHandshakeTimeoutMs` applies to remote CDP WebSocket reachability checks.
2026-02-24 01:51:44 +00:00
- Browser navigation/open-tab is SSRF-guarded before navigation and best-effort re-checked on final `http(s)` URL after navigation.
2026-03-15 08:22:48 -07:00
- In strict SSRF mode, remote CDP endpoint discovery/probes (`cdpUrl` , including `/json/version` lookups) are checked too.
2026-02-24 01:51:44 +00:00
- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` defaults to `true` (trusted-network model). Set it to `false` for strict public-only browsing.
- `browser.ssrfPolicy.allowPrivateNetwork` remains supported as a legacy alias for compatibility.
2026-01-16 03:24:53 +00:00
- `attachOnly: true` means “never launch a local browser; only attach if it is already running.”
2026-01-11 01:24:02 +01:00
- `color` + per-profile `color` tint the browser UI so you can see which profile is active.
2026-03-15 23:56:08 -07:00
- Default profile is `openclaw` (OpenClaw-managed standalone browser). Use `defaultProfile: "user"` to opt into the signed-in user browser.
2026-01-16 06:57:20 +00:00
- Auto-detect order: system default browser if Chromium-based; otherwise Chrome → Brave → Edge → Chromium → Chrome Canary.
2026-01-30 03:15:10 +01:00
- Local `openclaw` profiles auto-assign `cdpPort` /`cdpUrl` — set those only for remote CDP.
2026-03-13 20:08:42 +00:00
- `driver: "existing-session"` uses Chrome DevTools MCP instead of raw CDP. Do
not set `cdpUrl` for that driver.
2026-03-16 14:21:22 +01:00
- Set `browser.profiles.<name>.userDataDir` when an existing-session profile
should attach to a non-default Chromium user profile such as Brave or Edge.
2026-01-16 03:24:53 +00:00
## Use Brave (or another Chromium-based browser)
2026-01-16 06:57:20 +00:00
If your **system default ** browser is Chromium-based (Chrome/Brave/Edge/etc),
2026-01-30 03:15:10 +01:00
OpenClaw uses it automatically. Set `browser.executablePath` to override
2026-01-16 06:57:20 +00:00
auto-detection:
CLI example:
``` bash
2026-01-30 03:15:10 +01:00
openclaw config set browser.executablePath "/usr/bin/google-chrome"
2026-01-16 06:57:20 +00:00
```
2026-01-16 03:24:53 +00:00
``` json5
// macOS
{
browser: {
executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
}
}
// Windows
{
browser: {
executablePath: "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe"
}
}
// Linux
{
browser: {
executablePath: "/usr/bin/brave-browser"
}
}
```
2026-01-04 03:32:40 +00:00
2026-01-08 23:06:56 +01:00
## Local vs remote control
2026-01-04 03:32:40 +00:00
2026-01-27 03:23:42 +00:00
- **Local control (default):** the Gateway starts the loopback control service and can launch a local browser.
- **Remote control (node host):** run a node host on the machine that has the browser; the Gateway proxies browser actions to it.
2026-01-08 23:06:56 +01:00
- **Remote CDP:** set `browser.profiles.<name>.cdpUrl` (or `browser.cdpUrl` ) to
2026-01-30 03:15:10 +01:00
attach to a remote Chromium-based browser. In this case, OpenClaw will not launch a local browser.
2026-01-04 03:32:40 +00:00
2026-04-04 12:02:10 +01:00
Stopping behavior differs by profile mode:
- local managed profiles: `openclaw browser stop` stops the browser process that
OpenClaw launched
- attach-only and remote CDP profiles: `openclaw browser stop` closes the active
control session and releases Playwright/CDP emulation overrides (viewport,
color scheme, locale, timezone, offline mode, and similar state), even
though no browser process was launched by OpenClaw
2026-01-16 08:31:51 +00:00
Remote CDP URLs can include auth:
2026-01-31 21:13:13 +09:00
2026-01-16 08:31:51 +00:00
- Query tokens (e.g., `https://provider.example?token=<token>` )
- HTTP Basic auth (e.g., `https://user:pass@provider.example` )
2026-01-30 03:15:10 +01:00
OpenClaw preserves the auth when calling `/json/*` endpoints and when connecting
2026-01-16 08:31:51 +00:00
to the CDP WebSocket. Prefer environment variables or secrets managers for
tokens instead of committing them to config files.
2026-01-27 03:23:42 +00:00
## Node browser proxy (zero-config default)
2026-01-24 04:19:43 +00:00
2026-01-30 03:15:10 +01:00
If you run a **node host ** on the machine that has your browser, OpenClaw can
2026-01-27 03:23:42 +00:00
auto-route browser tool calls to that node without any extra browser config.
This is the default path for remote gateways.
2026-01-24 04:19:43 +00:00
Notes:
2026-01-31 21:13:13 +09:00
2026-01-24 04:19:43 +00:00
- The node host exposes its local browser control server via a **proxy command ** .
- Profiles come from the node’ s own `browser.profiles` config (same as local).
2026-03-23 00:55:23 -07:00
- `nodeHost.browserProxy.allowProfiles` is optional. Leave it empty for the legacy/default behavior: all configured profiles remain reachable through the proxy, including profile create/delete routes.
- If you set `nodeHost.browserProxy.allowProfiles` , OpenClaw treats it as a least-privilege boundary: only allowlisted profiles can be targeted, and persistent profile create/delete routes are blocked on the proxy surface.
2026-01-24 04:19:43 +00:00
- Disable if you don’ t want it:
- On the node: `nodeHost.browserProxy.enabled=false`
- On the gateway: `gateway.nodes.browser.mode="off"`
2026-01-27 03:23:42 +00:00
## Browserless (hosted remote CDP)
2026-01-16 09:05:19 +00:00
[Browserless ](https://browserless.io ) is a hosted Chromium service that exposes
2026-03-27 17:11:57 +01:00
CDP connection URLs over HTTPS and WebSocket. OpenClaw can use either form, but
for a remote browser profile the simplest option is the direct WebSocket URL
from Browserless' connection docs.
2026-01-16 09:05:19 +00:00
Example:
2026-01-31 21:13:13 +09:00
2026-01-16 09:05:19 +00:00
``` json5
{
browser: {
enabled: true,
defaultProfile: "browserless",
remoteCdpTimeoutMs: 2000,
remoteCdpHandshakeTimeoutMs: 4000,
profiles: {
browserless: {
2026-03-27 17:11:57 +01:00
cdpUrl: "wss://production-sfo.browserless.io?token=<BROWSERLESS_API_KEY>",
2026-01-31 21:13:13 +09:00
color: "#00AA00",
},
},
},
2026-01-16 09:05:19 +00:00
}
```
Notes:
2026-01-31 21:13:13 +09:00
2026-01-16 09:05:19 +00:00
- Replace `<BROWSERLESS_API_KEY>` with your real Browserless token.
- Choose the region endpoint that matches your Browserless account (see their docs).
2026-03-27 17:11:57 +01:00
- If Browserless gives you an HTTPS base URL, you can either convert it to
`wss://` for a direct CDP connection or keep the HTTPS URL and let OpenClaw
discover `/json/version` .
2026-01-16 09:05:19 +00:00
2026-03-02 01:08:15 -08:00
## Direct WebSocket CDP providers
2026-03-01 16:08:01 -08:00
2026-03-02 01:08:15 -08:00
Some hosted browser services expose a **direct WebSocket ** endpoint rather than
the standard HTTP-based CDP discovery (`/json/version` ). OpenClaw supports both:
2026-03-01 16:08:01 -08:00
2026-03-27 17:11:57 +01:00
- **HTTP(S) endpoints** — OpenClaw calls `/json/version` to discover the
WebSocket debugger URL, then connects.
2026-03-02 01:08:15 -08:00
- **WebSocket endpoints** (`ws://` / `wss://` ) — OpenClaw connects directly,
skipping `/json/version` . Use this for services like
2026-03-27 17:11:57 +01:00
[Browserless ](https://browserless.io ),
[Browserbase ](https://www.browserbase.com ), or any provider that hands you a
2026-03-02 01:08:15 -08:00
WebSocket URL.
### Browserbase
[Browserbase ](https://www.browserbase.com ) is a cloud platform for running
headless browsers with built-in CAPTCHA solving, stealth mode, and residential
proxies.
2026-03-01 16:08:01 -08:00
``` json5
{
browser: {
enabled: true,
defaultProfile: "browserbase",
remoteCdpTimeoutMs: 3000,
remoteCdpHandshakeTimeoutMs: 5000,
profiles: {
browserbase: {
2026-03-01 16:36:08 -08:00
cdpUrl: "wss://connect.browserbase.com?apiKey=<BROWSERBASE_API_KEY>",
2026-03-01 16:08:01 -08:00
color: "#F97316",
},
},
},
}
```
2026-03-01 16:51:50 -08:00
Notes:
2026-03-01 16:08:01 -08:00
2026-03-01 16:51:50 -08:00
- [Sign up ](https://www.browserbase.com/sign-up ) and copy your **API Key **
from the [Overview dashboard ](https://www.browserbase.com/overview ).
2026-03-01 16:36:08 -08:00
- Replace `<BROWSERBASE_API_KEY>` with your real Browserbase API key.
2026-03-02 00:49:55 -08:00
- Browserbase auto-creates a browser session on WebSocket connect, so no
manual session creation step is needed.
2026-03-01 16:52:49 -08:00
- The free tier allows one concurrent session and one browser hour per month.
See [pricing ](https://www.browserbase.com/pricing ) for paid plan limits.
2026-03-01 16:08:01 -08:00
- See the [Browserbase docs ](https://docs.browserbase.com ) for full API
reference, SDK guides, and integration examples.
2026-01-15 04:50:11 +00:00
## Security
Key ideas:
2026-01-31 21:13:13 +09:00
2026-01-27 03:23:42 +00:00
- Browser control is loopback-only; access flows through the Gateway’ s auth or node pairing.
2026-04-04 14:04:24 +01:00
- The standalone loopback browser HTTP API uses **shared-secret auth only ** :
gateway token bearer auth, `x-openclaw-password` , or HTTP Basic auth with the
configured gateway password.
- Tailscale Serve identity headers and `gateway.auth.mode: "trusted-proxy"` do
**not ** authenticate this standalone loopback browser API.
- If browser control is enabled and no shared-secret auth is configured, OpenClaw
auto-generates `gateway.auth.token` on startup and persists it to config.
- OpenClaw does **not ** auto-generate that token when `gateway.auth.mode` is
already `password` , `none` , or `trusted-proxy` .
2026-01-27 03:23:42 +00:00
- Keep the Gateway and any node hosts on a private network (Tailscale); avoid public exposure.
- Treat remote CDP URLs/tokens as secrets; prefer env vars or a secrets manager.
2026-01-15 04:50:11 +00:00
2026-01-27 03:23:42 +00:00
Remote CDP tips:
2026-01-31 21:13:13 +09:00
2026-03-02 01:08:15 -08:00
- Prefer encrypted endpoints (HTTPS or WSS) and short-lived tokens where possible.
2026-01-27 03:23:42 +00:00
- Avoid embedding long-lived tokens directly in config files.
2026-01-15 04:50:11 +00:00
2026-01-08 23:06:56 +01:00
## Profiles (multi-browser)
2026-01-04 03:32:40 +00:00
2026-01-30 03:15:10 +01:00
OpenClaw supports multiple named profiles (routing configs). Profiles can be:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- **openclaw-managed**: a dedicated Chromium-based browser instance with its own user data directory + CDP port
2026-01-16 03:24:53 +00:00
- **remote**: an explicit CDP URL (Chromium-based browser running elsewhere)
2026-03-13 20:08:42 +00:00
- **existing session**: your existing Chrome profile via Chrome DevTools MCP auto-connect
2026-01-04 03:32:40 +00:00
2026-01-08 23:06:56 +01:00
Defaults:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- The `openclaw` profile is auto-created if missing.
2026-03-15 23:56:08 -07:00
- The `user` profile is built-in for Chrome MCP existing-session attach.
- Existing-session profiles are opt-in beyond `user` ; create them with `--driver existing-session` .
2026-01-08 23:06:56 +01:00
- Local CDP ports allocate from **18800– 18899 ** by default.
- Deleting a profile moves its local data directory to Trash.
2026-01-06 11:04:33 -07:00
2026-01-08 23:06:56 +01:00
All control endpoints accept `?profile=<name>` ; the CLI uses `--browser-profile` .
2026-01-06 11:04:33 -07:00
2026-03-16 14:21:22 +01:00
## Existing-session via Chrome DevTools MCP
2026-03-13 20:08:42 +00:00
2026-03-16 14:21:22 +01:00
OpenClaw can also attach to a running Chromium-based browser profile through the
official Chrome DevTools MCP server. This reuses the tabs and login state
already open in that browser profile.
2026-03-13 20:08:42 +00:00
Official background and setup references:
- [Chrome for Developers: Use Chrome DevTools MCP with your browser session ](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session )
- [Chrome DevTools MCP README ](https://github.com/ChromeDevTools/chrome-devtools-mcp )
2026-03-14 04:15:25 +00:00
Built-in profile:
2026-03-13 20:08:42 +00:00
2026-03-14 04:15:25 +00:00
- `user`
Optional: create your own custom existing-session profile if you want a
2026-03-16 14:21:22 +01:00
different name, color, or browser data directory.
Default behavior:
- The built-in `user` profile uses Chrome MCP auto-connect, which targets the
default local Google Chrome profile.
Use `userDataDir` for Brave, Edge, Chromium, or a non-default Chrome profile:
``` json5
{
browser: {
profiles: {
brave: {
driver: "existing-session",
attachOnly: true,
userDataDir: "~/Library/Application Support/BraveSoftware/Brave-Browser",
color: "#FB542B",
},
},
},
}
```
Then in the matching browser:
1. Open that browser's inspect page for remote debugging.
2. Enable remote debugging.
3. Keep the browser running and approve the connection prompt when OpenClaw attaches.
2026-03-13 20:08:42 +00:00
2026-03-16 14:21:22 +01:00
Common inspect pages:
2026-03-13 20:08:42 +00:00
2026-03-16 14:21:22 +01:00
- Chrome: `chrome://inspect/#remote-debugging`
- Brave: `brave://inspect/#remote-debugging`
- Edge: `edge://inspect/#remote-debugging`
2026-03-13 20:08:42 +00:00
Live attach smoke test:
``` bash
2026-03-14 04:15:25 +00:00
openclaw browser --browser-profile user start
openclaw browser --browser-profile user status
openclaw browser --browser-profile user tabs
openclaw browser --browser-profile user snapshot --format ai
2026-03-13 20:08:42 +00:00
```
What success looks like:
- `status` shows `driver: existing-session`
2026-03-14 03:46:34 +00:00
- `status` shows `transport: chrome-mcp`
2026-03-13 20:08:42 +00:00
- `status` shows `running: true`
2026-03-16 14:21:22 +01:00
- `tabs` lists your already-open browser tabs
2026-03-13 20:08:42 +00:00
- `snapshot` returns refs from the selected live tab
2026-03-14 15:54:22 -07:00
What to check if attach does not work:
2026-03-13 20:08:42 +00:00
2026-03-16 14:21:22 +01:00
- the target Chromium-based browser is version `144+`
- remote debugging is enabled in that browser's inspect page
- the browser showed and you accepted the attach consent prompt
2026-03-15 23:56:08 -07:00
- `openclaw doctor` migrates old extension-based browser config and checks that
2026-03-16 14:21:22 +01:00
Chrome is installed locally for default auto-connect profiles, but it cannot
enable browser-side remote debugging for you
2026-03-14 03:46:34 +00:00
Agent use:
2026-03-14 04:15:25 +00:00
- Use `profile="user"` when you need the user’ s logged-in browser state.
- If you use a custom existing-session profile, pass that explicit profile name.
2026-03-14 15:54:22 -07:00
- Only choose this mode when the user is at the computer to approve the attach
prompt.
- the Gateway or node host can spawn `npx chrome-devtools-mcp@latest --autoConnect`
2026-03-13 20:08:42 +00:00
Notes:
- This path is higher-risk than the isolated `openclaw` profile because it can
act inside your signed-in browser session.
2026-03-16 14:21:22 +01:00
- OpenClaw does not launch the browser for this driver; it attaches to an
existing session only.
- OpenClaw uses the official Chrome DevTools MCP `--autoConnect` flow here. If
`userDataDir` is set, OpenClaw passes it through to target that explicit
Chromium user data directory.
2026-03-13 23:56:39 +00:00
- Existing-session screenshots support page captures and `--ref` element
captures from snapshots, but not CSS `--element` selectors.
2026-04-04 11:58:40 +01:00
- Existing-session page screenshots work without Playwright through Chrome MCP.
Ref-based element screenshots (`--ref` ) also work there, but `--full-page`
cannot be combined with `--ref` or `--element` .
2026-04-04 11:51:01 +01:00
- Existing-session actions are still more limited than the managed browser
path:
- `click` , `type` , `hover` , `scrollIntoView` , `drag` , and `select` require
snapshot refs instead of CSS selectors
- `click` is left-button only (no button overrides or modifiers)
- `type` does not support `slowly=true` ; use `fill` or `press`
- `press` does not support `delayMs`
2026-04-04 20:26:30 +01:00
- `hover` , `scrollIntoView` , `drag` , `select` , `fill` , and `evaluate` do not
support per-call timeout overrides
2026-04-04 11:51:01 +01:00
- `select` currently supports a single value only
2026-03-13 23:56:39 +00:00
- Existing-session `wait --url` supports exact, substring, and glob patterns
like other browser drivers. `wait --load networkidle` is not supported yet.
2026-04-04 20:26:30 +01:00
- Existing-session upload hooks require `ref` or `inputRef` , support one file
at a time, and do not support CSS `element` targeting.
- Existing-session dialog hooks do not support timeout overrides.
2026-04-04 11:51:01 +01:00
- Some features still require the managed browser path, including batch
actions, PDF export, download interception, and `responsebody` .
2026-03-15 23:56:08 -07:00
- Existing-session is host-local. If Chrome lives on a different machine or a
different network namespace, use remote CDP or a node host instead.
2026-01-15 04:50:11 +00:00
2026-01-08 23:06:56 +01:00
## Isolation guarantees
2026-01-16 03:24:53 +00:00
- **Dedicated user data dir**: never touches your personal browser profile.
2026-01-08 23:06:56 +01:00
- **Dedicated ports**: avoids `9222` to prevent collisions with dev workflows.
- **Deterministic tab control**: target tabs by `targetId` , not “last tab”.
## Browser selection
2026-01-06 11:04:33 -07:00
2026-01-30 03:15:10 +01:00
When launching locally, OpenClaw picks the first available:
2026-01-31 21:13:13 +09:00
2026-01-16 03:24:53 +00:00
1. Chrome
2. Brave
3. Edge
4. Chromium
5. Chrome Canary
2026-01-06 11:04:33 -07:00
2026-01-08 23:06:56 +01:00
You can override with `browser.executablePath` .
2026-01-04 03:32:40 +00:00
2026-01-08 23:06:56 +01:00
Platforms:
2026-01-31 21:13:13 +09:00
2026-01-08 23:06:56 +01:00
- macOS: checks `/Applications` and `~/Applications` .
2026-01-16 03:24:53 +00:00
- Linux: looks for `google-chrome` , `brave` , `microsoft-edge` , `chromium` , etc.
2026-01-08 23:06:56 +01:00
- Windows: checks common install locations.
2026-01-04 03:32:40 +00:00
2026-01-08 23:06:56 +01:00
## Control API (optional)
2026-01-04 03:32:40 +00:00
2026-01-27 03:23:42 +00:00
For local integrations only, the Gateway exposes a small loopback HTTP API:
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
- Status/start/stop: `GET /` , `POST /start` , `POST /stop`
- Tabs: `GET /tabs` , `POST /tabs/open` , `POST /tabs/focus` , `DELETE /tabs/:targetId`
- Snapshot/screenshot: `GET /snapshot` , `POST /screenshot`
- Actions: `POST /navigate` , `POST /act`
- Hooks: `POST /hooks/file-chooser` , `POST /hooks/dialog`
2026-01-12 19:40:59 +00:00
- Downloads: `POST /download` , `POST /wait/download`
2026-01-08 23:06:56 +01:00
- Debugging: `GET /console` , `POST /pdf`
2026-01-12 17:32:02 +00:00
- Debugging: `GET /errors` , `GET /requests` , `POST /trace/start` , `POST /trace/stop` , `POST /highlight`
2026-01-12 19:40:59 +00:00
- Network: `POST /response/body`
2026-01-12 17:32:02 +00:00
- State: `GET /cookies` , `POST /cookies/set` , `POST /cookies/clear`
- State: `GET /storage/:kind` , `POST /storage/:kind/set` , `POST /storage/:kind/clear`
- Settings: `POST /set/offline` , `POST /set/headers` , `POST /set/credentials` , `POST /set/geolocation` , `POST /set/media` , `POST /set/timezone` , `POST /set/locale` , `POST /set/device`
2025-12-19 23:57:35 +00:00
2026-01-08 23:06:56 +01:00
All endpoints accept `?profile=<name>` .
2025-12-19 23:57:35 +00:00
2026-04-04 14:04:24 +01:00
If shared-secret gateway auth is configured, browser HTTP routes require auth too:
2026-02-13 02:01:57 +01:00
- `Authorization: Bearer <gateway token>`
- `x-openclaw-password: <gateway password>` or HTTP Basic auth with that password
2026-04-04 14:04:24 +01:00
Notes:
- This standalone loopback browser API does **not ** consume trusted-proxy or
Tailscale Serve identity headers.
- If `gateway.auth.mode` is `none` or `trusted-proxy` , these loopback browser
routes do not inherit those identity-bearing modes; keep them loopback-only.
2026-01-08 23:06:56 +01:00
### Playwright requirement
2025-12-19 23:57:35 +00:00
2026-04-04 11:58:40 +01:00
Some features (navigate/act/AI snapshot/role snapshot, element screenshots,
PDF) require Playwright. If Playwright isn’ t installed, those endpoints return
a clear 501 error.
What still works without Playwright:
- ARIA snapshots
- Page screenshots for the managed `openclaw` browser when a per-tab CDP
WebSocket is available
- Page screenshots for `existing-session` / Chrome MCP profiles
- `existing-session` ref-based screenshots (`--ref` ) from snapshot output
What still needs Playwright:
- `navigate`
- `act`
- AI snapshots / role snapshots
- CSS-selector element screenshots (`--element` )
- full browser PDF export
Element screenshots also reject `--full-page` ; the route returns `fullPage is
not supported for element screenshots` .
2025-12-20 00:53:45 +00:00
2026-01-16 06:57:20 +00:00
If you see `Playwright is not available in this gateway build` , install the full
Playwright package (not `playwright-core` ) and restart the gateway, or reinstall
2026-01-30 03:15:10 +01:00
OpenClaw with browser support.
2026-01-16 06:57:20 +00:00
2026-02-02 02:07:00 -08:00
#### Docker Playwright install
If your Gateway runs in Docker, avoid `npx playwright` (npm override conflicts).
Use the bundled CLI instead:
``` bash
docker compose run --rm openclaw-cli \
node /app/node_modules/playwright-core/cli.js install chromium
```
To persist browser downloads, set `PLAYWRIGHT_BROWSERS_PATH` (for example,
`/home/node/.cache/ms-playwright` ) and make sure `/home/node` is persisted via
`OPENCLAW_HOME_VOLUME` or a bind mount. See [Docker ](/install/docker ).
2026-01-11 01:24:02 +01:00
## How it works (internal)
High-level flow:
2026-01-31 21:13:13 +09:00
2026-01-11 01:24:02 +01:00
- A small **control server ** accepts HTTP requests.
2026-01-16 03:24:53 +00:00
- It connects to Chromium-based browsers (Chrome/Brave/Edge/Chromium) via **CDP ** .
2026-01-11 01:24:02 +01:00
- For advanced actions (click/type/snapshot/PDF), it uses **Playwright ** on top
of CDP.
- When Playwright is missing, only non-Playwright operations are available.
This design keeps the agent on a stable, deterministic interface while letting
you swap local/remote browsers and profiles.
2026-01-08 23:06:56 +01:00
## CLI quick reference
All commands accept `--browser-profile <name>` to target a specific profile.
2026-01-12 18:42:23 +00:00
All commands also accept `--json` for machine-readable output (stable payloads).
2026-01-04 03:32:40 +00:00
2025-12-20 00:53:45 +00:00
Basics:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `openclaw browser status`
- `openclaw browser start`
- `openclaw browser stop`
- `openclaw browser tabs`
- `openclaw browser tab`
- `openclaw browser tab new`
- `openclaw browser tab select 2`
- `openclaw browser tab close 2`
- `openclaw browser open https://example.com`
- `openclaw browser focus abcd1234`
- `openclaw browser close abcd1234`
2025-12-20 00:53:45 +00:00
Inspection:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `openclaw browser screenshot`
- `openclaw browser screenshot --full-page`
- `openclaw browser screenshot --ref 12`
- `openclaw browser screenshot --ref e12`
- `openclaw browser snapshot`
- `openclaw browser snapshot --format aria --limit 200`
- `openclaw browser snapshot --interactive --compact --depth 6`
- `openclaw browser snapshot --efficient`
- `openclaw browser snapshot --labels`
- `openclaw browser snapshot --selector "#main" --interactive`
- `openclaw browser snapshot --frame "iframe#main" --interactive`
- `openclaw browser console --level error`
2026-04-04 12:02:10 +01:00
Lifecycle note:
- For attach-only and remote CDP profiles, `openclaw browser stop` is still the
right cleanup command after tests. It closes the active control session and
clears temporary emulation overrides instead of killing the underlying
browser.
2026-01-30 03:15:10 +01:00
- `openclaw browser errors --clear`
- `openclaw browser requests --filter api --clear`
- `openclaw browser pdf`
- `openclaw browser responsebody "**/api" --max-chars 5000`
2025-12-20 00:53:45 +00:00
Actions:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `openclaw browser navigate https://example.com`
- `openclaw browser resize 1280 720`
- `openclaw browser click 12 --double`
- `openclaw browser click e12 --double`
- `openclaw browser type 23 "hello" --submit`
- `openclaw browser press Enter`
- `openclaw browser hover 44`
- `openclaw browser scrollintoview e12`
- `openclaw browser drag 10 11`
- `openclaw browser select 9 OptionA OptionB`
2026-02-13 19:24:33 +00:00
- `openclaw browser download e12 report.pdf`
- `openclaw browser waitfordownload report.pdf`
2026-02-14 14:42:08 +01:00
- `openclaw browser upload /tmp/openclaw/uploads/file.pdf`
2026-01-30 03:15:10 +01:00
- `openclaw browser fill --fields '[{"ref":"1","type":"text","value":"Ada"}]'`
- `openclaw browser dialog --accept`
- `openclaw browser wait --text "Done"`
- `openclaw browser wait "#main" --url "**/dash" --load networkidle --fn "window.ready===true"`
- `openclaw browser evaluate --fn '(el) => el.textContent' --ref 7`
- `openclaw browser highlight e12`
- `openclaw browser trace start`
- `openclaw browser trace stop`
2026-01-12 17:32:02 +00:00
State:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `openclaw browser cookies`
- `openclaw browser cookies set session abc123 --url "https://example.com"`
- `openclaw browser cookies clear`
- `openclaw browser storage local get`
- `openclaw browser storage local set theme dark`
- `openclaw browser storage session clear`
- `openclaw browser set offline on`
2026-02-17 20:57:09 -05:00
- `openclaw browser set headers --headers-json '{"X-Debug":"1"}'`
2026-01-30 03:15:10 +01:00
- `openclaw browser set credentials user pass`
- `openclaw browser set credentials --clear`
- `openclaw browser set geo 37.7749 -122.4194 --origin "https://example.com"`
- `openclaw browser set geo --clear`
- `openclaw browser set media dark`
- `openclaw browser set timezone America/New_York`
- `openclaw browser set locale en-US`
- `openclaw browser set device "iPhone 14"`
2025-12-19 23:57:35 +00:00
Notes:
2026-01-31 21:13:13 +09:00
2026-01-08 23:06:56 +01:00
- `upload` and `dialog` are **arming ** calls; run them before the click/press
that triggers the chooser/dialog.
2026-02-13 19:24:33 +00:00
- Download and trace output paths are constrained to OpenClaw temp roots:
- traces: `/tmp/openclaw` (fallback: `${os.tmpdir()}/openclaw` )
- downloads: `/tmp/openclaw/downloads` (fallback: `${os.tmpdir()}/openclaw/downloads` )
2026-02-14 14:42:08 +01:00
- Upload paths are constrained to an OpenClaw temp uploads root:
- uploads: `/tmp/openclaw/uploads` (fallback: `${os.tmpdir()}/openclaw/uploads` )
2026-01-08 23:06:56 +01:00
- `upload` can also set file inputs directly via `--input-ref` or `--element` .
2026-01-12 08:36:23 +00:00
- `snapshot` :
- `--format ai` (default when Playwright is installed): returns an AI snapshot with numeric refs (`aria-ref="<n>"` ).
- `--format aria` : returns the accessibility tree (no refs; inspection only).
2026-01-15 03:50:48 +00:00
- `--efficient` (or `--mode efficient` ): compact role snapshot preset (interactive + compact + depth + lower maxChars).
2026-03-19 10:31:20 -07:00
- Config default (tool/CLI only): set `browser.snapshotDefaults.mode: "efficient"` to use efficient snapshots when the caller does not pass a mode (see [Gateway configuration ](/gateway/configuration-reference#browser )).
2026-01-12 08:36:23 +00:00
- Role snapshot options (`--interactive` , `--compact` , `--depth` , `--selector` ) force a role-based snapshot with refs like `ref=e12` .
2026-01-12 17:32:02 +00:00
- `--frame "<iframe selector>"` scopes role snapshots to an iframe (pairs with role refs like `e12` ).
2026-01-12 08:36:23 +00:00
- `--interactive` outputs a flat, easy-to-pick list of interactive elements (best for driving actions).
2026-01-15 03:50:48 +00:00
- `--labels` adds a viewport-only screenshot with overlayed ref labels (prints `MEDIA:<path>` ).
2026-01-12 08:36:23 +00:00
- `click` /`type` /etc require a `ref` from `snapshot` (either numeric `12` or role ref `e12` ).
CSS selectors are intentionally not supported for actions.
2026-01-08 23:06:56 +01:00
2026-01-12 18:42:23 +00:00
## Snapshots and refs
2026-01-30 03:15:10 +01:00
OpenClaw supports two “snapshot” styles:
2026-01-12 18:42:23 +00:00
2026-01-30 03:15:10 +01:00
- **AI snapshot (numeric refs)**: `openclaw browser snapshot` (default; `--format ai` )
2026-01-12 18:42:23 +00:00
- Output: a text snapshot that includes numeric refs.
2026-01-30 03:15:10 +01:00
- Actions: `openclaw browser click 12` , `openclaw browser type 23 "hello"` .
2026-01-12 18:42:23 +00:00
- Internally, the ref is resolved via Playwright’ s `aria-ref` .
2026-01-30 03:15:10 +01:00
- **Role snapshot (role refs like `e12` )**: `openclaw browser snapshot --interactive` (or `--compact` , `--depth` , `--selector` , `--frame` )
2026-01-12 18:42:23 +00:00
- Output: a role-based list/tree with `[ref=e12]` (and optional `[nth=1]` ).
2026-01-30 03:15:10 +01:00
- Actions: `openclaw browser click e12` , `openclaw browser highlight e12` .
2026-01-12 18:42:23 +00:00
- Internally, the ref is resolved via `getByRole(...)` (plus `nth()` for duplicates).
2026-01-15 03:50:48 +00:00
- Add `--labels` to include a viewport screenshot with overlayed `e12` labels.
2026-01-12 18:42:23 +00:00
Ref behavior:
2026-01-31 21:13:13 +09:00
2026-01-12 18:42:23 +00:00
- Refs are **not stable across navigations ** ; if something fails, re-run `snapshot` and use a fresh ref.
- If the role snapshot was taken with `--frame` , role refs are scoped to that iframe until the next role snapshot.
## Wait power-ups
You can wait on more than just time/text:
- Wait for URL (globs supported by Playwright):
2026-01-30 03:15:10 +01:00
- `openclaw browser wait --url "**/dash"`
2026-01-12 18:42:23 +00:00
- Wait for load state:
2026-01-30 03:15:10 +01:00
- `openclaw browser wait --load networkidle`
2026-01-12 18:42:23 +00:00
- Wait for a JS predicate:
2026-01-30 03:15:10 +01:00
- `openclaw browser wait --fn "window.ready===true"`
2026-01-12 18:42:23 +00:00
- Wait for a selector to become visible:
2026-01-30 03:15:10 +01:00
- `openclaw browser wait "#main"`
2026-01-12 18:42:23 +00:00
These can be combined:
``` bash
2026-01-30 03:15:10 +01:00
openclaw browser wait "#main" \
2026-01-12 18:42:23 +00:00
--url "**/dash" \
--load networkidle \
--fn "window.ready===true" \
--timeout-ms 15000
```
## Debug workflows
When an action fails (e.g. “not visible”, “strict mode violation”, “covered”):
2026-01-30 03:15:10 +01:00
1. `openclaw browser snapshot --interactive`
2026-01-12 18:42:23 +00:00
2. Use `click <ref>` / `type <ref>` (prefer role refs in interactive mode)
2026-01-30 03:15:10 +01:00
3. If it still fails: `openclaw browser highlight <ref>` to see what Playwright is targeting
2026-01-12 18:42:23 +00:00
4. If the page behaves oddly:
2026-01-30 03:15:10 +01:00
- `openclaw browser errors --clear`
- `openclaw browser requests --filter api --clear`
2026-01-12 18:42:23 +00:00
5. For deep debugging: record a trace:
2026-01-30 03:15:10 +01:00
- `openclaw browser trace start`
2026-01-12 18:42:23 +00:00
- reproduce the issue
2026-01-30 03:15:10 +01:00
- `openclaw browser trace stop` (prints `TRACE:<path>` )
2026-01-12 18:42:23 +00:00
## JSON output
`--json` is for scripting and structured tooling.
Examples:
``` bash
2026-01-30 03:15:10 +01:00
openclaw browser status --json
openclaw browser snapshot --interactive --json
openclaw browser requests --filter api --json
openclaw browser cookies --json
2026-01-12 18:42:23 +00:00
```
Role snapshots in JSON include `refs` plus a small `stats` block (lines/chars/refs/interactive) so tools can reason about payload size and density.
## State and environment knobs
These are useful for “make the site behave like X” workflows:
- Cookies: `cookies` , `cookies set` , `cookies clear`
- Storage: `storage local|session get|set|clear`
- Offline: `set offline on|off`
2026-02-17 20:57:09 -05:00
- Headers: `set headers --headers-json '{"X-Debug":"1"}'` (legacy `set headers --json '{"X-Debug":"1"}'` remains supported)
2026-01-12 18:42:23 +00:00
- HTTP basic auth: `set credentials user pass` (or `--clear` )
- Geolocation: `set geo <lat> <lon> --origin "https://example.com"` (or `--clear` )
- Media: `set media dark|light|no-preference|none`
- Timezone / locale: `set timezone ...` , `set locale ...`
- Device / viewport:
- `set device "iPhone 14"` (Playwright device presets)
- `set viewport 1280 720`
2026-01-08 23:06:56 +01:00
## Security & privacy
2026-01-30 03:15:10 +01:00
- The openclaw browser profile may contain logged-in sessions; treat it as sensitive.
- `browser act kind=evaluate` / `openclaw browser evaluate` and `wait --fn`
2026-01-27 05:00:07 +00:00
execute arbitrary JavaScript in the page context. Prompt injection can steer
this. Disable it with `browser.evaluateEnabled=false` if you do not need it.
2026-01-12 02:01:32 +00:00
- For logins and anti-bot notes (X/Twitter, etc.), see [Browser login + X/Twitter posting ](/tools/browser-login ).
2026-01-27 03:23:42 +00:00
- Keep the Gateway/node host private (loopback or tailnet-only).
2026-01-08 23:06:56 +01:00
- Remote CDP endpoints are powerful; tunnel and protect them.
2026-01-05 15:16:00 +00:00
2026-02-24 01:51:44 +00:00
Strict-mode example (block private/internal destinations by default):
``` json5
{
browser: {
ssrfPolicy: {
dangerouslyAllowPrivateNetwork: false,
hostnameAllowlist: ["*.example.com", "example.com"],
allowedHostnames: ["localhost"], // optional exact allow
},
},
}
```
2026-01-05 15:16:00 +00:00
## Troubleshooting
2026-01-08 23:06:56 +01:00
For Linux-specific issues (especially snap Chromium), see
[Browser troubleshooting ](/tools/browser-linux-troubleshooting ).
2026-01-11 01:24:02 +01:00
2026-03-08 19:19:14 +00:00
For WSL2 Gateway + Windows Chrome split-host setups, see
[WSL2 + Windows + remote Chrome CDP troubleshooting ](/tools/browser-wsl2-windows-remote-cdp-troubleshooting ).
2026-01-11 01:24:02 +01:00
## Agent tools + how control works
The agent gets **one tool ** for browser automation:
2026-01-31 21:13:13 +09:00
2026-01-11 01:24:02 +01:00
- `browser` — status/start/stop/tabs/open/focus/close/snapshot/screenshot/navigate/act
How it maps:
2026-01-31 21:13:13 +09:00
2026-01-11 01:24:02 +01:00
- `browser snapshot` returns a stable UI tree (AI or ARIA).
- `browser act` uses the snapshot `ref` IDs to click/type/drag/select.
- `browser screenshot` captures pixels (full page or element).
- `browser` accepts:
2026-01-30 03:15:10 +01:00
- `profile` to choose a named browser profile (openclaw, chrome, or remote CDP).
2026-01-27 03:23:42 +00:00
- `target` (`sandbox` | `host` | `node` ) to select where the browser lives.
2026-01-11 01:24:02 +01:00
- In sandboxed sessions, `target: "host"` requires `agents.defaults.sandbox.browser.allowHostControl=true` .
- If `target` is omitted: sandboxed sessions default to `sandbox` , non-sandbox sessions default to `host` .
2026-01-27 03:23:42 +00:00
- If a browser-capable node is connected, the tool may auto-route to it unless you pin `target="host"` or `target="node"` .
2026-01-11 01:24:02 +01:00
This keeps the agent deterministic and avoids brittle selectors.
2026-03-31 14:34:20 +09:00
## Related
- [Tools Overview ](/tools ) — all available agent tools
- [Sandboxing ](/gateway/sandboxing ) — browser control in sandboxed environments
- [Security ](/gateway/security ) — browser control risks and hardening