OpenClaw Managed Browser: Dedicated Agent Profile

Learn how OpenClaw launches a dedicated browser profile for agent-controlled browsing, including tab management, page interaction, and downloads. This page is for developers and users who need isolated 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 is able to launch its own dedicated Chrome/Brave/Edge/Chromium profile under agent control. This runs through a compact local control service inside the Gateway, restricted to loopback, and stays separate from your everyday browser.

  • Treat this as a browser reserved for the agent alone. The openclaw profile never comes into contact with your personal browsing profile.
  • Within this isolated lane, the agent can open tabs, read page content, perform clicks, and enter text.
  • The built-in user profile, by contrast, connects to your actual signed-in Chrome session through Chrome DevTools MCP.

What you get

  • A dedicated profile named openclaw (defaulting to an orange accent).
  • Predictable tab management (list/open/focus/close).
  • Agent operations (click/type/drag/select), page snapshots, screenshots, and PDF generation.
  • Answering questions based on readable page text without sending back a complete snapshot.
  • Playwright-backed profiles record direct attachment navigations under the managed downloads directory and return { url, suggestedFilename, path } metadata once final-URL policy validation passes.
  • When an action from a Playwright-backed agent immediately starts one or more downloads, it returns a downloads array carrying the same managed metadata.
  • A bundled browser-automation skill teaches agents the snapshot, stable-tab, stale-ref, and manual-blocker recovery loop whenever the browser plugin is active.
  • Optional support for multiple profiles (openclaw, work, remote, and so on).

This browser is not meant for daily use. It provides a safe, separated surface for agent automation and verification tasks.

On macOS, you can explicitly pull cookies from a Chrome-family system profile into a separate managed profile. The managed browser keeps its own user data directory; only the chosen cookies get copied, while local storage and IndexedDB remain untouched. Refer to Profiles or the openclaw browser CLI reference for import commands and their 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

When the plugin or browser.enabled is switched off, that counts as "Browser disabled"; check Configuration and Plugin control for details.

If openclaw browser is absent altogether, or the agent indicates the browser tool is not reachable, head to Missing browser command or tool.

Plugin control

The default browser tool ships as a bundled plugin. To swap in a different plugin that registers the same browser tool name, disable it first:

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

For defaults to work, both plugins.entries.browser.enabled and browser.enabled=true are required. Turning off only the plugin removes the openclaw browser CLI, the browser.request gateway method, the agent tool, and the control service as a single unit; your browser.* configuration remains intact for a replacement.

After changing browser config, restart the Gateway so the plugin can re-register its service.

Agent guidance

Tool-profile note: tools.profile: "coding" comes with web_search and web_fetch, but the full browser tool is not part of it. To give the agent or a spawned sub-agent browser automation capabilities, add browser at the profile stage:

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

For a single agent, go with agents.entries.*.tools.alsoAllow: ["browser"]. Relying on tools.subagents.tools.allow: ["browser"] alone falls short, since sub-agent policy gets applied only after profile filtering.

The browser plugin provides agent guidance at two levels:

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

When the plugin is enabled, its bundled skills show up in the agent's available skills list. The full skill instructions load on demand, so routine turns avoid paying the entire token cost.

For page text, opt for a selector-scoped snapshot or act:evaluate that returns only the relevant text or structured data, then let the active agent model reason over that bounded result. Use efficient snapshots for controls and action discovery; they deliberately leave out most non-interactive prose.

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 typical culprit is a plugins.allow list that leaves out browser and no root browser config block exists. Add it:

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

An explicit root browser block (any key under browser, like browser.enabled=true or browser.profiles.<name>) turns on the bundled browser plugin even under a restrictive plugins.allow, mirroring bundled channel config behavior. plugins.entries.browser.enabled=true and tools.alsoAllow: ["browser"] by themselves do not replace allowlist membership. Removing plugins.allow entirely also brings back the default.

Profiles: openclaw, user, chrome

  • openclaw: managed, isolated browser (no extension needed).
  • user: built-in Chrome DevTools MCP attach profile for your real signed-in Chrome session. The first time OpenClaw attaches, Chrome displays a blocking "Allow remote debugging?" prompt, so someone needs to be present 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:

  • By default, the isolated openclaw browser is used.
  • When existing logged-in sessions matter and the user is away from the computer (Telegram, WhatsApp, etc.), choose profile="chrome" (extension).
  • When existing logged-in sessions matter and the user is at the computer to accept the attach prompt, choose profile="user" (Chrome MCP).
  • profile is the explicit override for forcing a particular browser mode.

To make managed mode the default, set browser.defaultProfile: "openclaw".

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
      // allowedHostnames: ["localhost"],
      // allowRfc2544BenchmarkRange: true, // trusted fake-IP proxy range
      // allowIpv6UniqueLocalRange: true, // trusted fake-IP proxy IPv6 range
    },
    // 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" },
    },
  },
}

When a caller does not pass an explicit snapshotFormat or mode, the default snapshot extraction mode is changed by browser.snapshotDefaults.mode: "efficient"; per-call snapshot options are documented in the Browser control API.

On drivers with stable document identity, repeated AI or role snapshots of the same tab, document, and option family mark newly appeared ref-bearing elements with [new]. The first snapshot, and the first snapshot after navigation, establishes an unmarked baseline. Deltas are omitted from existing-session snapshots.

Tab cleanup ownership

Session tab cleanup only affects tabs created by the OpenClaw browser tool with action: "open". OpenClaw does not adopt tabs that were already open, opened by the user, or otherwise have unknown ownership. Periodic idle and cap sweeps for primary sessions are governed by the browser.tabCleanup block; disabling it does not disable explicit session lifecycle cleanup.

For host-local opens, ownership with a stable native CDP target and browser identity is stored in the shared SQLite state. Those records survive a Gateway restart and remain eligible for /new and other session lifecycle cleanup; session lifecycle cleanup includes subagent, cron, and ACP session endings. Records whose tool-facing target is the native CDP target also remain eligible for idle and per-session cap sweeps after restart. Chrome MCP target handles are process-local, so cold existing-session records wait for lifecycle cleanup rather than risking an idle sweep against activity that cannot be attributed safely after restart. This durable path can cover OpenClaw-managed profiles, regular remote CDP profiles, and existing-session profiles with an explicit cdpUrl, provided OpenClaw can resolve both the native target and a stable browser identity. Before closing a durable record, OpenClaw verifies 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 running, 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 is best-effort, 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 stays 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. 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

  • 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.allowedHostnames grants exact hosts while the rest of the private network remains blocked.
  • browser.ssrfPolicy.allowRfc2544BenchmarkRange and browser.ssrfPolicy.allowIpv6UniqueLocalRange narrowly allow trusted fake-IP proxy ranges.
  • browser.ssrfPolicy.allowPrivateNetwork remains supported as a legacy alias.

Profile behavior

  • Setting attachOnly: true means a local browser is never started; OpenClaw only connects when one is already active.
  • headless works either globally or for an individual local managed profile. A profile-level setting takes precedence over browser.headless, letting one locally launched profile run headless while another stays visible.
  • POST /start?headless=true and openclaw browser start --headless ask for a single headless launch of local managed profiles without touching browser.headless or profile configuration. Existing-session, attach-only, and remote CDP profiles turn down this override, since OpenClaw does not start those browser processes.
  • On Linux machines lacking DISPLAY or WAYLAND_DISPLAY, local managed profiles fall back to headless on their own when neither the environment nor profile/global config picks headed mode explicitly. Use the clear browser-level form openclaw browser --json status; a trailing openclaw browser status --json is accepted as well, 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 local managed launches in the current process. OPENCLAW_BROWSER_HEADLESS=0 forces headed mode for normal starts and gives a useful error on Linux hosts with no display server; an explicit start --headless request still takes priority for that single launch.
  • The browser-control route and programmatic client keep the human-readable error from the no-display error and also expose the stable reason no_display_for_headed_profile. Its details hold only profile, requestedHeadless, headlessSource, and displayPresent, so API clients can pick the right fix without matching message text.
  • For a running local managed profile, status and doctor query Chrome's browser-level CDP endpoint for renderer, backend, device/driver, feature status, driver workarounds, and accelerated video capabilities. That result is cached for the browser process and shown in full by openclaw browser --json status. A passive status call does not start Chrome. Existing-session, extension, remote CDP, and sandbox browsers stay separate and are not checked through this managed-host path.
  • Headless managed Chrome still relies on the conservative --disable-gpu default. The diagnostics do not enable acceleration, add a global acceleration setting, or give sandbox browser device access.
  • executablePath can be set globally or per local managed profile. Profile-level values override browser.executablePath, so different managed profiles can launch different Chromium-based browsers. Both forms accept ~ for your OS home directory.
  • color (top-level and per-profile) colors the browser UI so you can tell which profile is active.
  • Default profile is openclaw (managed standalone). Use defaultProfile: "user" to opt into the signed-in user browser.
  • Auto-detect order: system default browser if Chromium-based; otherwise Chrome, Brave, Edge, Chromium, Chrome Canary.
  • driver: "existing-session" uses 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" drives 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 with nobody 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 OS 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 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.
  • Remote CDP: set browser.profiles.<name>.cdpUrl (or browser.cdpUrl) to attach to a remote Chromium-based browser. In this case, OpenClaw will not launch a local browser.
  • For externally managed CDP services on loopback (for example Browserless in Docker published to 127.0.0.1), also set attachOnly: true. Loopback CDP without attachOnly is treated as a local OpenClaw-managed browser profile.
  • headless only affects local managed profiles that OpenClaw launches. It does not restart or change existing-session or remote CDP browsers.
  • executablePath follows the same local managed profile rule. Changing it on a running local managed profile marks that profile for restart/reconcile so the next launch uses the new binary.

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

Remote CDP URLs can include auth:

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

OpenClaw preserves the auth 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 auto-route browser tool calls to that node without any extra browser config. This is the default path for remote gateways.

Notes:

  • 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).
  • The proxy command never allows persistent profile mutations (create-profile, delete-profile, reset-profile) regardless of allowProfiles; make those changes on the node directly.
  • 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 don't 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 param)

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

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 real Browserless token.
  • Choose the region endpoint that matches your Browserless account (see their docs).
  • 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 look 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 rather than the standard HTTP-based CDP discovery (/json/version). OpenClaw accepts three CDP URL shapes and picks the right 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 (e.g. 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 approach as runtime attach, so a bare-root URL that establishes a connection will not be flagged as unreachable by diagnostics.

Browserbase

Browserbase offers a cloud service for operating headless browsers, featuring integrated CAPTCHA solving, stealth capabilities, 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 initiates a browser session automatically upon WebSocket connection, eliminating the need for manual session setup.
  • Check pricing for current free-tier allowances and subscription options.
  • Consult the Browserbase docs for the complete API reference, SDK guides, and integration examples.

Notte

Notte provides a cloud platform for headless browser execution, with built-in stealth features, 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:

  • Sign up and copy your API Key from the console settings page.
  • Replace <NOTTE_API_KEY> with your real Notte API key.
  • Notte creates a browser session automatically on WebSocket connect, so manual session creation is unnecessary. The session terminates when the WebSocket closes.
  • 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

Core concepts:

  • Browser control is restricted to loopback; access is mediated by the Gateway's auth or node pairing.
  • The standalone loopback browser HTTP API relies exclusively on shared-secret auth: 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" are not accepted for authenticating this standalone loopback browser API.
  • When browser control is active and no shared-secret auth is set, OpenClaw generates and stores a browser-control credential at startup: a token if gateway.auth.mode equals none, or a password if it is trusted-proxy (saved via gateway.auth.password so out-of-process loopback clients can retrieve it). This auto-generation is bypassed when an explicit string credential already exists for that mode, or when gateway.auth.mode is set to password.
  • Set gateway.auth.token, gateway.auth.password, OPENCLAW_GATEWAY_TOKEN, or OPENCLAW_GATEWAY_PASSWORD explicitly if you prefer a stable secret you manage rather than the auto-generated one.

Remote CDP guidance:

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

Profiles (multi-browser)

OpenClaw supports multiple named profiles (routing configs). Profiles fall into these categories:

  • 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 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 attach.
  • Beyond user, existing-session profiles are opt-in; create them with --driver existing-session.
  • Local CDP ports default to the 18800-18899 range.
  • Removing a profile sends its local data directory to Trash.

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

Existing session via Chrome DevTools MCP

OpenClaw can also connect to a running Chromium-based browser profile via the official Chrome DevTools MCP server. This reuses the tabs and login state already present in that browser profile.

Official background and setup references:

Built-in profile: user. Create your own custom existing-session profile if you need 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. Navigate to that browser's inspect page for remote debugging.
  2. Turn on remote debugging.
  3. Leave the browser running and accept 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

Signs of success:

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

Troubleshooting steps if attach fails:

  • the target Chromium-based browser is version 144+
  • remote debugging is enabled on that browser's inspect page
  • the browser appeared and you approved the attach consent prompt
  • if Chrome was launched 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 verifies that Chrome is installed locally for default auto-connect profiles, but it cannot enable browser-side remote debugging for you

Agent use:

  • Pick profile="user" whenever the user's signed-in browser state is what you need.
  • When relying on a custom existing-session profile, hand over that profile's explicit name.
  • Reserve this mode for moments when the user is present to approve the attach prompt.
  • Both the Gateway and the node host are able to start npx chrome-devtools-mcp@latest --autoConnect.

Notes:

  • This route carries more risk than the isolated openclaw profile, since it can operate inside your signed-in browser session.
  • For this driver, OpenClaw never launches the browser; it only connects to one.
  • OpenClaw follows the official Chrome DevTools MCP --autoConnect procedure here. If userDataDir is configured, it is forwarded to point at that user data directory.
  • Existing-session can connect either on the chosen host or through a linked browser node. When Chrome runs elsewhere and no browser node is linked, fall back to remote CDP or a node host.
  • Chrome MCP targets and snapshot refs stay confined to a single MCP subprocess. After that process is restarted, rerun browser tabs, explicitly choose a new target before any target-specific operation, and capture a fresh snapshot prior to using refs. A ref holds only for its own target and the latest snapshot. Old aliases never carry over to a replacement tab, even if the URL matches.
  • Chrome DevTools MCP currently dispatches page tools using a numeric page ID local to the process. Process-scoped handles block reuse across subprocess replacement, yet an in-process browser-context swap between consecutive tool calls can still redirect an action. Fully atomic routing depends on upstream page-tool support for stable target IDs.

Custom Chrome MCP launch

Override the spawned Chrome DevTools MCP server on a per-profile basis when the default npx chrome-devtools-mcp@latest flow does not fit (offline hosts, pinned versions, vendored binaries):

FieldWhat it does
mcpCommandExecutable to spawn instead of npx. Resolved as-is; absolute paths are honored.
mcpArgsArgument array passed verbatim to mcpCommand. Replaces the default chrome-devtools-mcp@latest --autoConnect arguments.

When cdpUrl is set on an existing-session profile, OpenClaw bypasses --autoConnect and hands the endpoint to Chrome MCP on its own:

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

Endpoint flags and userDataDir are mutually exclusive: once cdpUrl is set, userDataDir gets ignored for Chrome MCP launch, because Chrome MCP connects to the browser already running behind the endpoint instead of opening a profile directory.

Existing-session feature limitations

Existing-session drivers face tighter limits than the managed openclaw profile:

  • Screenshots - full-page captures and element-level captures via --ref are supported; CSS --element selectors are not. Neither page screenshots nor ref-based element screenshots require Playwright. (On any profile, including existing-session ones, --full-page cannot be paired with --ref or --element.)
  • Actions - click, type, hover, scrollIntoView, drag, and select all depend on snapshot refs; CSS selectors won't work for them. click-coords operates on visible viewport coordinates and skips the snapshot ref requirement. click only handles the left button, with no modifier keys or button overrides. For type, slowly=true is unsupported; turn to fill or press instead. press lacks support for delayMs. While type, hover, scrollIntoView, drag, select, and fill reject per-call timeoutMs overrides, evaluate accepts them. select takes just one value. Since batch is unavailable, dispatch actions one by one.
  • Wait / upload / dialog - wait --url handles exact matches, substrings, and glob patterns, mirroring the managed path; existing-session profiles don't support wait --load networkidle, though managed and raw/remote CDP profiles do. Upload hooks need ref or inputRef, process a single file at a time, and ignore CSS element. Dialog hooks can't accept timeout overrides or dialogId.
  • Dialog visibility - When an action triggers a modal dialog, managed browser action responses carry blockedByDialog and browserState.dialogs.pending; snapshots also reflect the pending dialog state. While a dialog is waiting, reply with browser dialog --accept/--dismiss --dialog-id <id>. Dialogs that OpenClaw doesn't handle show up under browserState.dialogs.recent.
  • Managed-only features - PDF export, download interception, and responsebody continue to require the managed browser route.

Isolation guarantees

  • Dedicated user data dir: your personal browser profile stays untouched.
  • Dedicated ports: 9222 is avoided to keep dev workflows collision-free.
  • Deterministic tab control: tabs gives suggestedTargetId first, followed by stable tabId handles like t1, optional labels, and the raw targetId. Agents should stick with suggestedTargetId; raw ids stay available for debugging and compatibility.

Browser selection

For local launches, OpenClaw selects the first free option from:

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

browser.executablePath lets you override this.

Platforms:

  • macOS: looks at /Applications and ~/Applications.
  • Linux: scans standard Chrome/Brave/Edge/Chromium paths 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: scans standard install directories.

Control API (optional)

For scripting and debugging, the Gateway exposes a small loopback-only HTTP control API plus a matching openclaw browser CLI (snapshots, refs, wait power-ups, JSON output, debug workflows). See Browser control API for the full reference.

Troubleshooting

For Linux-specific issues (especially snap Chromium), see Browser troubleshooting.

For WSL2 Gateway + Windows Chrome split-host setups, see WSL2 + Windows + remote Chrome CDP troubleshooting.

CDP startup failure vs navigation SSRF block

These are different failure classes and they point to different code paths.

  • CDP startup or readiness failure means OpenClaw cannot confirm that the browser control plane is healthy.
  • Navigation SSRF block means the browser control plane is healthy, but a page navigation target is rejected by policy.

Common 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 flows fail with a browser/network policy error while start and tabs still work

Use this minimal sequence to separate the two:

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

How to read the results:

  • If start fails with not reachable after start, troubleshoot CDP readiness first.
  • If start succeeds but tabs fails, the control plane is still unhealthy. Treat this as a CDP reachability problem, not a page-navigation problem.
  • If start and tabs succeed but open or navigate fails, the browser control plane is up and the failure is in navigation policy or the target page.
  • If start, tabs, and open all succeed, the basic managed-browser control path is healthy.

Important behavior details:

  • Browser config defaults to a fail-closed SSRF policy object even when you do not configure browser.ssrfPolicy.
  • For the local loopback openclaw managed profile, CDP health checks intentionally skip browser SSRF reachability enforcement for OpenClaw's own local control plane.
  • Navigation protection is separate. A successful start or tabs result does not mean a later open or navigate target is allowed.

Security guidance:

  • Do not relax browser SSRF policy by default.
  • Prefer 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 reviewed.

Agent tools + how control works

The agent gets one tool for browser automation:

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

How it maps:

  • browser snapshot returns a stable UI tree (AI or ARIA).
  • browser navigate also returns the loaded page's snapshot inline (efficient interactive tier, so the payload stays compact and bounded), so the agent does not need a follow-up snapshot call. Batch act results that report a cross-document navigation include the same fresh page state. Navigations that resolve to a download skip it.
  • browser act uses the snapshot ref IDs to click/type/drag/select.
  • browser screenshot captures pixels (full page, element, or labeled refs).
  • browser doctor checks Gateway, plugin, profile, browser, and tab readiness.
  • browser accepts:
    • 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, target: "host" requires agents.defaults.sandbox.browser.allowHostControl=true.
    • If target is omitted: sandboxed sessions default to sandbox, 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 keeps the agent deterministic and avoids brittle selectors.

  • Tools Overview - a complete list of every tool the agent can use
  • Sandboxing - managing browser control within sandboxed setups
  • Security - threats tied to browser control and how to mitigate them
6,191 words · updated Aug 7, 2026