Skip to content
Guides

Failed to start Chrome CDP on port 18800

Why snap Chromium breaks OpenClaw browser control on Linux

7 min read

You ask the agent to open a page and the tool call comes back with one line of JSON: Failed to start Chrome CDP on port 18800 for profile openclaw. Nothing in that message says which part failed, and on a headless Linux box the browser never appears at all. The usual cause is not OpenClaw, it is the browser that apt installed for you.

Four error strings, four different causes

  • Failed to start Chrome CDP on port 18800 for profile openclaw is the managed profile failing to come up on its debugging port. On Ubuntu the usual reason is that the Chromium on the box is a snap wrapper rather than a real browser binary.
  • The profile appears to be in use by another Chromium process points at stale Singleton lock files in the managed profile directory. OpenClaw removes those locks and retries once when the lock names a dead process on the current host, but locks naming another hostname are preserved until you confirm the profile is no longer in use, including after a machine rename.
  • Missing X server or $DISPLAY means a visible browser was explicitly requested on a host with no desktop session. Local managed profiles already fall back to headless on Linux when both DISPLAY and WAYLAND_DISPLAY are unset, so seeing this error means something forced a headed browser: OPENCLAW_BROWSER_HEADLESS=0, browser.headless set to false, or the same key on a single profile.
  • The error Port N is in use for profile NAME but not by openclaw shows up when a loopback external CDP service is already configured and attachOnly is still false. The fix is to stop asking OpenClaw to launch its own browser, which is the attach-only route below.
Snap's AppArmor confinement interferes with how OpenClaw spawns and monitors the browser process.

Why apt install chromium is the root cause

On Ubuntu and most Linux distributions, apt install chromium does not give you a browser. The package resolves to chromium-browser, apt prints a note that it selected chromium-browser instead of chromium, and what lands on disk is a snap wrapper. That matters, because when OpenClaw launches a browser locally it takes the first one it finds in the order Chrome, Brave, Edge, Chromium, Chrome Canary, and its Linux search path covers /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. On a fresh server where the snap is the only Chromium-class binary present, detection finds it and every managed launch dies on it. No combination of flags fixes that, which is why the documented answer is a different binary rather than a different setting.

Three moves that fix it

  • Install real Google Chrome, which is the recommended fix. Fetch google-chrome-stable_current_amd64.deb from dl.google.com, install it with dpkg -i, and run sudo apt --fix-broken install -y if dependencies complain. Then set browser.executablePath to /usr/bin/google-chrome-stable in ~/.openclaw/openclaw.json, with enabled, headless and noSandbox all true.
  • If snap Chromium has to stay, use attach-only mode. Set browser.attachOnly to true so OpenClaw never launches anything, and start the browser yourself with chromium-browser --headless --no-sandbox --disable-gpu --remote-debugging-port=18800 --user-data-dir=$HOME/.openclaw/browser/openclaw/user-data about:blank.
  • Make that manual browser outlive your shell with a systemd user service. A unit at ~/.config/systemd/user/openclaw-browser.service that runs /snap/bin/chromium with the same flags, plus Restart=on-failure and RestartSec=5, enabled through systemctl --user enable --now openclaw-browser.service, has the CDP port listening before OpenClaw asks for it.

The config surface is six settings, and the defaults suit a laptop rather than a server. browser.enabled turns browser control on and is already true. browser.executablePath is the path to a Chromium-based binary, Chrome, Brave, Edge or Chromium, auto-detected when you omit it, preferring the OS default browser when that browser is Chromium-based. browser.headless runs without a GUI and defaults to false, so a server has to set it explicitly, with OPENCLAW_BROWSER_HEADLESS available as a per-process override that is unset by default. browser.noSandbox adds the --no-sandbox flag that some Linux setups need, default false, and browser.attachOnly stops OpenClaw launching a browser at all, default false. Attach-only is also the documented answer on a Raspberry Pi, an older VPS host, or slow storage, where Chrome needs more time to expose its CDP HTTP endpoint than the managed-browser deadline allows. OpenClaw on Linux covers the Linux install in general, and OpenClaw on a VPS is the checklist for a server with nobody sitting at it.

CDP startup failure or navigation block

With the browser configured, verify it before looking anywhere else. These checks go to the OpenClaw browser control service rather than the Chrome CDP port used at launch, and its port is derived from gateway.port: 18791 by default, the gateway port plus two, so adjust it if you moved the Gateway. Ask for the root path with curl and you get running, pid and chosenBrowser; POST to /start; then GET /tabs. Now run the ladder that separates the two failure classes: openclaw browser --browser-profile openclaw start, then tabs, then open https://example.com. If start fails with not reachable after start, the control plane is unhealthy and CDP readiness is what to chase. If start succeeds and tabs fails, it is still a reachability problem, not a page problem. If start and tabs both pass and only open or navigate fails, the browser is healthy and you are looking at navigation policy or the page itself, which is a separate code path: browser config defaults to a fail-closed SSRF policy object even when you never wrote browser.ssrfPolicy, and a successful start or tabs grants nothing to the next address. When an exception is needed, a narrow exact-hostname entry in allowedHostnames beats opening the private network, and dangerouslyAllowPrivateNetwork belongs only in an environment you have reviewed on purpose. the OpenClaw browser tool is the tool the agent actually calls, and the browser control API is the full control API and command line reference.

On Diali

Diali hosts OpenClaw, so this evening does not happen to you. Each customer runs their own assistant rather than a share of a common one, and the runtime configuration is generated from what you set in the dashboard, then written again at every release, so there is no openclaw.json on a server to repair after an upgrade and no snap versus deb decision to make. Everything the assistant keeps lives on a persistent volume, with daily snapshots and one-click restore available through the Backups add-on (included on Max). Hosted OpenClaw on Diali describes the hosted setup and Diali pricing lists what it costs.

  • apt install chromium gives you a snap wrapper, not a browser.
  • Real Chrome first, attach-only plus a systemd unit second.
  • start and tabs pass but open fails: that is policy, not CDP.
Get started

Stop reading about it, build one

Set up an agent, pick a channel, and have it working inside the app you already keep open.