Skip to main content
dench browser controls a cloud browser without opening dench.com or installing Chrome locally. The browser provider stays server-side: the CLI only sends bearer-authenticated JSON, and your per-workspace browser profile (cookies, logins) is resolved automatically. You never see or pass provider credentials.
Both auth modes work: an approved dench signin session and a workspace DENCH_API_KEY. Sandboxes authenticate with DENCH_API_KEY automatically.

Two ways to use it

Interactive actions

One step per call: open, inspect, click, type, screenshot, stop. Best for quick logins and ad-hoc steps.

Playwright sessions

Open a CDP session and drive it with a full Playwright script. Best for longer, durable automations run from the sandbox.

Interactive actions

dench browser open https://example.com --json
dench browser inspect --json
dench browser click --text "Sign in"
dench browser fill --label "Email" --value "me@example.com"
dench browser type "search query"
dench browser key Enter
dench browser scroll down --pixels 600
dench browser wait --text "Done" --timeout-ms 15000
dench browser screenshot --output page.jpg --full-page
dench browser stop
The CLI remembers the latest browser thread per host/session, so follow-up actions reuse it. Pass --thread <threadId> to target a specific one, or dench browser reset to forget it.

Playwright sessions (CDP)

Create a session, connect with Playwright over CDP, then stop it. The live view and replay appear in the Dench chat panel the same way as interactive runs.
dench browser session create --json
# -> { "sessionId": "...", "connectUrl": "wss://.../cdp?relay_token=...", "liveViewUrl": "..." }
dench browser session status <sessionId> --json
dench browser session stop <sessionId> --json
Connect from a script with chromium.connectOverCDP(session.connectUrl):
import { chromium } from "playwright-core";
import { execFileSync } from "node:child_process";

const session = JSON.parse(
  execFileSync("dench", ["browser", "session", "create", "--json"], {
    encoding: "utf8",
  }),
);

const browser = await chromium.connectOverCDP(session.connectUrl);
const context = browser.contexts()[0];
const page = context.pages()[0] ?? (await context.newPage());

await page.goto("https://example.com");
console.log(await page.title());

await browser.close();
execFileSync("dench", ["browser", "session", "stop", session.sessionId, "--json"]);
The optional --context-id flag overrides the resolved profile for manual testing; normally you should omit it and let the workspace profile apply. See the full agent playbook at references/BROWSER.md and the HTTP equivalents under the API reference.