Skip to content

Set Up Isolated OpenClaw Managed Browsers in 2 Minutes

OpenClaw runs a dedicated Chrome, Brave, Edge, or Chromium profile that the agent controls. It stays completely isolated from your personal browser and is managed through a local control service inside the Gateway.

Think of it as a separate, agent-only browser. The openclaw profile won’t touch your personal data. The agent can open tabs, read pages, click, and type in its own safe lane. If you want to use your real signed-in session, the built-in user profile handles that via Chrome MCP.

You get a separate browser profile named openclaw, which usually has an orange accent so you can tell it apart. It gives you deterministic tab control—meaning you can list, open, focus, or close tabs reliably.

The agent can perform actions like clicking, typing, dragging, and selecting. You can also grab snapshots, screenshots, and PDFs. If you need more than one setup, it supports multiple profiles like work or remote. This browser isn’t meant to be your daily driver; it is a safe, isolated space for agent automation and verification.

You can jump right in with these CLI commands:

Terminal window
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

If you see a “Browser disabled” message, you need to enable it in your config and restart the Gateway. If the openclaw browser command is missing or the agent says the tool is unavailable, check out the Missing browser command or tool section.

The default browser tool is a bundled plugin that is enabled by default. You can disable or replace it without breaking the rest of the OpenClaw plugin system.

To disable it, use this config:

{
plugins: {
entries: {
browser: {
enabled: false,
},
},
},
}

You should disable this bundled plugin before installing another one that uses the same browser tool name. For the default experience to work, you need two things:

  • plugins.entries.browser.enabled must not be disabled.
  • browser.enabled=true must be set.

If you turn off the plugin, the CLI, gateway methods, agent tools, and the control service all disappear. Your browser.* configuration stays there in case a replacement plugin wants to use those settings. Since the plugin owns the runtime implementation, removing it removes the whole feature set. Just remember that any browser config changes need a Gateway restart so the plugin can register the service with your new settings.

If openclaw browser suddenly stops working after an upgrade, or the agent can’t find the tool, it is usually because of a restrictive plugins.allow list. If you use an allowlist and forget to include browser, the plugin won’t load.

Here is an example of a config that would break the browser:

{
plugins: {
allow: ["telegram"],
},
}

You can fix this by adding browser to that list:

{
plugins: {
allow: ["telegram", "browser"],
},
}

Keep these points in mind:

  • Setting browser.enabled=true won’t help if plugins.allow blocks the plugin.
  • plugins.entries.browser.enabled=true also won’t work if the plugin isn’t on the allowlist.
  • Using tools.alsoAllow: ["browser"] does not load the plugin; it only changes policy for a plugin that is already running.
  • If you don’t actually need a strict allowlist, removing plugins.allow entirely will restore the default behavior.

You’ll know you have this issue if openclaw browser is an unknown command, browser.request is missing, or the agent says the tool is unavailable.

You have two main choices for browser profiles: openclaw and user. The openclaw profile is a managed, isolated browser that doesn’t require any extensions. The user profile is a built-in Chrome MCP attach profile designed for your real signed-in Chrome session.

When your agent makes browser tool calls, it uses the isolated openclaw browser by default. You should prefer profile="user" when your existing logged-in sessions are necessary and you are at your computer to click or approve any attach prompts. If you want a specific browser mode, use the profile override. If you want managed mode to be your standard, set browser.defaultProfile: "openclaw".

Your browser settings live in ~/.openclaw/openclaw.json. Here is how the configuration structure looks:

{
browser: {
enabled: true, // default: true
ssrfPolicy: {
// dangerouslyAllowPrivateNetwork: true, // opt in only for trusted private-network access
// allowPrivateNetwork: true, // legacy alias
// hostnameAllowlist: ["*.example.com", "example.com"],
// allowedHostnames: ["localhost"],
},
// cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override
remoteCdpTimeoutMs: 1500, // remote CDP HTTP timeout (ms)
remoteCdpHandshakeTimeoutMs: 3000, // remote CDP WebSocket handshake timeout (ms)
defaultProfile: "openclaw",
color: "#FF4500",
headless: false,
noSandbox: false,
attachOnly: false,
executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
profiles: {
openclaw: { cdpPort: 18800, color: "#FF4500" },
work: { cdpPort: 18801, color: "#0066CC" },
user: {
driver: "existing-session",
attachOnly: true,
color: "#00AA00",
},
brave: {
driver: "existing-session",
attachOnly: true,
userDataDir: "~/Library/Application Support/BraveSoftware/Brave-Browser",
color: "#FB542B",
},
remote: { cdpUrl: "http://10.0.0.42:9222", color: "#00AA00" },
},
},
}

Keep these details in mind:

  • The browser control service binds to loopback on a port derived from gateway.port. The default is 18791 (gateway + 2).
  • If you override the Gateway port using gateway.port or OPENCLAW_GATEWAY_PORT, the browser ports shift to stay in the same family.
  • If cdpUrl is unset, it defaults to the managed local CDP port.
  • For remote reachability checks, remoteCdpTimeoutMs and remoteCdpHandshakeTimeoutMs control the HTTP and WebSocket handshake timeouts.
  • Browser navigation is protected by SSRF guards before it starts and re-checked on the final URL. In strict SSRF mode, this also applies to remote CDP endpoint discovery and probes.
  • The browser.ssrfPolicy.dangerouslyAllowPrivateNetwork setting is disabled by default. You should only set it to true if you intentionally trust private-network browser access. The legacy alias browser.ssrfPolicy.allowPrivateNetwork is still supported.
  • Setting attachOnly: true means OpenClaw will never launch a local browser; it only attaches if one is already running.
  • You can use color and per-profile color settings to tint the browser UI, making it easy to see which profile is active.
  • The default profile is openclaw. Use defaultProfile: "user" if you want to opt into your signed-in user browser.
  • OpenClaw auto-detects your browser by checking the system default if it is Chromium-based. Otherwise, it searches in this order: Chrome, Brave, Edge, Chromium, and Chrome Canary.
  • Local openclaw profiles assign their own cdpPort and cdpUrl, so you only need to set those for remote CDP.
  • If you use driver: "existing-session", it uses the Chrome DevTools MCP instead of raw CDP. Do not set cdpUrl for this driver.
  • Set browser.profiles.<name>.userDataDir when an existing-session profile needs to attach to a non-default Chromium user profile like Brave or Edge.

Use Brave (or another Chromium-based browser)

Section titled “Use Brave (or another Chromium-based browser)”

If your system default browser is Chromium-based, OpenClaw uses it automatically. You can set browser.executablePath to override this auto-detection.

CLI example:

Terminal window
openclaw config set browser.executablePath "/usr/bin/google-chrome"
// 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"
}
}

You have three ways to handle browser control:

  • Local control (default): The Gateway starts the loopback control service and launches a local browser.
  • Remote control (node host): You run a node host on the machine that has the browser, and the Gateway proxies actions to it.
  • Remote CDP: Set browser.profiles.<name>.cdpUrl (or browser.cdpUrl) to attach to a remote Chromium-based browser. OpenClaw will not launch a local browser in this case.

The behavior of openclaw browser stop depends on your profile mode:

  • For local managed profiles, it stops the browser process that OpenClaw launched.
  • For attach-only and remote CDP profiles, it closes the active control session and releases Playwright/CDP emulation overrides like viewport, color scheme, locale, timezone, and offline mode. It does this even though it didn’t launch the browser process.

Remote CDP URLs can include authentication via query tokens (like https://provider.example?token=<token>) or HTTP Basic auth (like https://user:pass@provider.example). OpenClaw preserves this auth when calling /json/* endpoints and connecting to the CDP WebSocket. You should use environment variables or secrets managers for tokens instead of putting them in your config files.

If you run a node host on the machine that has your browser, OpenClaw can auto-route browser tool calls to that node. You don’t need any extra browser config for this. It is the default path for remote gateways.

Keep these points in mind:

  • The node host uses a proxy command to expose its local browser control server.
  • Your profiles come from the node’s own browser.profiles config, just like a local setup.
  • nodeHost.browserProxy.allowProfiles is optional. If you leave it empty, you get the default behavior where all configured profiles are reachable, including routes to create or delete profiles.
  • If you set nodeHost.browserProxy.allowProfiles, OpenClaw uses it as a least-privilege boundary. Only allowlisted profiles can be targeted, and the proxy blocks persistent profile create/delete routes.

If you want to turn this off:

  • On the node: nodeHost.browserProxy.enabled=false
  • On the gateway: gateway.nodes.browser.mode="off"

Browserless is a hosted Chromium service that provides CDP connection URLs over HTTPS and WebSocket. OpenClaw can use either, but the simplest way to handle a remote browser profile is using the direct WebSocket URL from the Browserless docs.

Example:

{
browser: {
enabled: true,
defaultProfile: "browserless",
remoteCdpTimeoutMs: 2000,
remoteCdpHandshakeTimeoutMs: 4000,
profiles: {
browserless: {
cdpUrl: "wss://production-sfo.browserless.io?token=<BROWSERLESS_API_KEY>",
color: "#00AA00",
},
},
},
}

Notes for your setup:

  • Replace <BROWSERLESS_API_KEY> with your real Browserless token.
  • Pick the region endpoint that matches your Browserless account.
  • If Browserless gives you an HTTPS base URL, you can convert it to wss:// for a direct CDP connection. You can also keep the HTTPS URL and let OpenClaw find /json/version.

Some hosted browser services use a direct WebSocket endpoint instead of the standard HTTP-based CDP discovery. OpenClaw supports both methods:

  • HTTP(S) endpoints — OpenClaw calls /json/version to find the WebSocket debugger URL and then connects.
  • WebSocket endpoints (ws:// / wss://) — OpenClaw connects directly and skips the /json/version step. Use this for services like Browserless or Browserbase.

Browserbase is a cloud platform for running headless browsers. It includes built-in CAPTCHA solving, stealth mode, and residential proxies.

{
browser: {
enabled: true,
defaultProfile: "browserbase",
remoteCdpTimeoutMs: 3000,
remoteCdpHandshakeTimeoutMs: 5000,
profiles: {
browserbase: {
cdpUrl: "wss://connect.browserbase.com?apiKey=<BROWSERBASE_API_KEY>",
color: "#F97316",
},
},
},
}

Notes for your setup:

  • Sign up and get your API Key from the Overview dashboard.
  • Replace <BROWSERBASE_API_KEY> with your real Browserbase API key.
  • Browserbase creates a browser session automatically when you connect via WebSocket, so you don’t need a manual session step.
  • The free tier allows one concurrent session and one browser hour per month. You can check their pricing for paid plans.
  • Check the Browserbase docs for the full API reference and integration examples.

Here are the key ideas for keeping your setup safe:

  • Browser control is loopback-only. Access flows through the Gateway’s auth or node pairing.
  • The standalone loopback browser HTTP API uses shared-secret auth only. This means gateway token bearer auth, x-openclaw-password, or HTTP Basic auth with your gateway password.
  • Tailscale Serve identity headers and gateway.auth.mode: "trusted-proxy" do not authenticate this specific API.
  • If browser control is on and you haven’t configured shared-secret auth, OpenClaw creates gateway.auth.token on startup and saves it to your config.
  • OpenClaw does not create that token when gateway.auth.mode is already set to password, none, or trusted-proxy.
  • Keep the Gateway and any node hosts on a private network like Tailscale and avoid public exposure.
  • Treat remote CDP URLs and tokens as secrets. Use environment variables or a secrets manager.

Remote CDP tips:

  • Use encrypted endpoints like HTTPS or WSS and short-lived tokens.
  • Avoid putting long-lived tokens directly into your config files.

OpenClaw lets you manage multiple named profiles for your routing configurations. You can choose from four different setups depending on your needs:

  • openclaw-managed: This gives you a dedicated Chromium-based browser instance.
  • openclaw-managed (data): It uses its own user data directory and a specific CDP port.
  • remote: You can point to an explicit CDP URL for a Chromium-based browser running on another machine.
  • existing session: This connects to your actual Chrome profile using the Chrome DevTools MCP auto-connect feature.

Here are the default settings you should know:

  • OpenClaw creates the openclaw profile automatically if it is missing.
  • The user profile is built-in specifically for attaching to existing Chrome MCP sessions.
  • If you want more existing-session profiles, you have to opt-in by creating them with the --driver existing-session flag.
  • Local CDP ports are allocated from the 18800–18899 range by default.
  • When you delete a profile, OpenClaw moves its local data directory to the Trash.
  • All control endpoints support the ?profile=<name> parameter, and you can use --browser-profile in the CLI.

You can attach OpenClaw to a Chromium-based browser profile that is already running. This is a great way to reuse the tabs and login states you already have open. It works through the official Chrome DevTools MCP server.

You can find more background and setup details here:

The user profile is built-in for this mode. If you want a different name, a specific color, or a custom browser data directory, you can create your own custom existing-session profile. By default, the user profile uses Chrome MCP auto-connect to target your default local Google Chrome profile.

If you need to target Brave, Edge, Chromium, or a non-default Chrome profile, use the userDataDir setting:

{
browser: {
profiles: {
brave: {
driver: "existing-session",
attachOnly: true,
userDataDir: "~/Library/Application Support/BraveSoftware/Brave-Browser",
color: "#FB542B",
},
},
},
}

Once you have configured it, follow these steps in the matching browser:

  1. Open the browser’s inspect page for remote debugging.
  2. Turn on remote debugging.
  3. Keep the browser running.
  4. Approve the connection prompt when OpenClaw tries to attach.

You can find the inspect pages at these locations:

  • Chrome: chrome://inspect/#remote-debugging
  • Brave: brave://inspect/#remote-debugging
  • Edge: edge://inspect/#remote-debugging
  • Chromium: chrome://inspect/#remote-debugging

You can run a smoke test to verify the live attachment:

Terminal window
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

You will know it is working when you see these results:

  • The status command shows driver: existing-session.
  • The status command shows transport: chrome-mcp.
  • The status command confirms running: true.
  • The tabs command lists the tabs you already have open.
  • The snapshot command returns references from your selected live tab.
  • The connection is active and responsive.

If the attachment fails, check these four points:

  • Your Chromium-based browser must be version 144 or higher.
  • Remote debugging must be enabled in the browser’s inspect page.
  • You must accept the attach consent prompt when it appears in the browser.
  • Run openclaw doctor to migrate old configs and ensure Chrome is installed locally. Note that it cannot enable remote debugging for you.

When using an agent, keep these four things in mind:

  • Use profile="user" when you need your logged-in browser state.
  • Pass the explicit profile name if you are using a custom existing-session profile.
  • Only use this mode when you are at the computer to approve the attach prompt.
  • The Gateway or node host can run npx chrome-devtools-mcp@latest --autoConnect.

There are some important notes for this path:

  • This mode is higher-risk than the isolated openclaw profile because it operates inside your signed-in session.
  • OpenClaw does not launch the browser for this driver; it only attaches to an existing one.
  • It uses the official Chrome DevTools MCP --autoConnect flow. If you set userDataDir, OpenClaw passes it through to that specific directory.
  • Screenshots support page captures and --ref element captures, but they do not support CSS --element selectors.
  • Page screenshots work without Playwright through Chrome MCP, but you cannot combine --full-page with --ref or --element.
  • Actions are more limited than the managed browser path.
  • click, type, hover, scrollIntoView, drag, and select require snapshot refs instead of CSS selectors.
  • click only supports the left button without overrides or modifiers.
  • type does not support slowly=true; you should use fill or press instead.
  • press does not support delayMs.
  • hover, scrollIntoView, drag, select, fill, and evaluate do not support per-call timeout overrides.
  • select only supports a single value at this time.
  • wait --url supports exact, substring, and glob patterns, but wait --load networkidle is not supported yet.
  • Upload hooks require ref or inputRef and handle one file at a time without CSS element targeting.
  • Dialog hooks do not support timeout overrides.
  • You still need the managed browser path for batch actions, PDF export, download interception, and responsebody.
  • Existing-session is host-local. If Chrome is on a different machine or network, use remote CDP or a node host.

OpenClaw provides several guarantees to keep your environments clean:

  • Dedicated user data dir: It never touches your personal browser profile.
  • Dedicated ports: It avoids port 9222 to prevent collisions with your other development workflows.
  • Deterministic tab control: You target tabs by targetId instead of relying on the “last tab” opened.
  • Trash-based data deletion: Local data directories are moved to the Trash rather than being permanently deleted immediately.

When you launch a browser locally, OpenClaw looks for the first available option in this order:

  1. Chrome
  2. Brave
  3. Edge
  4. Chromium
  5. Chrome Canary
  6. Custom path via browser.executablePath

The system checks standard locations across different platforms:

  • macOS: It looks in /Applications and ~/Applications.
  • Linux: It searches for google-chrome, brave, microsoft-edge, and chromium.
  • Windows: It checks the common installation folders.
  • Custom: You can always override the selection by providing a specific browser.executablePath.

AI Setup Assistant

If you are building local integrations, the Gateway provides a small loopback HTTP API. It is optional, but it gives you a direct way to interact with the browser.

Here are the endpoints available to you:

  • 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 /go to, POST /act
  • Hooks: POST /hooks/file-chooser, POST /hooks/dialog
  • Downloads: POST /download, POST /wait/download
  • Debugging: GET /console, POST /pdf
  • Debugging: GET /errors, GET /requests, POST /trace/start, POST /trace/stop, POST /highlight
  • Network: POST /response/body
  • 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

Every endpoint accepts the ?profile=<name> parameter.

If you have configured shared-secret gateway auth, these browser HTTP routes will also require authentication:

  • Authorization: Bearer <gateway token>
  • x-openclaw-password: <gateway password> or HTTP Basic auth with that password

A few important notes:

  • This standalone loopback browser API does not consume trusted-proxy or Tailscale Serve identity headers.
  • If gateway.auth.mode is set to none or trusted-proxy, these loopback browser routes do not inherit those identity-bearing modes. You should keep them loopback-only.

The POST /act endpoint uses a structured error response for route-level validation and policy failures:

{ "error": "<message>", "code": "ACT_*" }

You might see these code values:

  • ACT_KIND_REQUIRED (HTTP 400): kind is missing or unrecognized.
  • ACT_INVALID_REQUEST (HTTP 400): action payload failed normalization or validation.
  • ACT_SELECTOR_UNSUPPORTED (HTTP 400): selector was used with an unsupported action kind.
  • ACT_EVALUATE_DISABLED (HTTP 403): evaluate (or wait --fn) is disabled by config.
  • ACT_TARGET_ID_MISMATCH (HTTP 403): top-level or batched targetId conflicts with request target.
  • ACT_EXISTING_SESSION_UNSUPPORTED (HTTP 501): action is not supported for existing-session profiles.

Other runtime failures might return { "error": "<message>" } without a code field.

Some features like go to, act, AI snapshots, role snapshots, element screenshots, and PDF generation require Playwright. If Playwright is not installed, these endpoints will return a 501 error.

These features still work 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

These features require Playwright:

  • go to
  • act
  • AI snapshots / role snapshots
  • CSS-selector element screenshots (--element)
  • full browser PDF export

Element screenshots also reject the --full-page flag. The route will return fullPage is not supported for element screenshots.

If you see a message saying Playwright is not available in this gateway build, you need to install the full Playwright package (not playwright-core) and restart the gateway. You can also reinstall OpenClaw with browser support.

If you run the Gateway in Docker, avoid using npx playwright because of npm override conflicts. Use the bundled CLI instead:

Terminal window
docker compose run --rm openclaw-cli \
node /app/node_modules/playwright-core/cli.js install chromium

To keep your browser downloads, set the PLAYWRIGHT_BROWSERS_PATH (for example, /home/node/.cache/ms-playwright). Make sure /home/node is persisted through OPENCLAW_HOME_VOLUME or a bind mount. You can find more details in the Docker documentation.

Here is the high-level flow of how the system operates:

  • A small control server accepts your HTTP requests.
  • It connects to Chromium-based browsers like Chrome, Brave, Edge, or Chromium via CDP.
  • For advanced actions such as clicks, typing, snapshots, or PDF generation, 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 interface while allowing you to swap between local or remote browsers and profiles.

AI Setup Assistant

You can use --browser-profile <name> with any command to target a specific profile. If you need machine-readable output for your scripts, all commands also accept the --json flag for stable payloads.

Here are the basic commands you’ll use to manage your browser:

Terminal window
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

When you need to see what’s happening under the hood, use these inspection tools:

Terminal window
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

Regarding the lifecycle:

For attach-only and remote CDP profiles, openclaw browser stop is still the right cleanup command after your tests. It closes the active control session and clears temporary emulation overrides instead of killing the underlying browser.

Terminal window
openclaw browser errors --clear
openclaw browser requests --filter api --clear
openclaw browser pdf
openclaw browser responsebody "**/api" --max-chars 5000

To interact with the page, use these action commands:

Terminal window
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
openclaw browser download e12 report.pdf
openclaw browser waitfordownload report.pdf
openclaw browser upload /tmp/openclaw/uploads/file.pdf
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

You can also manage the browser state, cookies, and emulation settings:

Terminal window
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
openclaw browser set headers --headers-json '{"X-Debug":"1"}'
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"

Keep these notes in mind:

  • upload and dialog are arming calls; run them before the click or press that triggers the chooser or dialog.
  • Download and trace output paths are restricted to OpenClaw temp roots:
  • traces: /tmp/openclaw (fallback: ${os.tmpdir()}/openclaw)
  • downloads: /tmp/openclaw/downloads (fallback: ${os.tmpdir()}/openclaw/downloads)
  • Upload paths are restricted to an OpenClaw temp uploads root:
  • uploads: /tmp/openclaw/uploads (fallback: ${os.tmpdir()}/openclaw/uploads)
  • upload can also set file inputs directly via --input-ref or --element.
  • snapshot details:
  • --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).
  • --efficient (or --mode efficient): compact role snapshot preset (interactive + compact + depth + lower maxChars).
  • 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).
  • Role snapshot options (--interactive, --compact, --depth, --selector) force a role-based snapshot with refs like ref=e12.
  • --frame "<iframe selector>" scopes role snapshots to an iframe (pairs with role refs like e12).
  • --interactive outputs a flat, easy-to-pick list of interactive elements (best for driving actions).
  • --labels adds a viewport-only screenshot with overlayed ref labels (prints MEDIA:<path>).
  • click, type, and other actions require a ref from a snapshot (either numeric 12 or role ref e12). CSS selectors are intentionally not supported for actions.

OpenClaw supports two different snapshot styles depending on your needs:

  • AI snapshot (numeric refs): openclaw browser snapshot (default; --format ai)

  • Output: a text snapshot that includes numeric refs.

  • Actions: openclaw browser click 12, openclaw browser type 23 "hello".

  • Internally, the ref is resolved via Playwright’s aria-ref.

  • Role snapshot (role refs like e12): openclaw browser snapshot --interactive (or --compact, --depth, --selector, --frame)

  • Output: a role-based list or tree with [ref=e12] (and optional [nth=1]).

  • Actions: openclaw browser click e12, openclaw browser highlight e12.

  • Internally, the ref is resolved via getByRole(...) (plus nth() for duplicates).

  • Add --labels to include a viewport screenshot with overlayed e12 labels.

A few things to remember about ref behavior:

  • Refs are not stable across page changes. If an action fails, you should re-run snapshot and use a fresh ref.
  • If you took a role snapshot with --frame, your role refs are scoped to that iframe until you take the next role snapshot.

You can wait on much more than just time or text. You have several options to ensure the page is exactly where you need it to be:

  • Wait for a URL (Playwright globs are supported):
  • openclaw browser wait --url "**/dash"
  • Wait for a specific load state:
  • openclaw browser wait --load networkidle
  • Wait for a JS predicate:
  • openclaw browser wait --fn "window.ready===true"
  • Wait for a selector to become visible:
  • openclaw browser wait "#main"

You can also combine these into a single command:

Terminal window
openclaw browser wait "#main" \
--url "**/dash" \
--load networkidle \
--fn "window.ready===true" \
--timeout-ms 15000

When an action fails—maybe you see an error like “not visible,” “strict mode violation,” or “covered”—you can follow this workflow to fix it:

  1. Run openclaw browser snapshot --interactive.
  2. Use click <ref> or type <ref>. You should prefer role refs when you are working in interactive mode.
  3. If the action still fails, use openclaw browser highlight <ref> to see exactly what Playwright is targeting.
  4. If the page behaves oddly, check the logs:
  • openclaw browser errors --clear
  • openclaw browser requests --filter api --clear
  1. For deep debugging, you can record a trace:
  • Start with openclaw browser trace start.
  • Reproduce the issue.
  • Finish with openclaw browser trace stop (this prints the TRACE:<path>).

If you are building scripts or structured tooling, you should use the --json flag. It turns the output into machine-readable data that you can pipe into other programs.

Here are a few ways you can use it:

Terminal window
openclaw browser status --json
openclaw browser snapshot --interactive --json
openclaw browser requests --filter api --json
openclaw browser cookies --json

When you take role snapshots in JSON, the output includes refs along with a small stats block. This block tracks lines, characters, references, and interactive elements. These details help your tools reason about the size and density of the payload before you process it.

These settings are great for “make the site behave like X” workflows. You can use these commands to control the browser state and environment:

  • Cookies: Manage these with cookies, cookies set, or cookies clear.
  • Storage: Access or modify data using storage local|session get|set|clear.
  • Offline mode: Toggle connectivity with set offline on|off.
  • Headers: Use set headers --headers-json '{"X-Debug":"1"}'. If you are used to the older syntax, the legacy set headers --json '{"X-Debug":"1"}' is still supported.
  • HTTP basic auth: Handle credentials with set credentials user pass or remove them with --clear.
  • Geolocation: Define your location using set geo <lat> <lon> --origin "https://example.com" or reset it with --clear.
  • Media: Change the appearance with set media dark|light|no-preference|none.
  • Timezone and locale: Adjust your regional settings with set timezone ... and set locale ....
  • Device: Use set device "iPhone 14" to apply Playwright device presets.
  • Viewport: Set specific screen dimensions with set viewport 1280 720.

You should treat your openclaw browser profile as sensitive data because it can contain active logged-in sessions.

The browser act kind=evaluate command, openclaw browser evaluate, and wait --fn are designed to run arbitrary JavaScript within the page context. This means prompt injection could potentially steer these actions. If your use case doesn’t require this, you can turn it off by setting browser.evaluateEnabled=false.

If you are working with logins or dealing with anti-bot measures on sites like X/Twitter, you can find specific notes in the guide for Browser login + X/Twitter posting.

It is best practice to keep your Gateway or node host private. Use loopback or a tailnet to stay safe. Remote CDP endpoints give you a lot of control over the browser, so you must tunnel and protect them.

Here is a strict-mode example that blocks private or internal destinations by default:

{
browser: {
ssrfPolicy: {
dangerouslyAllowPrivateNetwork: false,
hostnameAllowlist: ["*.example.com", "example.com"],
allowedHostnames: ["localhost"], // optional exact allow
},
},
}

If you run into issues on Linux, particularly with snap Chromium, head over to the Browser troubleshooting page.

If you are using a split-host setup with WSL2 Gateway and Windows Chrome, check out the guide for WSL2 + Windows + remote Chrome CDP troubleshooting to fix common connection problems.

You get exactly one tool for browser automation:

  • browser — status/start/stop/tabs/open/focus/close/snapshot/screenshot/go to/act

This is how the mapping works for you:

  • browser snapshot returns a stable UI tree (AI or ARIA).
  • browser act uses the snapshot ref IDs to click, type, drag, or select.
  • browser screenshot captures pixels for the full page or a specific element.

The browser tool accepts these parameters:

  • profile to choose a named browser profile (openclaw, chrome, or remote CDP).
  • target (sandbox | host | node) to select where the browser lives.

In sandboxed sessions, using target: "host" requires you to set agents.defaults.sandbox.browser.allowHostControl=true.

If you omit the target, sandboxed sessions default to sandbox and non-sandbox sessions default to host. If a browser-capable node is connected, the tool may auto-route to it unless you pin target="host" or target="node".

This setup keeps the agent deterministic and helps you avoid dealing with brittle selectors.

AI Setup Assistant

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.