2025-12-19 23:57:35 +00:00
|
|
|
|
---
|
2026-01-08 23:06:56 +01:00
|
|
|
|
summary: "Integrated browser control server + action commands"
|
2025-12-19 23:57:35 +00:00
|
|
|
|
read_when:
|
|
|
|
|
|
- Adding agent-controlled browser automation
|
|
|
|
|
|
- Debugging why clawd is interfering with your own Chrome
|
|
|
|
|
|
- Implementing browser settings + lifecycle in the macOS app
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
# Browser (clawd-managed)
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-16 03:24:53 +00:00
|
|
|
|
Clawdbot can run a **dedicated Chrome/Brave/Edge/Chromium profile** that the agent controls.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
It is isolated from your personal browser and is managed through a small local
|
|
|
|
|
|
control server.
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-11 01:24:02 +01:00
|
|
|
|
Beginner view:
|
|
|
|
|
|
- Think of it as a **separate, agent-only browser**.
|
2026-01-16 06:57:20 +00:00
|
|
|
|
- The `clawd` profile does **not** touch your personal browser profile.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
- The agent can **open tabs, read pages, click, and type** in a safe lane.
|
2026-01-16 06:57:20 +00:00
|
|
|
|
- The default `chrome` profile uses the **system default Chromium browser** via the
|
|
|
|
|
|
extension relay; switch to `clawd` for the isolated managed browser.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## What you get
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- A separate browser profile named **clawd** (orange accent by default).
|
|
|
|
|
|
- Deterministic tab control (list/open/focus/close).
|
|
|
|
|
|
- Agent actions (click/type/drag/select), snapshots, screenshots, PDFs.
|
|
|
|
|
|
- Optional multi-profile support (`clawd`, `work`, `remote`, ...).
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
This browser is **not** your daily driver. It is a safe, isolated surface for
|
|
|
|
|
|
agent automation and verification.
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Quick start
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
```bash
|
2026-01-15 08:50:08 +00:00
|
|
|
|
clawdbot browser --browser-profile clawd status
|
|
|
|
|
|
clawdbot browser --browser-profile clawd start
|
|
|
|
|
|
clawdbot browser --browser-profile clawd open https://example.com
|
|
|
|
|
|
clawdbot browser --browser-profile clawd snapshot
|
2026-01-08 23:06:56 +01:00
|
|
|
|
```
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
If you get “Browser disabled”, enable it in config (see below) and restart the
|
|
|
|
|
|
Gateway.
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-16 06:57:20 +00:00
|
|
|
|
## Profiles: `clawd` vs `chrome`
|
|
|
|
|
|
|
|
|
|
|
|
- `clawd`: managed, isolated browser (no extension required).
|
|
|
|
|
|
- `chrome`: extension relay to your **system browser** (requires the Clawdbot
|
|
|
|
|
|
extension to be attached to a tab).
|
|
|
|
|
|
|
|
|
|
|
|
Set `browser.defaultProfile: "clawd"` if you want managed mode by default.
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Configuration
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Browser settings live in `~/.clawdbot/clawdbot.json`.
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
```json5
|
2026-01-04 03:32:40 +00:00
|
|
|
|
{
|
2026-01-08 23:06:56 +01:00
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true, // default: true
|
|
|
|
|
|
controlUrl: "http://127.0.0.1:18791",
|
|
|
|
|
|
cdpUrl: "http://127.0.0.1:18792", // defaults to controlUrl + 1
|
2026-01-16 09:01:25 +00:00
|
|
|
|
remoteCdpTimeoutMs: 1500, // remote CDP HTTP timeout (ms)
|
|
|
|
|
|
remoteCdpHandshakeTimeoutMs: 3000, // remote CDP WebSocket handshake timeout (ms)
|
2026-01-15 08:50:08 +00:00
|
|
|
|
defaultProfile: "chrome",
|
2026-01-08 23:06:56 +01:00
|
|
|
|
color: "#FF4500",
|
|
|
|
|
|
headless: false,
|
|
|
|
|
|
noSandbox: false,
|
|
|
|
|
|
attachOnly: false,
|
2026-01-16 03:24:53 +00:00
|
|
|
|
executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
|
2026-01-08 23:06:56 +01:00
|
|
|
|
profiles: {
|
|
|
|
|
|
clawd: { cdpPort: 18800, color: "#FF4500" },
|
|
|
|
|
|
work: { cdpPort: 18801, color: "#0066CC" },
|
|
|
|
|
|
remote: { cdpUrl: "http://10.0.0.42:9222", color: "#00AA00" }
|
2026-01-04 03:32:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Notes:
|
|
|
|
|
|
- `controlUrl` defaults to `http://127.0.0.1:18791`.
|
|
|
|
|
|
- If you override the Gateway port (`gateway.port` or `CLAWDBOT_GATEWAY_PORT`),
|
|
|
|
|
|
the default browser ports shift to stay in the same “family” (control = gateway + 2).
|
|
|
|
|
|
- `cdpUrl` defaults to `controlUrl + 1` when unset.
|
2026-01-16 09:01:25 +00:00
|
|
|
|
- `remoteCdpTimeoutMs` applies to remote (non-loopback) CDP reachability checks.
|
|
|
|
|
|
- `remoteCdpHandshakeTimeoutMs` applies to remote CDP WebSocket reachability checks.
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- `attachOnly: true` means “never launch a local browser; only attach if it is already running.”
|
2026-01-11 01:24:02 +01:00
|
|
|
|
- `color` + per-profile `color` tint the browser UI so you can see which profile is active.
|
2026-01-16 06:57:20 +00:00
|
|
|
|
- Default profile is `chrome` (extension relay). Use `defaultProfile: "clawd"` for the managed browser.
|
|
|
|
|
|
- Auto-detect order: system default browser if Chromium-based; otherwise Chrome → Brave → Edge → Chromium → Chrome Canary.
|
|
|
|
|
|
- Local `clawd` profiles auto-assign `cdpPort`/`cdpUrl` — set those only for remote CDP.
|
2026-01-16 03:24:53 +00:00
|
|
|
|
|
|
|
|
|
|
## Use Brave (or another Chromium-based browser)
|
|
|
|
|
|
|
2026-01-16 06:57:20 +00:00
|
|
|
|
If your **system default** browser is Chromium-based (Chrome/Brave/Edge/etc),
|
|
|
|
|
|
Clawdbot uses it automatically. Set `browser.executablePath` to override
|
|
|
|
|
|
auto-detection:
|
|
|
|
|
|
|
|
|
|
|
|
CLI example:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
clawdbot config set browser.executablePath "/usr/bin/google-chrome"
|
|
|
|
|
|
```
|
2026-01-16 03:24:53 +00:00
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
// macOS
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
executablePath: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Windows
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
executablePath: "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Linux
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
executablePath: "/usr/bin/brave-browser"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Local vs remote control
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- **Local control (default):** `controlUrl` is loopback (`127.0.0.1`/`localhost`).
|
2026-01-16 03:24:53 +00:00
|
|
|
|
The Gateway starts the control server and can launch a local browser.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- **Remote control:** `controlUrl` is non-loopback. The Gateway **does not** start
|
|
|
|
|
|
a local server; it assumes you are pointing at an existing server elsewhere.
|
|
|
|
|
|
- **Remote CDP:** set `browser.profiles.<name>.cdpUrl` (or `browser.cdpUrl`) to
|
2026-01-16 03:24:53 +00:00
|
|
|
|
attach to a remote Chromium-based browser. In this case, Clawdbot will not launch a local browser.
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-11 01:24:02 +01:00
|
|
|
|
## Remote browser (control server)
|
|
|
|
|
|
|
|
|
|
|
|
You can run the **browser control server** on another machine and point your
|
|
|
|
|
|
Gateway at it with a remote `controlUrl`. This lets the agent drive a browser
|
|
|
|
|
|
outside the host (lab box, VM, remote desktop, etc.).
|
|
|
|
|
|
|
|
|
|
|
|
Key points:
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- The **control server** speaks to Chromium-based browsers (Chrome/Brave/Edge/Chromium) via **CDP**.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
- The **Gateway** only needs the HTTP control URL.
|
|
|
|
|
|
- Profiles are resolved on the **control server** side.
|
|
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
controlUrl: "http://10.0.0.42:18791",
|
|
|
|
|
|
defaultProfile: "work"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Use `profiles.<name>.cdpUrl` for **remote CDP** if you want the Gateway to talk
|
2026-01-16 03:24:53 +00:00
|
|
|
|
directly to a Chromium-based browser instance without a remote control server.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
|
2026-01-16 08:31:51 +00:00
|
|
|
|
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`)
|
|
|
|
|
|
|
|
|
|
|
|
Clawdbot 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.
|
|
|
|
|
|
|
2026-01-16 09:05:19 +00:00
|
|
|
|
### Browserless (hosted remote CDP)
|
|
|
|
|
|
|
|
|
|
|
|
[Browserless](https://browserless.io) is a hosted Chromium service that exposes
|
|
|
|
|
|
CDP endpoints over HTTPS. You can point a Clawdbot browser profile at a
|
|
|
|
|
|
Browserless region endpoint and authenticate with your API key.
|
|
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
defaultProfile: "browserless",
|
|
|
|
|
|
remoteCdpTimeoutMs: 2000,
|
|
|
|
|
|
remoteCdpHandshakeTimeoutMs: 4000,
|
|
|
|
|
|
profiles: {
|
|
|
|
|
|
browserless: {
|
|
|
|
|
|
cdpUrl: "https://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).
|
|
|
|
|
|
|
2026-01-15 04:50:11 +00:00
|
|
|
|
### Running the control server on the browser machine
|
|
|
|
|
|
|
|
|
|
|
|
Run a standalone browser control server (recommended when your Gateway is remote):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-01-16 03:24:53 +00:00
|
|
|
|
# on the machine that runs Chrome/Brave/Edge
|
2026-01-15 04:50:11 +00:00
|
|
|
|
clawdbot browser serve --bind <browser-host> --port 18791 --token <token>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Then point your Gateway at it:
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
controlUrl: "http://<browser-host>:18791",
|
|
|
|
|
|
|
|
|
|
|
|
// Option A (recommended): keep token in env on the Gateway
|
|
|
|
|
|
// (avoid writing secrets into config files)
|
|
|
|
|
|
// controlToken: "<token>"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
And set the auth token in the Gateway environment:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
export CLAWDBOT_BROWSER_CONTROL_TOKEN="<token>"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Option B: store the token in the Gateway config instead (same shared token):
|
|
|
|
|
|
|
|
|
|
|
|
```json5
|
|
|
|
|
|
{
|
|
|
|
|
|
browser: {
|
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
controlUrl: "http://<browser-host>:18791",
|
|
|
|
|
|
controlToken: "<token>"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Security
|
|
|
|
|
|
|
|
|
|
|
|
This section covers the **browser control server** (`browser.controlUrl`) used for agent browser automation.
|
|
|
|
|
|
|
|
|
|
|
|
Key ideas:
|
|
|
|
|
|
- Treat the browser control server like an admin API: **private network only**.
|
|
|
|
|
|
- Use **token auth** always when the server is reachable off-machine.
|
|
|
|
|
|
- Prefer **Tailnet-only** connectivity over LAN exposure.
|
|
|
|
|
|
|
|
|
|
|
|
### Tokens (what is shared with what?)
|
|
|
|
|
|
|
|
|
|
|
|
- `browser.controlToken` / `CLAWDBOT_BROWSER_CONTROL_TOKEN` is **only** for authenticating browser control HTTP requests to `browser.controlUrl`.
|
|
|
|
|
|
- It is **not** the Gateway token (`gateway.auth.token`) and **not** a node pairing token.
|
|
|
|
|
|
- You *can* reuse the same string value, but it’s better to keep them separate to reduce blast radius.
|
|
|
|
|
|
|
|
|
|
|
|
### Binding (don’t expose to your LAN by accident)
|
|
|
|
|
|
|
|
|
|
|
|
Recommended:
|
|
|
|
|
|
- Keep `clawdbot browser serve` bound to loopback (`127.0.0.1`) and publish it via Tailscale.
|
|
|
|
|
|
- Or bind to a Tailnet IP only (never `0.0.0.0`) and require a token.
|
|
|
|
|
|
|
|
|
|
|
|
Avoid:
|
|
|
|
|
|
- `--bind 0.0.0.0` (LAN-visible). Even with token auth, traffic is plain HTTP unless you also add TLS.
|
|
|
|
|
|
|
|
|
|
|
|
### TLS / HTTPS (recommended approach: terminate in front)
|
|
|
|
|
|
|
|
|
|
|
|
Best practice here: keep `clawdbot browser serve` on HTTP and terminate TLS in front.
|
|
|
|
|
|
|
|
|
|
|
|
If you’re already using Tailscale, you have two good options:
|
|
|
|
|
|
|
|
|
|
|
|
1) **Tailnet-only, still HTTP** (transport is encrypted by Tailscale):
|
|
|
|
|
|
- Keep `controlUrl` as `http://…` but ensure it’s only reachable over your tailnet.
|
|
|
|
|
|
|
|
|
|
|
|
2) **Serve HTTPS via Tailscale** (nice UX: `https://…` URL):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# on the browser machine
|
|
|
|
|
|
clawdbot browser serve --bind 127.0.0.1 --port 18791 --token <token>
|
|
|
|
|
|
tailscale serve https / http://127.0.0.1:18791
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Then set your Gateway config `browser.controlUrl` to the HTTPS URL (MagicDNS/ts.net) and keep using the same token.
|
|
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
- Do **not** use Tailscale Funnel for this unless you explicitly want to make the endpoint public.
|
|
|
|
|
|
- For Tailnet setup/background, see [Gateway web surfaces](/web/index) and the [Gateway CLI](/cli/gateway).
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Profiles (multi-browser)
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-15 08:26:23 +00:00
|
|
|
|
Clawdbot supports multiple named profiles (routing configs). Profiles can be:
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- **clawd-managed**: a dedicated Chromium-based browser instance with its own user data directory + CDP port
|
|
|
|
|
|
- **remote**: an explicit CDP URL (Chromium-based browser running elsewhere)
|
2026-01-15 08:26:23 +00:00
|
|
|
|
- **extension relay**: your existing Chrome tab(s) via the local relay + Chrome extension
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Defaults:
|
|
|
|
|
|
- The `clawd` profile is auto-created if missing.
|
2026-01-15 08:26:23 +00:00
|
|
|
|
- The `chrome` profile is built-in for the Chrome extension relay (points at `http://127.0.0.1:18792` by default).
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Local CDP ports allocate from **18800–18899** by default.
|
|
|
|
|
|
- Deleting a profile moves its local data directory to Trash.
|
2026-01-06 11:04:33 -07:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
All control endpoints accept `?profile=<name>`; the CLI uses `--browser-profile`.
|
2026-01-06 11:04:33 -07:00
|
|
|
|
|
2026-01-15 04:50:11 +00:00
|
|
|
|
## Chrome extension relay (use your existing Chrome)
|
|
|
|
|
|
|
|
|
|
|
|
Clawdbot can also drive **your existing Chrome tabs** (no separate “clawd” Chrome instance) via a local CDP relay + a Chrome extension.
|
|
|
|
|
|
|
|
|
|
|
|
Full guide: [Chrome extension](/tools/chrome-extension)
|
|
|
|
|
|
|
|
|
|
|
|
Flow:
|
|
|
|
|
|
- You run a **browser control server** (Gateway on the same machine, or `clawdbot browser serve`).
|
|
|
|
|
|
- A local **relay server** listens at a loopback `cdpUrl` (default: `http://127.0.0.1:18792`).
|
2026-01-15 05:20:56 +00:00
|
|
|
|
- You click the **Clawdbot Browser Relay** extension icon on a tab to attach (it does not auto-attach).
|
2026-01-15 04:50:11 +00:00
|
|
|
|
- The agent controls that tab via the normal `browser` tool, by selecting the right profile.
|
|
|
|
|
|
|
2026-01-15 05:15:33 +00:00
|
|
|
|
If the Gateway runs on the same machine as Chrome (default setup), you usually **do not** need `clawdbot browser serve`.
|
|
|
|
|
|
Use `browser serve` only when the Gateway runs elsewhere (remote mode).
|
|
|
|
|
|
|
2026-01-15 05:17:12 +00:00
|
|
|
|
### Sandboxed sessions
|
|
|
|
|
|
|
|
|
|
|
|
If the agent session is sandboxed, the `browser` tool may default to `target="sandbox"` (sandbox browser).
|
|
|
|
|
|
Chrome extension relay takeover requires host browser control, so either:
|
|
|
|
|
|
- run the session unsandboxed, or
|
|
|
|
|
|
- set `agents.defaults.sandbox.browser.allowHostControl: true` and use `target="host"` when calling the tool.
|
|
|
|
|
|
|
2026-01-15 04:50:11 +00:00
|
|
|
|
### Setup
|
|
|
|
|
|
|
2026-01-15 08:26:23 +00:00
|
|
|
|
1) Load the extension (dev/unpacked):
|
2026-01-15 04:50:11 +00:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-01-15 08:26:23 +00:00
|
|
|
|
clawdbot browser extension install
|
2026-01-15 04:50:11 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- Chrome → `chrome://extensions` → enable “Developer mode”
|
|
|
|
|
|
- “Load unpacked” → select the directory printed by `clawdbot browser extension path`
|
|
|
|
|
|
- Pin the extension, then click it on the tab you want to control (badge shows `ON`).
|
|
|
|
|
|
|
2026-01-15 08:26:23 +00:00
|
|
|
|
2) Use it:
|
2026-01-15 04:50:11 +00:00
|
|
|
|
- CLI: `clawdbot browser --browser-profile chrome tabs`
|
|
|
|
|
|
- Agent tool: `browser` with `profile="chrome"`
|
|
|
|
|
|
|
2026-01-15 08:26:23 +00:00
|
|
|
|
Optional: if you want a different name or relay port, create your own profile:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
clawdbot browser create-profile \
|
|
|
|
|
|
--name my-chrome \
|
|
|
|
|
|
--driver extension \
|
|
|
|
|
|
--cdp-url http://127.0.0.1:18792 \
|
|
|
|
|
|
--color "#00AA00"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-01-15 04:50:11 +00:00
|
|
|
|
Notes:
|
|
|
|
|
|
- This mode relies on Playwright-on-CDP for most operations (screenshots/snapshots/actions).
|
|
|
|
|
|
- Detach by clicking the extension icon again.
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Isolation guarantees
|
|
|
|
|
|
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- **Dedicated user data dir**: never touches your personal browser profile.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- **Dedicated ports**: avoids `9222` to prevent collisions with dev workflows.
|
|
|
|
|
|
- **Deterministic tab control**: target tabs by `targetId`, not “last tab”.
|
|
|
|
|
|
|
|
|
|
|
|
## Browser selection
|
2026-01-06 11:04:33 -07:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
When launching locally, Clawdbot picks the first available:
|
2026-01-16 03:24:53 +00:00
|
|
|
|
1. Chrome
|
|
|
|
|
|
2. Brave
|
|
|
|
|
|
3. Edge
|
|
|
|
|
|
4. Chromium
|
|
|
|
|
|
5. Chrome Canary
|
2026-01-06 11:04:33 -07:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
You can override with `browser.executablePath`.
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Platforms:
|
|
|
|
|
|
- macOS: checks `/Applications` and `~/Applications`.
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- Linux: looks for `google-chrome`, `brave`, `microsoft-edge`, `chromium`, etc.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Windows: checks common install locations.
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Control API (optional)
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
If you want to integrate directly, the browser control server exposes a small
|
|
|
|
|
|
HTTP API:
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Status/start/stop: `GET /`, `POST /start`, `POST /stop`
|
|
|
|
|
|
- Tabs: `GET /tabs`, `POST /tabs/open`, `POST /tabs/focus`, `DELETE /tabs/:targetId`
|
|
|
|
|
|
- Snapshot/screenshot: `GET /snapshot`, `POST /screenshot`
|
|
|
|
|
|
- Actions: `POST /navigate`, `POST /act`
|
|
|
|
|
|
- Hooks: `POST /hooks/file-chooser`, `POST /hooks/dialog`
|
2026-01-12 19:40:59 +00:00
|
|
|
|
- Downloads: `POST /download`, `POST /wait/download`
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Debugging: `GET /console`, `POST /pdf`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- Debugging: `GET /errors`, `GET /requests`, `POST /trace/start`, `POST /trace/stop`, `POST /highlight`
|
2026-01-12 19:40:59 +00:00
|
|
|
|
- Network: `POST /response/body`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- State: `GET /cookies`, `POST /cookies/set`, `POST /cookies/clear`
|
|
|
|
|
|
- State: `GET /storage/:kind`, `POST /storage/:kind/set`, `POST /storage/:kind/clear`
|
|
|
|
|
|
- Settings: `POST /set/offline`, `POST /set/headers`, `POST /set/credentials`, `POST /set/geolocation`, `POST /set/media`, `POST /set/timezone`, `POST /set/locale`, `POST /set/device`
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
All endpoints accept `?profile=<name>`.
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
### Playwright requirement
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
2026-01-12 08:36:23 +00:00
|
|
|
|
Some features (navigate/act/AI snapshot/role snapshot, element screenshots, PDF) require
|
2026-01-11 10:15:37 +00:00
|
|
|
|
Playwright. If Playwright isn’t installed, those endpoints return a clear 501
|
2026-01-15 04:50:11 +00:00
|
|
|
|
error. ARIA snapshots and basic screenshots still work for clawd-managed Chrome.
|
|
|
|
|
|
For the Chrome extension relay driver, ARIA snapshots and screenshots require Playwright.
|
2025-12-20 00:53:45 +00:00
|
|
|
|
|
2026-01-16 06:57:20 +00:00
|
|
|
|
If you see `Playwright is not available in this gateway build`, install the full
|
|
|
|
|
|
Playwright package (not `playwright-core`) and restart the gateway, or reinstall
|
|
|
|
|
|
Clawdbot with browser support.
|
|
|
|
|
|
|
2026-01-11 01:24:02 +01:00
|
|
|
|
## How it works (internal)
|
|
|
|
|
|
|
|
|
|
|
|
High-level flow:
|
|
|
|
|
|
- A small **control server** accepts HTTP requests.
|
2026-01-16 03:24:53 +00:00
|
|
|
|
- It connects to Chromium-based browsers (Chrome/Brave/Edge/Chromium) via **CDP**.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
- For advanced actions (click/type/snapshot/PDF), it uses **Playwright** on top
|
|
|
|
|
|
of CDP.
|
|
|
|
|
|
- When Playwright is missing, only non-Playwright operations are available.
|
|
|
|
|
|
|
|
|
|
|
|
This design keeps the agent on a stable, deterministic interface while letting
|
|
|
|
|
|
you swap local/remote browsers and profiles.
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## CLI quick reference
|
|
|
|
|
|
|
|
|
|
|
|
All commands accept `--browser-profile <name>` to target a specific profile.
|
2026-01-12 18:42:23 +00:00
|
|
|
|
All commands also accept `--json` for machine-readable output (stable payloads).
|
2026-01-04 03:32:40 +00:00
|
|
|
|
|
2025-12-20 00:53:45 +00:00
|
|
|
|
Basics:
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser status`
|
|
|
|
|
|
- `clawdbot browser start`
|
|
|
|
|
|
- `clawdbot browser stop`
|
|
|
|
|
|
- `clawdbot browser tabs`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `clawdbot browser tab`
|
|
|
|
|
|
- `clawdbot browser tab new`
|
|
|
|
|
|
- `clawdbot browser tab select 2`
|
|
|
|
|
|
- `clawdbot browser tab close 2`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser open https://example.com`
|
|
|
|
|
|
- `clawdbot browser focus abcd1234`
|
|
|
|
|
|
- `clawdbot browser close abcd1234`
|
2025-12-20 00:53:45 +00:00
|
|
|
|
|
|
|
|
|
|
Inspection:
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser screenshot`
|
|
|
|
|
|
- `clawdbot browser screenshot --full-page`
|
|
|
|
|
|
- `clawdbot browser screenshot --ref 12`
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `clawdbot browser screenshot --ref e12`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser snapshot`
|
|
|
|
|
|
- `clawdbot browser snapshot --format aria --limit 200`
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `clawdbot browser snapshot --interactive --compact --depth 6`
|
2026-01-15 03:50:48 +00:00
|
|
|
|
- `clawdbot browser snapshot --efficient`
|
|
|
|
|
|
- `clawdbot browser snapshot --labels`
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `clawdbot browser snapshot --selector "#main" --interactive`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `clawdbot browser snapshot --frame "iframe#main" --interactive`
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `clawdbot browser console --level error`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `clawdbot browser errors --clear`
|
|
|
|
|
|
- `clawdbot browser requests --filter api --clear`
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `clawdbot browser pdf`
|
2026-01-12 19:40:59 +00:00
|
|
|
|
- `clawdbot browser responsebody "**/api" --max-chars 5000`
|
2025-12-20 00:53:45 +00:00
|
|
|
|
|
|
|
|
|
|
Actions:
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser navigate https://example.com`
|
|
|
|
|
|
- `clawdbot browser resize 1280 720`
|
|
|
|
|
|
- `clawdbot browser click 12 --double`
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `clawdbot browser click e12 --double`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser type 23 "hello" --submit`
|
|
|
|
|
|
- `clawdbot browser press Enter`
|
|
|
|
|
|
- `clawdbot browser hover 44`
|
2026-01-12 21:56:13 +00:00
|
|
|
|
- `clawdbot browser scrollintoview e12`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser drag 10 11`
|
|
|
|
|
|
- `clawdbot browser select 9 OptionA OptionB`
|
2026-01-12 19:40:59 +00:00
|
|
|
|
- `clawdbot browser download e12 /tmp/report.pdf`
|
|
|
|
|
|
- `clawdbot browser waitfordownload /tmp/report.pdf`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser upload /tmp/file.pdf`
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `clawdbot browser fill --fields '[{"ref":"1","type":"text","value":"Ada"}]'`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser dialog --accept`
|
|
|
|
|
|
- `clawdbot browser wait --text "Done"`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `clawdbot browser wait "#main" --url "**/dash" --load networkidle --fn "window.ready===true"`
|
2026-01-04 14:32:47 +00:00
|
|
|
|
- `clawdbot browser evaluate --fn '(el) => el.textContent' --ref 7`
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `clawdbot browser highlight e12`
|
|
|
|
|
|
- `clawdbot browser trace start`
|
|
|
|
|
|
- `clawdbot browser trace stop`
|
|
|
|
|
|
|
|
|
|
|
|
State:
|
|
|
|
|
|
- `clawdbot browser cookies`
|
|
|
|
|
|
- `clawdbot browser cookies set session abc123 --url "https://example.com"`
|
|
|
|
|
|
- `clawdbot browser cookies clear`
|
|
|
|
|
|
- `clawdbot browser storage local get`
|
|
|
|
|
|
- `clawdbot browser storage local set theme dark`
|
|
|
|
|
|
- `clawdbot browser storage session clear`
|
|
|
|
|
|
- `clawdbot browser set offline on`
|
|
|
|
|
|
- `clawdbot browser set headers --json '{"X-Debug":"1"}'`
|
|
|
|
|
|
- `clawdbot browser set credentials user pass`
|
|
|
|
|
|
- `clawdbot browser set credentials --clear`
|
|
|
|
|
|
- `clawdbot browser set geo 37.7749 -122.4194 --origin "https://example.com"`
|
|
|
|
|
|
- `clawdbot browser set geo --clear`
|
|
|
|
|
|
- `clawdbot browser set media dark`
|
|
|
|
|
|
- `clawdbot browser set timezone America/New_York`
|
|
|
|
|
|
- `clawdbot browser set locale en-US`
|
|
|
|
|
|
- `clawdbot browser set device "iPhone 14"`
|
2025-12-19 23:57:35 +00:00
|
|
|
|
|
|
|
|
|
|
Notes:
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `upload` and `dialog` are **arming** calls; run them before the click/press
|
|
|
|
|
|
that triggers the chooser/dialog.
|
|
|
|
|
|
- `upload` can also set file inputs directly via `--input-ref` or `--element`.
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `snapshot`:
|
|
|
|
|
|
- `--format ai` (default when Playwright is installed): returns an AI snapshot with numeric refs (`aria-ref="<n>"`).
|
|
|
|
|
|
- `--format aria`: returns the accessibility tree (no refs; inspection only).
|
2026-01-15 03:50:48 +00:00
|
|
|
|
- `--efficient` (or `--mode efficient`): compact role snapshot preset (interactive + compact + depth + lower maxChars).
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- Role snapshot options (`--interactive`, `--compact`, `--depth`, `--selector`) force a role-based snapshot with refs like `ref=e12`.
|
2026-01-12 17:32:02 +00:00
|
|
|
|
- `--frame "<iframe selector>"` scopes role snapshots to an iframe (pairs with role refs like `e12`).
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `--interactive` outputs a flat, easy-to-pick list of interactive elements (best for driving actions).
|
2026-01-15 03:50:48 +00:00
|
|
|
|
- `--labels` adds a viewport-only screenshot with overlayed ref labels (prints `MEDIA:<path>`).
|
2026-01-12 08:36:23 +00:00
|
|
|
|
- `click`/`type`/etc require a `ref` from `snapshot` (either numeric `12` or role ref `e12`).
|
|
|
|
|
|
CSS selectors are intentionally not supported for actions.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
|
2026-01-12 18:42:23 +00:00
|
|
|
|
## Snapshots and refs
|
|
|
|
|
|
|
|
|
|
|
|
Clawdbot supports two “snapshot” styles:
|
|
|
|
|
|
|
|
|
|
|
|
- **AI snapshot (numeric refs)**: `clawdbot browser snapshot` (default; `--format ai`)
|
|
|
|
|
|
- Output: a text snapshot that includes numeric refs.
|
|
|
|
|
|
- Actions: `clawdbot browser click 12`, `clawdbot browser type 23 "hello"`.
|
|
|
|
|
|
- Internally, the ref is resolved via Playwright’s `aria-ref`.
|
|
|
|
|
|
|
|
|
|
|
|
- **Role snapshot (role refs like `e12`)**: `clawdbot browser snapshot --interactive` (or `--compact`, `--depth`, `--selector`, `--frame`)
|
|
|
|
|
|
- Output: a role-based list/tree with `[ref=e12]` (and optional `[nth=1]`).
|
|
|
|
|
|
- Actions: `clawdbot browser click e12`, `clawdbot browser highlight e12`.
|
|
|
|
|
|
- Internally, the ref is resolved via `getByRole(...)` (plus `nth()` for duplicates).
|
2026-01-15 03:50:48 +00:00
|
|
|
|
- Add `--labels` to include a viewport screenshot with overlayed `e12` labels.
|
2026-01-12 18:42:23 +00:00
|
|
|
|
|
|
|
|
|
|
Ref behavior:
|
|
|
|
|
|
- Refs are **not stable across navigations**; if something fails, re-run `snapshot` and use a fresh ref.
|
|
|
|
|
|
- If the role snapshot was taken with `--frame`, role refs are scoped to that iframe until the next role snapshot.
|
|
|
|
|
|
|
|
|
|
|
|
## Wait power-ups
|
|
|
|
|
|
|
|
|
|
|
|
You can wait on more than just time/text:
|
|
|
|
|
|
|
|
|
|
|
|
- Wait for URL (globs supported by Playwright):
|
|
|
|
|
|
- `clawdbot browser wait --url "**/dash"`
|
|
|
|
|
|
- Wait for load state:
|
|
|
|
|
|
- `clawdbot browser wait --load networkidle`
|
|
|
|
|
|
- Wait for a JS predicate:
|
|
|
|
|
|
- `clawdbot browser wait --fn "window.ready===true"`
|
|
|
|
|
|
- Wait for a selector to become visible:
|
|
|
|
|
|
- `clawdbot browser wait "#main"`
|
|
|
|
|
|
|
|
|
|
|
|
These can be combined:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
clawdbot browser wait "#main" \
|
|
|
|
|
|
--url "**/dash" \
|
|
|
|
|
|
--load networkidle \
|
|
|
|
|
|
--fn "window.ready===true" \
|
|
|
|
|
|
--timeout-ms 15000
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Debug workflows
|
|
|
|
|
|
|
|
|
|
|
|
When an action fails (e.g. “not visible”, “strict mode violation”, “covered”):
|
|
|
|
|
|
|
|
|
|
|
|
1. `clawdbot browser snapshot --interactive`
|
|
|
|
|
|
2. Use `click <ref>` / `type <ref>` (prefer role refs in interactive mode)
|
|
|
|
|
|
3. If it still fails: `clawdbot browser highlight <ref>` to see what Playwright is targeting
|
|
|
|
|
|
4. If the page behaves oddly:
|
|
|
|
|
|
- `clawdbot browser errors --clear`
|
|
|
|
|
|
- `clawdbot browser requests --filter api --clear`
|
|
|
|
|
|
5. For deep debugging: record a trace:
|
|
|
|
|
|
- `clawdbot browser trace start`
|
|
|
|
|
|
- reproduce the issue
|
|
|
|
|
|
- `clawdbot browser trace stop` (prints `TRACE:<path>`)
|
|
|
|
|
|
|
|
|
|
|
|
## JSON output
|
|
|
|
|
|
|
|
|
|
|
|
`--json` is for scripting and structured tooling.
|
|
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
clawdbot browser status --json
|
|
|
|
|
|
clawdbot browser snapshot --interactive --json
|
|
|
|
|
|
clawdbot browser requests --filter api --json
|
|
|
|
|
|
clawdbot browser cookies --json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Role snapshots in JSON include `refs` plus a small `stats` block (lines/chars/refs/interactive) so tools can reason about payload size and density.
|
|
|
|
|
|
|
|
|
|
|
|
## State and environment knobs
|
|
|
|
|
|
|
|
|
|
|
|
These are useful for “make the site behave like X” workflows:
|
|
|
|
|
|
|
|
|
|
|
|
- Cookies: `cookies`, `cookies set`, `cookies clear`
|
|
|
|
|
|
- Storage: `storage local|session get|set|clear`
|
|
|
|
|
|
- Offline: `set offline on|off`
|
|
|
|
|
|
- Headers: `set headers --json '{"X-Debug":"1"}'` (or `--clear`)
|
|
|
|
|
|
- HTTP basic auth: `set credentials user pass` (or `--clear`)
|
|
|
|
|
|
- Geolocation: `set geo <lat> <lon> --origin "https://example.com"` (or `--clear`)
|
|
|
|
|
|
- Media: `set media dark|light|no-preference|none`
|
|
|
|
|
|
- Timezone / locale: `set timezone ...`, `set locale ...`
|
|
|
|
|
|
- Device / viewport:
|
|
|
|
|
|
- `set device "iPhone 14"` (Playwright device presets)
|
|
|
|
|
|
- `set viewport 1280 720`
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Security & privacy
|
|
|
|
|
|
|
|
|
|
|
|
- The clawd browser profile may contain logged-in sessions; treat it as sensitive.
|
2026-01-12 02:01:32 +00:00
|
|
|
|
- For logins and anti-bot notes (X/Twitter, etc.), see [Browser login + X/Twitter posting](/tools/browser-login).
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Keep control URLs loopback-only unless you intentionally expose the server.
|
|
|
|
|
|
- Remote CDP endpoints are powerful; tunnel and protect them.
|
2026-01-05 15:16:00 +00:00
|
|
|
|
|
|
|
|
|
|
## Troubleshooting
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
For Linux-specific issues (especially snap Chromium), see
|
|
|
|
|
|
[Browser troubleshooting](/tools/browser-linux-troubleshooting).
|
2026-01-11 01:24:02 +01:00
|
|
|
|
|
|
|
|
|
|
## Agent tools + how control works
|
|
|
|
|
|
|
|
|
|
|
|
The agent gets **one tool** for browser automation:
|
|
|
|
|
|
- `browser` — 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 act` uses the snapshot `ref` IDs to click/type/drag/select.
|
|
|
|
|
|
- `browser screenshot` captures pixels (full page or element).
|
|
|
|
|
|
- `browser` accepts:
|
|
|
|
|
|
- `profile` to choose a named browser profile (host or remote control server).
|
|
|
|
|
|
- `target` (`sandbox` | `host` | `custom`) to select where the browser lives.
|
|
|
|
|
|
- `controlUrl` sets `target: "custom"` implicitly (remote control server).
|
|
|
|
|
|
- In sandboxed sessions, `target: "host"` requires `agents.defaults.sandbox.browser.allowHostControl=true`.
|
|
|
|
|
|
- If `target` is omitted: sandboxed sessions default to `sandbox`, non-sandbox sessions default to `host`.
|
2026-01-11 01:52:23 +01:00
|
|
|
|
- Sandbox allowlists can restrict `target: "custom"` to specific URLs/hosts/ports.
|
2026-01-11 01:55:38 +01:00
|
|
|
|
- Defaults: allowlists unset (no restriction), and sandbox host control is disabled.
|
2026-01-11 01:24:02 +01:00
|
|
|
|
|
|
|
|
|
|
This keeps the agent deterministic and avoids brittle selectors.
|