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

# Browser Configuration

> Configure Skyvern's browser modes including headful, headless, local Chrome, and CDP connect. Set display resolution, viewport size, and connect to external Chrome instances for self-hosted deployments.

Skyvern uses Playwright with Chromium to execute browser automations.

## Browser modes

The `BROWSER_TYPE` setting controls how Skyvern runs the browser.

* **[Headful](#headful-default)**: visible browser window (default)
* **[Headless](#headless)**: no display, runs in the background
* **[Use Your Own Chrome](#use-your-own-chrome)**: runs the installed Chrome app with your logged-in profile
* **[CDP Connect](#cdp-connect-external-chrome)**: connects to an already-running Chrome instance

### Headful (default)

```bash .env theme={null}
BROWSER_TYPE=chromium-headful
```

The browser runs with a visible window. In Docker, this displays on a virtual framebuffer (Xvfb).

### Headless

```bash .env theme={null}
BROWSER_TYPE=chromium-headless
```

The browser runs without any display.

<Note>
  Some websites detect and block headless browsers. If you encounter issues with bot detection, try headful mode with a virtual display.
</Note>

### Use Your Own Chrome

```bash .env theme={null}
BROWSER_TYPE=cdp-connect
CHROME_EXECUTABLE_PATH=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
```

Skyvern launches the Chrome app installed on your machine and connects to it automatically. Your existing Chrome profile (cookies, saved logins, extensions) is copied over so automations run in a browser environment that matches your real one.

Useful for:

* Running automations with your saved logins and cookies
* Using your installed Chrome extensions
* Avoiding bot detection by using a real Chrome installation

### CDP Connect (External Chrome)

```bash .env theme={null}
BROWSER_TYPE=cdp-connect
BROWSER_REMOTE_DEBUGGING_URL=http://host.docker.internal:9222/
BROWSER_CDP_CONNECT_TIMEOUT_MS=120000
```

Connect to an existing Chrome instance running with remote debugging enabled. Useful for:

* Using your existing browser profile with saved logins
* Debugging with Chrome DevTools
* Running automations on a browser with specific extensions

<Note>
  Docker Compose self-host installs default `BROWSER_STREAMING_MODE` to `cdp`.
  Existing installs that already set this variable in `.env` keep their value.
  To opt out of CDP livestreaming, set `BROWSER_STREAMING_MODE=vnc` in `.env`.
</Note>

***

## Setting up Use Your Own Chrome

Set `CHROME_EXECUTABLE_PATH` to your Chrome installation path and Skyvern handles the rest. No need to manually start Chrome with debugging flags.

### Step 1: Find your Chrome path

<CodeGroup>
  ```bash macOS theme={null}
  /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
  ```

  ```powershell Windows theme={null}
  "C:\Program Files\Google\Chrome\Application\chrome.exe"
  ```

  ```bash Linux theme={null}
  # Usually one of:
  /usr/bin/google-chrome
  /usr/bin/chromium
  /usr/bin/chromium-browser
  ```
</CodeGroup>

### Step 2: Configure Skyvern

<CodeGroup>
  ```bash macOS .env theme={null}
  BROWSER_TYPE=cdp-connect
  CHROME_EXECUTABLE_PATH=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
  ```

  ```bash Windows .env theme={null}
  BROWSER_TYPE=cdp-connect
  CHROME_EXECUTABLE_PATH="C:\Program Files\Google\Chrome\Application\chrome.exe"
  ```

  ```bash Linux .env theme={null}
  BROWSER_TYPE=cdp-connect
  CHROME_EXECUTABLE_PATH=/usr/bin/google-chrome
  ```
</CodeGroup>

When Skyvern starts, it will:

1. Copy your Chrome profile to a working directory (`./tmp/user_data_dir`)
2. Launch Chrome with remote debugging on port 9222
3. Connect via CDP automatically

<Warning>
  All existing Chrome windows must be closed before Skyvern can launch Chrome with remote debugging. If Chrome is already running, Skyvern will return an error.
</Warning>

<Note>
  If port 9222 is already in use (e.g., from a previous session), Skyvern will connect to the existing instance instead of launching a new one.
</Note>

***

## Setting up CDP Connect

CDP (Chrome DevTools Protocol) lets Skyvern control an external Chrome browser instead of launching its own.

### Step 1: Enable Chrome remote debugging

For an already-running Chrome profile, prefer Chrome's built-in remote debugging
toggle:

1. Open `chrome://inspect/#remote-debugging` in Chrome.
2. Enable remote debugging for this browser instance.
3. Keep Chrome open while Skyvern connects.

This path keeps you on your existing Chrome profile. Skyvern will first try to
auto-discover a local debugging server, then let you paste a direct
`ws://.../devtools/browser/...` URL if Chrome exposes only a WebSocket endpoint.

#### Docker-reachable isolated profile fallback

When Skyvern runs in Docker, Chrome's built-in listener may bind to host
loopback only. If the container cannot reach it, start a separate Chrome profile
with a Docker-reachable CDP endpoint:

<CodeGroup>
  ```bash macOS theme={null}
  /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
    --remote-debugging-port=9222 \
    --remote-debugging-address=0.0.0.0 \
    --user-data-dir="$HOME/chrome-cdp-profile" \
    --no-first-run \
    --no-default-browser-check
  ```

  ```powershell Windows theme={null}
  "C:\Program Files\Google\Chrome\Application\chrome.exe" `
    --remote-debugging-port=9222 `
    --remote-debugging-address=0.0.0.0 `
    --user-data-dir="C:\chrome-cdp-profile" `
    --no-first-run `
    --no-default-browser-check
  ```

  ```bash Linux theme={null}
  google-chrome \
    --remote-debugging-port=9222 \
    --remote-debugging-address=0.0.0.0 \
    --user-data-dir="$HOME/chrome-cdp-profile" \
    --no-first-run \
    --no-default-browser-check
  ```
</CodeGroup>

The `--user-data-dir` flag creates a separate profile for Skyvern, preserving
your main Chrome profile. Since [Chrome 136](https://developer.chrome.com/blog/remote-debugging-port),
`--remote-debugging-port` is ignored for the default Chrome data directory, so
only use these flags with a non-standard user data directory.

#### Windows Docker Desktop with `chrome://inspect`

Chrome's `chrome://inspect/#remote-debugging` toggle can bind its debugging
server to host loopback only. Docker Desktop cannot connect to that listener
directly through `host.docker.internal`. Skyvern includes a Windows helper that
bridges Docker to Chrome and writes the exact WebSocket URL from Chrome's
`DevToolsActivePort` file.

Open Chrome, go to `chrome://inspect/#remote-debugging`, enable remote
debugging, then run this from an Administrator PowerShell in the Skyvern repo:

```powershell Windows theme={null}
.\scripts\windows_chrome_inspect_cdp.ps1 -UpdateEnv
docker compose up -d --force-recreate skyvern
```

The helper creates a Windows port proxy from `0.0.0.0:9223` to Chrome's
loopback debugging port, adds a matching firewall rule, reads the full browser
WebSocket path, and writes:

```bash .env theme={null}
BROWSER_TYPE=cdp-connect
BROWSER_REMOTE_DEBUGGING_URL=ws://host.docker.internal:9223/devtools/browser/<id>
BROWSER_REMOTE_DEBUGGING_HOST_HEADER=127.0.0.1:<chrome-port>
BROWSER_STREAMING_MODE=cdp
BROWSER_CDP_CONNECT_TIMEOUT_MS=120000
```

Chrome may prompt you to allow the remote debugging connection the first time
Skyvern connects. Click **Allow** and retry the browser session if the first
attempt times out.

### Step 2: Configure Skyvern

```bash .env theme={null}
BROWSER_TYPE=cdp-connect
BROWSER_REMOTE_DEBUGGING_URL=http://host.docker.internal:9222/
BROWSER_CDP_CONNECT_TIMEOUT_MS=120000
```

Use the URL that matches the remote debugging path you chose. For a classic
HTTP CDP endpoint, use the host and port. For a `chrome://inspect` flow that
only exposes a browser WebSocket, use the full direct
`ws://.../devtools/browser/<id>` URL.

When running Skyvern in Docker:

| Host OS       | URL                                 |
| ------------- | ----------------------------------- |
| macOS/Windows | `http://host.docker.internal:9222/` |
| Linux         | `http://172.17.0.1:9222/`           |

If Docker Desktop reaches Chrome but Chrome rejects the `host.docker.internal`
host name, Skyvern retries with the Docker host gateway IPv4 address. You can
also set `BROWSER_REMOTE_DEBUGGING_URL` directly to that IPv4 address.

If Windows Defender Firewall blocks the connection from Docker, allow inbound
TCP traffic on port 9222:

```powershell Windows theme={null}
New-NetFirewallRule -DisplayName "Chrome Remote Debug 9222" -Direction Inbound -LocalPort 9222 -Protocol TCP -Action Allow
```

### Step 3: Verify connection

For a classic HTTP CDP endpoint, test that Chrome is listening on port 9222:

```bash theme={null}
curl http://localhost:9222/json/version
```

```powershell Windows theme={null}
Invoke-RestMethod http://127.0.0.1:9222/json/version
```

You should see Chrome's version information and a `webSocketDebuggerUrl`.

If you used the Windows `chrome://inspect` helper, the configured URL is a
direct `ws://.../devtools/browser/<id>` endpoint. In that mode, verify by
starting a Skyvern browser session after restarting the backend.

<Note>
  If `/json/version` does not return Chrome version information from inside the
  Skyvern container, verify Chrome is listening on `0.0.0.0:9222` or `::9222` and
  that Windows Firewall allows inbound traffic on port 9222.
</Note>

<Warning>
  CDP mode exposes Chrome to network access. The examples use
  `--remote-debugging-address=0.0.0.0` so Docker can reach Chrome on the host.
  Only use this in trusted environments. If Skyvern runs on the same host outside
  Docker, bind to `127.0.0.1` instead.
</Warning>

***

## Display settings

Configure how the browser appears to websites. These settings affect geolocation detection and content rendering.

### Locale and timezone

```bash .env theme={null}
# Optional, unset by default. Set to match your target region.
BROWSER_LOCALE=en-US
BROWSER_TIMEZONE=America/New_York
```

Set these to match your target audience or the expected user location. Mismatched locale/timezone can trigger bot detection on some sites.

Common combinations:

| Region  | BROWSER\_LOCALE | BROWSER\_TIMEZONE     |
| ------- | --------------- | --------------------- |
| US East | `en-US`         | `America/New_York`    |
| US West | `en-US`         | `America/Los_Angeles` |
| UK      | `en-GB`         | `Europe/London`       |
| Germany | `de-DE`         | `Europe/Berlin`       |
| Japan   | `ja-JP`         | `Asia/Tokyo`          |

### Viewport size

```bash .env theme={null}
BROWSER_WIDTH=1920
BROWSER_HEIGHT=1080
```

The default 1920x1080 works for most sites.

***

## Timeout settings

Control how long Skyvern waits for various browser operations.

```bash .env theme={null}
# Time to wait for individual actions (clicks, typing)
BROWSER_ACTION_TIMEOUT_MS=5000

# Time to wait for screenshots to capture
BROWSER_SCREENSHOT_TIMEOUT_MS=20000

# Time to wait for page loads
BROWSER_LOADING_TIMEOUT_MS=60000

# Time to wait for DOM tree analysis
BROWSER_SCRAPING_BUILDING_ELEMENT_TREE_TIMEOUT_MS=60000
```

### When to adjust timeouts

| Symptom                              | Adjustment                                                   |
| ------------------------------------ | ------------------------------------------------------------ |
| Actions fail on slow sites           | Increase `BROWSER_ACTION_TIMEOUT_MS`                         |
| Screenshots timeout on complex pages | Increase `BROWSER_SCREENSHOT_TIMEOUT_MS`                     |
| Page load timeouts                   | Increase `BROWSER_LOADING_TIMEOUT_MS`                        |
| DOM analysis fails on large pages    | Increase `BROWSER_SCRAPING_BUILDING_ELEMENT_TREE_TIMEOUT_MS` |

***

## Advanced settings

### Browser logging

```bash .env theme={null}
BROWSER_LOGS_ENABLED=true
```

When enabled, browser console logs are captured in artifacts. Useful for debugging JavaScript errors on target sites.

### Maximum pages

```bash .env theme={null}
BROWSER_MAX_PAGES_NUMBER=10
```

Limits the number of browser tabs Skyvern can open simultaneously. Increase if your agents navigate multiple pages in parallel; decrease to reduce memory usage.

### Chrome policies

```bash .env theme={null}
BROWSER_POLICY_FILE=/etc/chromium/policies/managed/policies.json
```

Path to a Chrome policy file for enterprise configurations.

### Video recording path

```bash .env theme={null}
VIDEO_PATH=./videos
```

Directory where browser session recordings are saved. Recordings are useful for debugging but consume disk space.

***

## Memory considerations

Browser instances are memory-intensive. These are approximate guidelines. Actual usage depends on page complexity and browser settings.

| Concurrent tasks | Recommended RAM |
| ---------------- | --------------- |
| 1-2              | 4GB             |
| 3-5              | 8GB             |
| 6-10             | 16GB            |
| 10+              | 32GB+           |

If you experience out-of-memory errors:

1. Reduce `BROWSER_MAX_PAGES_NUMBER`
2. Use a smaller viewport (`BROWSER_WIDTH`, `BROWSER_HEIGHT`)
3. Run in headless mode (`BROWSER_TYPE=chromium-headless`)
4. Limit concurrent task execution

***

## Scaling browsers

The default Docker Compose setup runs one browser instance inside the Skyvern container. For higher concurrency:

### Option 1: Vertical scaling

Add more RAM to your server and increase `MAX_STEPS_PER_RUN` and `BROWSER_MAX_PAGES_NUMBER`.

### Option 2: Horizontal scaling

Deploy multiple Skyvern instances behind a load balancer. Each instance runs its own browser. See [Kubernetes Deployment](/developers/self-hosted/kubernetes) for orchestrated scaling.

### Option 3: External browser pool

Use a browser pool service like Browserless or your own Playwright grid, then connect via CDP:

```bash .env theme={null}
BROWSER_TYPE=cdp-connect
BROWSER_REMOTE_DEBUGGING_URL=http://browserless:3000/
```

***

## Next steps

<CardGroup cols={2}>
  <Card title="Proxy Setup" icon="shield" href="/developers/self-hosted/proxy">
    Configure proxies to avoid bot detection
  </Card>

  <Card title="Storage Configuration" icon="hard-drive" href="/developers/self-hosted/storage">
    Store recordings and artifacts in S3 or Azure Blob
  </Card>
</CardGroup>
