> ## Documentation Index
> Fetch the complete documentation index at: https://browseruse-0aece648-reagan-eng-5397-make-docs-better-for-ag.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Playwright

> Connect Playwright to a remote stealth browser over CDP — Python and TypeScript.

Run your Playwright scripts on Browser Use's cloud browsers. 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.

When to use this:

* You have existing Playwright scripts and want to run them on stealth infrastructure
* You need pixel-perfect control (screenshots, specific click coordinates, form filling)
* You want to combine agent tasks with manual browser automation

## Option 1: WebSocket URL (no SDK)

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

<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>

### 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. The SDK also gives you a `live_url` to [watch or embed the session](/cloud/browser/live-preview).

<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>

### Create response

`browsers.create()` wraps `POST https://api.browser-use.com/api/v3/browsers`, which returns `201` with:

```json theme={null}
{
  "id": "0d5f16f3-96cc-4d5f-a5a4-4a4d3b5f9d2e",
  "status": "active",
  "liveUrl": "https://live.browser-use.com?wss=...",
  "cdpUrl": "https://0d5f16f3.cdp1.browser-use.com",
  "timeoutAt": "2026-07-14T20:15:00Z",
  "startedAt": "2026-07-14T20:00:00Z",
  "finishedAt": null,
  "proxyUsedMb": "0.0",
  "proxyCost": "0.0",
  "browserCost": "0.0",
  "agentSessionId": null,
  "recordingUrl": null
}
```

Field names are camelCase in the REST API and TypeScript SDK (`cdpUrl`, `liveUrl`) and snake\_case in the Python SDK (`cdp_url`, `live_url`). `cdpUrl` and `liveUrl` are nullable — check them before connecting.

### Stopping a session over REST

There is no `POST /browsers/{id}/stop` endpoint. Stopping is an update:

```bash theme={null}
curl -X PATCH "https://api.browser-use.com/api/v3/browsers/$SESSION_ID" \
  -H "X-Browser-Use-API-Key: $BROWSER_USE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "stop"}'
```

## Gotchas

<Note>
  Use `connect_over_cdp()` / `connectOverCDP()`, **not** `connect()`. Playwright's `connect()` expects a Playwright-protocol server and fails against a CDP endpoint with an opaque `Protocol error (Browser.getVersion)`.
</Note>

* **Reuse the existing context.** The session already has a context and page open — use `browser.contexts[0].pages[0]` instead of `browser.new_context()`, so you keep the stealth fingerprint and any loaded [profile](/cloud/browser/playwright#query-parameters).
* **Closing the connection vs stopping the session.** With the WebSocket URL, disconnecting stops the browser. With the SDK, `pw_browser.close()` only disconnects your client — call `client.browsers.stop(browser.id)` to end the session.

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

## See also

* [Puppeteer](/cloud/browser/puppeteer) and [Selenium](/cloud/browser/selenium) connections
* [Live preview & recording](/cloud/browser/live-preview) — watch the session or embed it in your app
* [Proxies](/cloud/browser/proxies) and [stealth](/cloud/browser/stealth) configuration
