> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boxd.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Launch a Browser

> Drive a real Chrome browser on your Mac from inside a boxd machine.

Launch and control a Chrome instance on your Mac, with the Chrome DevTools Protocol (CDP) forwarded into the VM. This lets tools like Puppeteer or Playwright running inside a VM control a real browser on your local machine.

<Info>
  This builds on the [client utilities](/guides/client-utilities). Turn them on first with `boxd config set client-utils.enable true`. Currently available for macOS (Apple Silicon) only.
</Info>

```bash theme={"theme":"github-dark"}
boxd local browser open                    # Launch Chrome
boxd local browser open --headless         # Launch headless
boxd local browser info                    # Check status and CDP URL
boxd local browser close                   # Close the browser
```

## Connecting via CDP

`boxd local browser open` (and `boxd local browser info`) print the CDP WebSocket URL. It points at boxd's device ingress (`…/device/<id>/browser/ws`) and is forwarded to the Chrome instance on your machine. Pass that URL to Puppeteer or Playwright.

Connect from Puppeteer:

```javascript theme={"theme":"github-dark"}
const puppeteer = require('puppeteer-core');
const { execSync } = require('child_process');

// Launches Chrome on your machine and prints "CDP WebSocket: <url>".
const out = execSync('boxd local browser open', { encoding: 'utf8' });
const wsUrl = out.match(/CDP WebSocket: (\S+)/)[1];

const browser = await puppeteer.connect({ browserWSEndpoint: wsUrl });
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
```

Or from Playwright:

```javascript theme={"theme":"github-dark"}
const { chromium } = require('playwright-core');
const { execSync } = require('child_process');

const out = execSync('boxd local browser open', { encoding: 'utf8' });
const wsUrl = out.match(/CDP WebSocket: (\S+)/)[1];

const browser = await chromium.connectOverCDP(wsUrl);
```

Or drive it from Claude Code, which comes with the [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp) pre-installed and pre-configured:

```bash theme={"theme":"github-dark"}
claude
# open my local browser and search for cat pictures on google
```

## Session persistence

The browser uses a fixed session directory on your Mac (`~/.boxd/browser-sessions/default/`). Cookies, localStorage, and login state persist across `open`/`close` cycles.

Only one browser instance runs at a time. Calling `open` when a browser is already running returns the existing session.
