OpenClaw-Managed Browser: Dedicated Agent-Only Profile

This page explains how OpenClaw launches a separate Chrome/Brave/Edge/Chromium profile for agent control. It covers deterministic tab management, agent actions, and managed downloads for developers integrating browser automation.

Read this when

  • Adding agent-controlled browser automation
  • Debugging why openclaw is interfering with your own Chrome
  • Implementing browser settings + lifecycle in the macOS app

OpenClaw can launch a dedicated Chrome/Brave/Edge/Chromium profile under agent control. This runs via a small local control service inside the Gateway (loopback only) and stays separate from your personal browser.

  • Treat it as a distinct, agent-only browser. The openclaw profile never interacts with your personal browser profile.
  • Inside this isolated lane, the agent opens tabs, reads pages, clicks, and types.
  • The built-in user profile, by contrast, connects to your actual signed-in Chrome session through Chrome DevTools MCP.

What you get

  • A dedicated browser profile called openclaw (default orange accent).
  • Deterministic tab management (list, open, focus, close).
  • Agent operations (click, type, drag, select), snapshots, screenshots, PDFs.
  • Playwright-backed profiles store direct attachment navigations under the managed downloads directory and return { url, suggestedFilename, path } metadata after final-URL policy validation.
  • When an action immediately starts one or more downloads, Playwright-backed agent actions return a downloads array with the same managed metadata.
  • A bundled browser-automation skill teaches agents the snapshot, stable-tab, stale-ref, and manual-blocker recovery loop when the browser plugin is enabled.
  • Optional multi-profile support (openclaw, work, remote, ...).

This browser is not meant for everyday use. It provides a safe, isolated environment for agent automation and verification.

On macOS, you can explicitly copy cookies from a Chrome-family system profile into a separate managed profile. The managed browser still uses its own user data directory; only the selected cookies are copied, while local storage and IndexedDB remain behind. See Profiles or the openclaw browser CLI reference for import commands and limitations.

Quick start

openclaw browser --browser-profile openclaw doctor
openclaw browser --browser-profile openclaw doctor --deep
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

"Browser disabled" means the plugin or browser.enabled is turned off; see Configuration and Plugin control.

If openclaw browser is completely absent, or the agent reports the browser tool as unavailable, go to Missing browser command or tool.

Plugin control

The default browser tool is a bundled plugin. Disable it to swap it with another plugin that registers the same browser tool name:

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

Defaults require both plugins.entries.browser.enabled and browser.enabled=true. Disabling only the plugin removes the openclaw browser CLI, browser.request gateway method, agent tool, and control service as a single unit; your browser.* config remains intact for a replacement.

Browser configuration changes need a Gateway restart so the plugin can re-register its service.

Agent guidance

Tool-profile note: tools.profile: "coding" includes web_search and web_fetch, but not the full browser tool. To allow the agent or a spawned sub-agent to use browser automation, add browser at the profile stage:

{
  tools: {
    profile: "coding",
    alsoAllow: ["browser"],
  },
}

For a single agent, use agents.entries.*.tools.alsoAllow: ["browser"]. tools.subagents.tools.allow: ["browser"] alone is insufficient because sub-agent policy is applied after profile filtering.

The browser plugin provides two levels of agent guidance:

  • The browser tool description contains the compact always-on contract: choose the right profile, keep refs on the same tab, use tabId/labels for tab targeting, and load the browser skill for multi-step work.
  • The bundled browser-automation skill carries the longer operating loop: check status/tabs first, label task tabs, snapshot before acting, resnapshot after UI changes, recover stale refs once, and report login/2FA/captcha or camera/microphone blockers as manual action instead of guessing.

Plugin-bundled skills appear in the agent's available skills when the plugin is enabled. The full skill instructions load on demand, so routine turns do not incur the full token cost.

Missing browser command or tool

If openclaw browser is unknown after an upgrade, browser.request is missing, or the agent reports the browser tool as unavailable, the usual cause is a plugins.allow list that omits browser and no root browser config block exists. Add it:

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

An explicit root browser block (any key under browser, such as browser.enabled=true or browser.profiles.<name>) activates the bundled browser plugin even under a restrictive plugins.allow, matching bundled channel config behavior. plugins.entries.browser.enabled=true and tools.alsoAllow: ["browser"] do not by themselves substitute for allowlist membership. Removing plugins.allow entirely also restores the default.

Profiles: openclaw, user, chrome

  • openclaw: managed, isolated browser (no extension required).
  • user: built-in Chrome DevTools MCP attach profile for your real signed-in Chrome session. Chrome shows a blocking "Allow remote debugging?" prompt the first time OpenClaw attaches, so someone must be at the computer.
  • chrome: built-in Chrome extension profile for your real signed-in Chrome session. Works from a phone with nobody at the desk because it drives tabs through the OpenClaw browser extension instead of the remote-debugging port, so there is no "Allow remote debugging?" prompt.

For agent browser tool calls:

  • The default is to use the isolated openclaw browser.
  • When the user is away from the computer (Telegram, WhatsApp, etc.) and existing logged-in sessions matter, prefer profile="chrome" (extension).
  • When the user is at the computer to approve the attach prompt and existing logged-in sessions matter, prefer profile="user" (Chrome MCP).
  • profile serves as the explicit override when you need a particular browser mode.

Set browser.defaultProfile: "openclaw" to enable managed mode as the default.

Configuration

Browser settings are configured in ~/.openclaw/openclaw.json.

{
  browser: {
    enabled: true, // default: true
    evaluateEnabled: true, // default: true; false disables act:evaluate (arbitrary JS)
    ssrfPolicy: {
      // dangerouslyAllowPrivateNetwork: true, // opt in only for trusted private-network access
      // hostnameAllowlist: ["*.example.com", "example.com"],
      // allowedHostnames: ["localhost"],
    },
    // cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override
    tabCleanup: {
      enabled: true, // default: true
    },
    // snapshotDefaults: { mode: "efficient" }, // default snapshot mode when the caller omits one
    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",
        headless: true,
        executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
      },
      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" },
    },
  },
}

If a caller does not supply an explicit snapshotFormat or mode, browser.snapshotDefaults.mode: "efficient" alters the default snapshot extraction mode; per-call snapshot options are documented in the Browser control API.

Tab cleanup ownership

Session tab cleanup applies exclusively to tabs created by the OpenClaw browser tool using action: "open". Tabs that were already open, opened manually, or have unknown ownership are not adopted by OpenClaw. The browser.tabCleanup block governs periodic idle and cap sweeps for primary sessions; disabling it does not turn off explicit session lifecycle cleanup.

For host-local opens, ownership with a stable native CDP target and browser identity is recorded in the shared SQLite state. These records persist through a Gateway restart and stay eligible for /new and other session lifecycle cleanup, which includes subagent, cron, and ACP session endings. Records whose tool-facing target matches the native CDP target also remain eligible for idle and per-session cap sweeps after a restart. Chrome MCP target handles are process-local, so cold existing-session records wait for lifecycle cleanup instead of risking an idle sweep against activity that cannot be safely attributed after a restart. This durable path can cover OpenClaw-managed profiles, regular remote CDP profiles, and existing-session profiles with an explicit cdpUrl, as long as OpenClaw can resolve both the native target and a stable browser identity. Before closing a durable record, OpenClaw confirms that the configured profile and browser instance still match.

Chrome MCP --autoConnect, CDP endpoints whose /json/version response lacks a stable browser identity, and opens whose native target cannot be resolved remain process-local best-effort tracking. They can be cleaned up while that Gateway process is active, but they are not automatically closed after a Gateway restart. Tabs left open before durable tracking was available are not retroactively adopted; close those tabs manually.

Cleanup operates on a best-effort basis, not a guarantee that every eligible tab closes immediately. A transient ownership check or close failure leaves durable cleanup pending for a later retry. Retries are not unbounded: when the browser remains unreachable and the tab has gone unused for over a day, the tracking row is retired so the durable store cannot fill up with tabs that can never be verified again.

Screenshot vision (text-only model support)

When the main model is text-only (no vision/multimodal support), browser screenshots return image blocks that the model cannot read. Browser screenshots reuse the existing image-understanding configuration, so an image model configured for media understanding can describe screenshots as text without any browser-specific model settings.

{
  tools: {
    media: {
      image: {
        models: [
          { provider: "bytedance", model: "doubao-seed-2.0-pro" },
          // Add fallback candidates; first success wins
          { provider: "openai", model: "gpt-4o" },
        ],
      },
      // Shared media models also work when tagged for image support.
      // models: [{ provider: "openai", model: "gpt-4o", capabilities: ["image"] }],
    },
  },
  agents: {
    defaults: {
      // Existing image-model defaults are also honored.
      // imageModel: { primary: "openai/gpt-4o" },
    },
  },
}

How it works:

  1. The agent calls browser screenshot and an image is captured to disk as usual.
  2. The browser tool asks the existing image-understanding runtime whether it can describe the screenshot using configured media image models, shared media models, image-model defaults, or an auth-backed image provider.
  3. The vision model returns a text description, which is wrapped with wrapExternalContent (prompt injection guard) and returned to the agent as a text block instead of an image block.
  4. If image understanding is unavailable, skipped, or fails, the browser falls back to returning the original image block.

Screenshot image blocks are private tool results: the agent can inspect them, but OpenClaw does not automatically attach them to channel replies. To share a screenshot, ask the agent to send it explicitly with the message tool.

Use the existing tools.media.image / tools.media.models fields for model fallbacks, timeouts, byte limits, profiles, and provider request settings.

If the active main model already supports vision and no explicit image understanding model is configured, OpenClaw keeps the normal image result so the main model can read the screenshot directly.

Ports and reachability

  • The control service binds to loopback on a port derived from gateway.port (default 18791 = gateway + 2). OPENCLAW_GATEWAY_PORT takes priority over gateway.port; either shifts the derived ports in the same family.
  • Local openclaw profiles auto-assign cdpPort/cdpUrl from a range starting 9 ports above the control port (default 18800-18899); set those only for remote CDP profiles or existing-session endpoint attach. cdpUrl defaults to the managed local CDP port when unset.
  • Remote and attachOnly CDP reachability, WebSocket handshakes, and local managed-Chrome startup use built-in deadlines.
  • Repeated managed Chrome launch/readiness failures are circuit-broken per profile. After several consecutive failures, OpenClaw pauses new launch attempts briefly instead of spawning Chromium on every browser tool call. Fix the startup problem, disable the browser if it is not needed, or restart the Gateway after repair.

SSRF policy

  • Browser navigation and open-tab requests are preflight checked. During the action and bounded post-action grace, guarded Playwright interactions (click, coordinate click, hover, drag, scroll, select, press, type, form fill, and evaluate) intercept policy-denied top-level and subframe document loads before HTTP request bytes, then best-effort re-check the final http(s) URL.
  • Before each fresh OpenClaw-managed Chrome launch, OpenClaw best-effort disables network prediction, suppressing Chromium's observed speculative preconnect for those denied loads. This is defense in depth, not a policy boundary: a browser reused across a control-service restart and other browser backends may not share the hardening. Playwright routing is still not a network firewall and does not intercept redirect hops, a popup's first request, Service Worker traffic, page code that runs after the bounded guard window, or every background/subresource path. Complete egress isolation requires owner-side isolation or a policy-enforcing proxy.
  • In strict SSRF mode, remote CDP endpoint discovery and /json/version probes (cdpUrl) are checked too.
  • Gateway/provider HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY environment variables do not automatically proxy the OpenClaw-managed browser. Managed Chrome launches direct by default so provider proxy settings do not weaken browser SSRF checks.
  • OpenClaw-managed local CDP readiness probes and DevTools WebSocket connections bypass the managed network proxy for the exact launched loopback endpoint, so openclaw browser start still works when an operator proxy blocks loopback egress.
  • To proxy the managed browser itself, pass explicit Chrome proxy flags through browser.extraArgs, such as --proxy-server=... or --proxy-pac-url=.... Strict SSRF mode blocks explicit browser proxy routing unless private-network browser access is intentionally enabled.
  • browser.ssrfPolicy.dangerouslyAllowPrivateNetwork is off by default; enable only when private-network browser access is intentionally trusted.
  • browser.ssrfPolicy.allowPrivateNetwork remains supported as a legacy alias.

Profile behavior

  • attachOnly: true prevents any local browser from being started; it only connects to an existing instance.
  • headless supports configuration at either the global level or for individual local managed profiles. A profile-specific setting takes precedence over browser.headless, allowing one locally launched profile to operate headlessly while another remains visible.
  • Both POST /start?headless=true and openclaw browser start --headless trigger a one-time headless launch for local managed profiles without modifying browser.headless or the profile's configuration. Profiles using existing sessions, attach-only mode, or remote CDP reject this override because OpenClaw does not start browser processes for them.
  • On Linux systems lacking DISPLAY or WAYLAND_DISPLAY, local managed profiles automatically run headless when neither the environment nor profile or global configuration explicitly selects headed mode. Use the unambiguous browser-level form openclaw browser --json status; trailing openclaw browser status --json also functions because status has no --json of its own. The command outputs headlessSource as env, profile, config, request, linux-display-fallback, or default.
  • OPENCLAW_BROWSER_HEADLESS=1 forces headless operation for all local managed launches in the current process. OPENCLAW_BROWSER_HEADLESS=0 forces headed mode for normal starts and provides a meaningful error on Linux hosts without a display server; an explicit start --headless request still takes priority for that specific launch.
  • The browser-control route and programmatic client preserve the human-readable error from the no-display error and expose the stable reason no_display_for_headed_profile. Its details contain only profile, requestedHeadless, headlessSource, and displayPresent, enabling API clients to pick the right fix without parsing message text.
  • For an active local managed profile, status and doctor queries use Chrome's browser-level CDP endpoint to inspect renderer, backend, device and driver, feature status, driver workarounds, and accelerated video capabilities. The result is cached for that browser process and fully available through openclaw browser --json status. A passive status call does not start Chrome. Existing-session, extension, remote CDP, and sandbox browsers are separate and not examined through this managed-host path.
  • Headless managed Chrome still applies the conservative --disable-gpu default. The diagnostics do not turn on acceleration, add a global acceleration setting, or give sandbox browsers device access.
  • executablePath can be set globally or for individual local managed profiles. Profile-specific values override browser.executablePath, so different managed profiles can use different Chromium-based browsers. Both forms accept ~ for your operating system's home directory.
  • color (both top-level and per-profile) colors the browser UI to indicate which profile is active.
  • The default profile is openclaw (managed standalone). Use defaultProfile: "user" to choose the signed-in user browser.
  • Auto-detection order: system default browser if it is Chromium-based; otherwise Chrome, Brave, Edge, Chromium, Chrome Canary.
  • driver: "existing-session" uses the Chrome DevTools MCP instead of raw CDP. It can attach through Chrome MCP auto-connect or through cdpUrl when you already have a DevTools endpoint for the running browser.
  • driver: "extension" controls your signed-in Chrome through the OpenClaw Chrome extension. The relay owns its loopback endpoint, so these profiles do not accept cdpUrl. This is the only signed-in-browser mode that works without anyone at the computer.
  • Set browser.profiles.<name>.userDataDir when an existing-session profile should attach to a non-default Chromium user profile (Brave, Edge, etc.). This path also accepts ~ for your operating system's home directory.

Use Brave or another Chromium-based browser

If your system default browser is Chromium-based (Chrome/Brave/Edge/etc), OpenClaw uses it automatically. Set browser.executablePath to override auto-detection. Top-level and per-profile executablePath values accept ~ for your OS home directory:

openclaw config set browser.executablePath "/usr/bin/google-chrome"
openclaw config set browser.profiles.work.executablePath "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

Or set it in config, per platform:

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",
  },
}

Per-profile executablePath only affects local managed profiles that OpenClaw launches. existing-session profiles attach to an already-running browser instead, and remote CDP profiles use the browser behind cdpUrl.

Local vs remote control

  • Local control (default): The Gateway activates the loopback control service and can start a local browser.
  • Remote control (node host): Deploy a node host on the machine with the browser; the Gateway proxies browser commands to it.
  • Remote CDP: Configure browser.profiles.<name>.cdpUrl (or browser.cdpUrl) to connect to a remote Chromium-based browser. In this scenario, OpenClaw will not start a local browser.
  • For externally managed CDP services on loopback (such as Browserless in Docker published to 127.0.0.1), also set attachOnly: true. A loopback CDP without attachOnly is considered a local OpenClaw-managed browser profile.
  • headless applies only to local managed profiles that OpenClaw starts. It does not restart or modify existing-session or remote CDP browsers.
  • executablePath follows the same rule for local managed profiles. Changing it on a running local managed profile flags that profile for restart/reconcile so the next launch uses the new binary.

Stopping behavior varies by profile mode:

  • local managed profiles: openclaw browser stop terminates the browser process that OpenClaw started
  • attach-only and remote CDP profiles: openclaw browser stop ends the active control session and releases Playwright/CDP emulation overrides (viewport, color scheme, locale, timezone, offline mode, and similar state), even though OpenClaw did not start any browser process

Remote CDP URLs can include authentication:

  • Query tokens (for example, https://provider.example?token=<token>)
  • HTTP Basic auth (for example, https://user:pass@provider.example)

OpenClaw preserves the authentication when calling /json/* endpoints and when connecting to the CDP WebSocket. Prefer environment variables or secrets managers for tokens instead of committing them to config files.

Node browser proxy (zero-config default)

If you run a node host on the machine that has your browser, OpenClaw can automatically route browser tool calls to that node without any extra browser configuration. This is the default path for remote gateways.

Notes:

  • The node host exposes its local browser control server through a proxy command.
  • Profiles come from the node's own browser.profiles configuration (same as local).
  • The proxy command never allows persistent profile mutations (create-profile, delete-profile, reset-profile) regardless of allowProfiles; apply those changes directly on the node.
  • nodeHost.browserProxy.allowProfiles is optional. Leave it empty for the legacy/default behavior: all configured profiles remain reachable through the proxy.
  • If you set nodeHost.browserProxy.allowProfiles, OpenClaw treats it as a least-privilege boundary limiting which profile names the proxy will target.
  • Disable if you do not want it:
    • On the node: nodeHost.browserProxy.enabled=false
    • On the gateway: gateway.nodes.browser.mode="off" (also accepts "auto" to pick a single connected browser node, or "manual" to require an explicit node parameter)

Browserless (hosted remote CDP)

Browserless is a hosted Chromium service that exposes 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 documentation.

Example:

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

Notes:

  • Replace <BROWSERLESS_API_KEY> with your actual Browserless token.
  • Choose the region endpoint that matches your Browserless account (refer to their documentation).
  • 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.

Browserless Docker on the same host

When Browserless is self-hosted in Docker and OpenClaw runs on the host, treat Browserless as an externally managed CDP service:

{
  browser: {
    enabled: true,
    defaultProfile: "browserless",
    profiles: {
      browserless: {
        cdpUrl: "ws://127.0.0.1:3000",
        attachOnly: true,
        color: "#00AA00",
      },
    },
  },
}

The address in browser.profiles.browserless.cdpUrl must be reachable from the OpenClaw process. Browserless must also advertise a matching reachable endpoint; set Browserless EXTERNAL to that same public-to-OpenClaw WebSocket base, such as ws://127.0.0.1:3000, ws://browserless:3000, or a stable private Docker network address. If /json/version returns webSocketDebuggerUrl pointing at an address OpenClaw cannot reach, CDP HTTP can appear healthy while the WebSocket attach still fails.

Do not leave attachOnly unset for a loopback Browserless profile. Without attachOnly, OpenClaw treats the loopback port as a local managed browser profile and may report that the port is in use but not owned by OpenClaw.

Direct WebSocket CDP providers

Some hosted browser services expose a direct WebSocket endpoint instead of the standard HTTP-based CDP discovery (/json/version). OpenClaw accepts three CDP URL formats and selects the correct connection strategy automatically:

  • HTTP(S) discovery - http://host[:port] or https://host[:port]. OpenClaw calls /json/version to discover the WebSocket debugger URL, then connects. No WebSocket fallback.
  • Direct WebSocket endpoints - ws://host[:port]/devtools/<kind>/<id> or wss://... with a /devtools/browser|page|worker|shared_worker|service_worker/<id> path. OpenClaw connects directly via a WebSocket handshake and skips /json/version entirely.
  • Bare WebSocket roots - ws://host[:port] or wss://host[:port] with no /devtools/... path (for example Browserless, Browserbase). OpenClaw tries HTTP /json/version discovery first (normalising the scheme to http/https); if discovery returns a webSocketDebuggerUrl it is used, otherwise OpenClaw falls back to a direct WebSocket handshake at the bare root. If the advertised WebSocket endpoint rejects the CDP handshake but the configured bare root accepts it, OpenClaw falls back to that root as well. This lets a bare ws:// pointed at a local Chrome still connect, since Chrome only accepts WebSocket upgrades on the specific per-target path from /json/version, while hosted providers can still use their root WebSocket endpoint when their discovery endpoint advertises a short-lived URL that is not suitable for Playwright CDP.

openclaw browser doctor applies the same discovery-first, WebSocket-fallback logic used for runtime attach, so a bare-root URL that connects successfully is not flagged as unreachable by diagnostics.

Browserbase

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

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

Notes:

  • Register and retrieve your API Key from the Overview dashboard.
  • Swap <BROWSERBASE_API_KEY> with your actual Browserbase API key.
  • Browserbase automatically spawns a browser session upon WebSocket connection, so no manual session creation is required.
  • Check pricing for current free-tier limits and paid plans.
  • Consult the Browserbase documentation for the full API reference, SDK guides, and integration examples.

Notte

Notte is a cloud service for running headless browsers. It provides built-in stealth, residential proxies, and a CDP-native WebSocket gateway.

{
  browser: {
    enabled: true,
    defaultProfile: "notte",
    profiles: {
      notte: {
        cdpUrl: "wss://us-prod.notte.cc/sessions/connect?token=<NOTTE_API_KEY>",
        color: "#7C3AED",
      },
    },
  },
}

Notes:

  • Register and copy your API Key from the console settings page.
  • Replace <NOTTE_API_KEY> with your actual Notte API key.
  • Notte automatically creates a browser session on WebSocket connect, so no manual session creation is needed. The session is terminated when the WebSocket disconnects.
  • See pricing for current free-tier limits and paid plans.
  • Refer to the Notte docs for the full API reference, SDK guides, and integration examples.

Security

Key ideas:

  • Browser control operates only on loopback; access is routed through the Gateway's authentication or node pairing.
  • The standalone loopback browser HTTP API relies exclusively on shared-secret authentication: gateway token bearer auth, x-openclaw-password, or HTTP Basic auth using 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 without any shared-secret auth configured, OpenClaw generates and stores a browser-control credential at startup: a token when gateway.auth.mode is none, or a password when it is trusted-proxy (persisted via gateway.auth.password so out-of-process loopback clients can resolve it). Auto-generation is skipped when an explicit string credential is already configured for that mode, or when gateway.auth.mode is password.
  • Set gateway.auth.token, gateway.auth.password, OPENCLAW_GATEWAY_TOKEN, or OPENCLAW_GATEWAY_PASSWORD explicitly if you want a stable secret you control rather than the auto-generated one.

Remote CDP tips:

  • Favor encrypted endpoints (HTTPS or WSS) and short-lived tokens whenever possible.
  • Do not embed long-lived tokens directly in configuration files.
  • Keep the Gateway and any node hosts on a private network (Tailscale); avoid exposing them publicly.
  • Treat remote CDP URLs and tokens as secrets; use environment variables or a secrets manager.

Profiles (multi-browser)

OpenClaw supports multiple named profiles (routing configurations). Profiles can be:

  • openclaw-managed: a dedicated Chromium-based browser instance with its own user data directory and CDP port
  • remote: an explicit CDP URL pointing to a Chromium-based browser running elsewhere
  • existing session: your current Chrome profile, accessed via Chrome DevTools MCP auto-connect

Defaults:

  • The openclaw profile is created automatically if it does not exist.
  • The user profile is built-in for Chrome MCP existing-session attachment.
  • Existing-session profiles are opt-in beyond user; create them with --driver existing-session.
  • Local CDP ports are assigned from the 18800-18899 range by default.
  • Deleting a profile moves its local data directory to the Trash.

All control endpoints accept ?profile=<name>; the CLI uses --browser-profile.

Existing session via Chrome DevTools MCP

OpenClaw can also connect to an already 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.

Official background and setup references:

Built-in profile: user. Create your own custom existing-session profile if you want a different name, color, or browser data directory.

By default, 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. ~ expands to your OS home directory:

{
  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.

Common inspect pages:

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

Live attach smoke test:

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

What success looks like:

  • status shows driver: existing-session
  • status shows transport: chrome-mcp
  • status shows running: true
  • tabs lists your already-open browser tabs
  • snapshot returns refs from the selected live tab

What to check if attach does not work:

  • 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
  • if Chrome was started with an explicit --remote-debugging-port, set browser.profiles.<name>.cdpUrl to that DevTools endpoint instead of relying on Chrome MCP auto-connect
  • openclaw doctor migrates old extension-based browser config and checks that Chrome is installed locally for default auto-connect profiles, but it cannot enable browser-side remote debugging for you

Agent usage:

  • profile="user" is the right choice when you need the browser state the user is currently logged into.
  • If you are working with a custom existing-session profile, provide the exact profile name.
  • Pick this mode only when the user is present to approve the attach dialog.
  • Either the Gateway or the node host can start npx chrome-devtools-mcp@latest --autoConnect.

Remarks:

  • This method carries more risk than the isolated openclaw profile, since it can operate inside your authenticated browser session.
  • OpenClaw does not start the browser for this driver; it only connects to an existing one.
  • OpenClaw relies on the official Chrome DevTools MCP --autoConnect protocol here. When userDataDir is configured, it is forwarded to point at that user data directory.
  • An existing-session profile can attach on the chosen host or through a linked browser node. If Chrome runs on a different machine and no browser node is linked, fall back to remote CDP or a node host.
  • Chrome MCP targets and snapshot references are confined to a single MCP subprocess. After that process is restarted, execute browser tabs again, explicitly pick a new target before doing target-specific work, and capture a fresh snapshot before referencing anything. Each reference is only valid for its target and the most recent snapshot. Old aliases do not carry over to a replacement tab, even if its URL is identical.
  • Currently, Chrome DevTools MCP directs page tools using a numeric page ID local to the process. Process-scoped handles prevent reuse after a subprocess replacement, but swapping the browser context within the same process between consecutive tool calls can still redirect an action. Full atomic routing depends on upstream page-tool support for stable target identifiers.

Custom Chrome MCP launch

Replace the default spawned Chrome DevTools MCP server per profile when the standard npx chrome-devtools-mcp@latest workflow does not fit your needs (offline hosts, pinned versions, vendored binaries):

FieldWhat it does
mcpCommandBinary to launch instead of npx. Used as given; absolute paths are respected.
mcpArgsArgument list passed directly to mcpCommand. Replaces the default chrome-devtools-mcp@latest --autoConnect arguments.

When cdpUrl is defined on an existing-session profile, OpenClaw omits --autoConnect and automatically passes the endpoint to Chrome MCP:

  • http(s)://...--browserUrl <url> (DevTools HTTP discovery endpoint).
  • ws(s)://...--wsEndpoint <url> (direct CDP WebSocket).

Endpoint flags and userDataDir are mutually exclusive: if cdpUrl is set, userDataDir is ignored when launching Chrome MCP, because Chrome MCP connects to the already running browser via the endpoint instead of opening a profile directory.

Existing-session feature limitations

Compared to the managed openclaw profile, existing-session drivers face more restrictions:

  • Screenshots - Full page captures and --ref element captures are supported; CSS --element selectors are not. You do not need Playwright for page or ref-based element screenshots. (--full-page cannot be used together with --ref or --element on any profile, including existing-session ones.)
  • Actions - click, type, hover, scrollIntoView, drag, and select require snapshot references (CSS selectors are not accepted). click-coords clicks at visible viewport coordinates and does not need a snapshot ref. click only supports the left mouse button (no button overrides or modifier keys). type does not support slowly=true; instead use fill or press. press does not support delayMs. type, hover, scrollIntoView, drag, select, and fill do not allow per-call timeoutMs overrides; evaluate does. select accepts a single value. batch is unsupported; send actions one at a time.
  • Wait / upload / dialog - wait --url supports exact, substring, and glob patterns (same as the managed path); wait --load networkidle is unsupported on existing-session profiles (it works on managed and raw/remote CDP profiles). Upload hooks need ref or inputRef, one file per call, with no CSS element. Dialog hooks do not support timeout overrides or dialogId.
  • Dialog visibility - Managed browser action responses include blockedByDialog and browserState.dialogs.pending when an action opens a modal dialog; snapshots also reflect pending dialog state. Respond with browser dialog --accept/--dismiss --dialog-id <id> while a dialog is pending. Dialogs handled outside OpenClaw appear under browserState.dialogs.recent.
  • Managed-only features - PDF export, download interception, and responsebody still require the managed browser path.

Isolation guarantees

  • Dedicated user data dir: your personal browser profile is never touched.
  • Dedicated ports: 9222 is avoided to prevent conflicts with development workflows.
  • Deterministic tab control: tabs returns suggestedTargetId first, then stable tabId handles such as t1, optional labels, and the raw targetId. Agents should reuse suggestedTargetId; raw ids remain available for debugging and compatibility.

Browser selection

When launching locally, OpenClaw picks the first available:

  1. Chrome
  2. Brave
  3. Edge
  4. Chromium
  5. Chrome Canary

You can override with browser.executablePath.

Platforms:

  • macOS: checks /Applications and ~/Applications.
  • Linux: checks common Chrome/Brave/Edge/Chromium locations under /usr/bin, /snap/bin, /opt/google, /opt/brave.com, /usr/lib/chromium, and /usr/lib/chromium-browser, plus Playwright-managed Chromium under PLAYWRIGHT_BROWSERS_PATH or ~/.cache/ms-playwright.
  • Windows: checks common install locations.

Control API (optional)

For debugging and scripting, the Gateway offers a small loopback-only HTTP control API along with a corresponding openclaw browser command-line tool (snapshots, references, wait power-ups, JSON output, debug workflows). Consult the Browser control API for complete documentation.

Troubleshooting

For Linux-specific problems (particularly with snap Chromium), refer to Browser troubleshooting.

For configurations involving a WSL2 Gateway paired with Windows Chrome, see WSL2 + Windows + remote Chrome CDP troubleshooting.

CDP startup failure vs navigation SSRF block

These represent distinct failure categories, each pointing to separate code paths.

  • CDP startup or readiness failure indicates OpenClaw cannot verify the browser control plane is operational.
  • Navigation SSRF block means the browser control plane is functioning, but a page navigation request has been denied by policy.

Typical examples:

  • CDP startup or readiness failure:
    • Chrome CDP websocket for profile "openclaw" is not reachable after start
    • Remote CDP for profile "<name>" is not reachable at <cdpUrl>
    • Port <port> is in use for profile "<name>" but not by openclaw when a loopback external CDP service is configured without attachOnly: true
  • Navigation SSRF block:
    • open, navigate, snapshot, or tab-opening operations fail with a browser or network policy error while start and tabs remain functional

Use this minimal procedure to distinguish between them:

openclaw browser --browser-profile openclaw start
openclaw browser --browser-profile openclaw tabs
openclaw browser --browser-profile openclaw open https://example.com

Interpreting the results:

  • When start fails with not reachable after start, start by troubleshooting CDP readiness.
  • If start succeeds but tabs fails, the control plane is still not healthy. Treat this as a CDP connectivity issue, not a page navigation one.
  • When start and tabs succeed but open or navigate fails, the browser control plane is operational and the problem lies in navigation policy or the target page.
  • If start, tabs, and open all succeed, the basic managed-browser control path is healthy.

Important behavioral notes:

  • Even without configuring browser.ssrfPolicy, the browser configuration defaults to a fail-closed SSRF policy object.
  • For the local loopback openclaw managed profile, CDP health checks deliberately skip browser SSRF reachability enforcement for OpenClaw's own local control plane.
  • Navigation protection operates independently. A successful start or tabs result does not guarantee that a subsequent open or navigate target will be permitted.

Security recommendations:

  • Do not relax browser SSRF policy by default.
  • Favor narrow host exceptions such as hostnameAllowlist or allowedHostnames over broad private-network access.
  • Use dangerouslyAllowPrivateNetwork: true only in intentionally trusted environments where private-network browser access is required and has been reviewed.

Agent tools + how control works

The agent receives one tool for browser automation:

  • browser - doctor/status/start/stop/tabs/open/focus/close/snapshot/screenshot/navigate/act

How it maps:

  • browser snapshot provides a stable UI tree (AI or ARIA).
  • browser act uses snapshot ref identifiers to click, type, drag, or select.
  • browser screenshot captures pixel data (full page, element, or labeled references).
  • browser doctor verifies Gateway, plugin, profile, browser, and tab readiness.
  • browser accepts:
    • profile to select a named browser profile (openclaw, chrome, or remote CDP).
    • target (sandbox | host | node) to specify the browser's location.
    • 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.
    • When a browser-capable node is connected, the tool may auto-route to it unless you pin target="host" or target="node".

This approach keeps the agent deterministic and avoids fragile selectors.

  • Tools Overview - a complete list of available agent tools
  • Sandboxing - browser control within sandboxed environments
  • Security - risks and hardening for browser control