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

# Playwright, Puppeteer, Selenium

> Connect your automation framework to Browser Use's stealth infrastructure via CDP.

Every session runs in a [hardened Chromium fork](/cloud/browser/stealth) with stealth, anti-fingerprinting, and [residential proxies](/cloud/browser/proxies) enabled by default — no configuration needed.

## Option 1: WebSocket URL (no SDK)

Connect with a single URL. All configuration is passed as query parameters.

### Playwright

<CodeGroup>
  ```python Python theme={null}
  from playwright.async_api import async_playwright

  WSS_URL = "wss://connect.browser-use.com?apiKey=YOUR_API_KEY&proxyCountryCode=us"

  async with async_playwright() as p:
      browser = await p.chromium.connect_over_cdp(WSS_URL)
      page = browser.contexts[0].pages[0]
      await page.goto("https://example.com")
      print(await page.title())
      await browser.close()
  # Browser is automatically stopped when the WebSocket disconnects
  ```

  ```typescript TypeScript theme={null}
  import { chromium } from "playwright";

  const WSS_URL = "wss://connect.browser-use.com?apiKey=YOUR_API_KEY&proxyCountryCode=us";

  const browser = await chromium.connectOverCDP(WSS_URL);
  const page = browser.contexts()[0].pages()[0];
  await page.goto("https://example.com");
  console.log(await page.title());
  await browser.close();
  // Browser is automatically stopped when the WebSocket disconnects
  ```
</CodeGroup>

### Puppeteer

```typescript theme={null}
import puppeteer from "puppeteer-core";

const WSS_URL = "wss://connect.browser-use.com?apiKey=YOUR_API_KEY&proxyCountryCode=us";

const browser = await puppeteer.connect({ browserWSEndpoint: WSS_URL });
const [page] = await browser.pages();
await page.goto("https://example.com");
console.log(await page.title());
await browser.close();
```

### Selenium

Selenium requires a local WebSocket proxy to connect to Browser Use's remote CDP endpoint. Use [selenium-wire](https://github.com/wkeeling/selenium-wire) or connect through Playwright's CDP bridge instead:

```python theme={null}
from playwright.sync_api import sync_playwright

WSS_URL = "wss://connect.browser-use.com?apiKey=YOUR_API_KEY&proxyCountryCode=us"

with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(WSS_URL)
    page = browser.contexts[0].pages[0]
    page.goto("https://example.com")
    print(page.title())
    browser.close()
```

<Note>
  Selenium's `debugger_address` only supports local `host:port` connections. For remote CDP over WebSocket, use Playwright or Puppeteer instead.
</Note>

## Query parameters

| Parameter             | Type     | Description                                                  |
| --------------------- | -------- | ------------------------------------------------------------ |
| `apiKey`              | `string` | **Required.** Your Browser Use API key.                      |
| `proxyCountryCode`    | `string` | Proxy country code (e.g. `us`, `de`, `jp`). 195+ countries.  |
| `profileId`           | `string` | Load a saved browser profile (cookies, localStorage).        |
| `timeout`             | `int`    | Session timeout in minutes. Default: 15. Max: 240 (4 hours). |
| `browserScreenWidth`  | `int`    | Browser width in pixels.                                     |
| `browserScreenHeight` | `int`    | Browser height in pixels.                                    |

## Option 2: SDK

Create a browser via the SDK, get a `cdp_url`, and connect with Playwright or Puppeteer.

### Playwright

<CodeGroup>
  ```python Python theme={null}
  from browser_use_sdk.v3 import AsyncBrowserUse
  from playwright.async_api import async_playwright

  client = AsyncBrowserUse()
  browser = await client.browsers.create()
  print(browser.cdp_url)   # https://uuid.cdpN.browser-use.com
  print(browser.live_url)  # https://live.browser-use.com?wss=...

  async with async_playwright() as p:
      pw_browser = await p.chromium.connect_over_cdp(browser.cdp_url)
      page = pw_browser.contexts[0].pages[0]
      await page.goto("https://example.com")
      print(await page.title())
      await pw_browser.close()

  await client.browsers.stop(browser.id)
  ```

  ```typescript TypeScript theme={null}
  import { BrowserUse } from "browser-use-sdk/v3";
  import { chromium } from "playwright";

  const client = new BrowserUse();
  const browser = await client.browsers.create();
  console.log(browser.cdpUrl);  // https://uuid.cdpN.browser-use.com
  console.log(browser.liveUrl); // https://live.browser-use.com?wss=...

  const pwBrowser = await chromium.connectOverCDP(browser.cdpUrl);
  const page = pwBrowser.contexts()[0].pages()[0];
  await page.goto("https://example.com");
  console.log(await page.title());
  await pwBrowser.close();

  await client.browsers.stop(browser.id);
  ```
</CodeGroup>

### Puppeteer

```typescript theme={null}
import { BrowserUse } from "browser-use-sdk/v3";
import puppeteer from "puppeteer-core";

const client = new BrowserUse();
const browser = await client.browsers.create();

// Puppeteer needs the WebSocket URL from /json/version
const resp = await fetch(`${browser.cdpUrl}/json/version`);
const { webSocketDebuggerUrl } = await resp.json();

const pwBrowser = await puppeteer.connect({ browserWSEndpoint: webSocketDebuggerUrl });
const [page] = await pwBrowser.pages();
await page.goto("https://example.com");
console.log(await page.title());
await pwBrowser.close();

await client.browsers.stop(browser.id);
```

<Warning>
  Always stop browser sessions when done. Sessions left running will continue to incur charges until the timeout expires.
</Warning>
