Playwright on Browserberg
Playwright connects to Browserberg over the Chrome DevTools Protocol. Your selectors, your fixtures, your assertions and your test runner all stay exactly as they are.
Connect in one line
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(
`wss://browserberg.com/v1/connect?token=${process.env.BB_TOKEN}`);
const context = browser.contexts()[0];
const page = await context.newPage();
await page.goto('https://portal.example.de');
await page.getByLabel('Benutzername').fill('...');
await page.getByRole('button', { name: 'Anmelden' }).click();
import os
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(
f"wss://browserberg.com/v1/connect?token={os.environ['BB_TOKEN']}")
page = browser.contexts[0].new_page()
page.goto("https://portal.example.de")
Details
| Protocol | Chrome DevTools Protocol over WebSocket |
|---|---|
| Playwright versions | 1.40 and later, Node and Python |
| Connect method | chromium.connectOverCDP / connect_over_cdp |
| Browser engine | Chromium |
| Session start, p50 target | under 1.5 seconds |
| Where sessions run | EU bare metal (OVHcloud) |
As of 2026-08-30
Things worth knowing
Use the existing context, not a fresh one
connectOverCDP attaches to a running browser. Calling browser.newContext() creates a second, empty context and loses the profile you restored. Take browser.contexts()[0].
Profiles survive between runs
Cookies, localStorage and IndexedDB are captured at the end of a session and restored at the start of the next, so a logged-in state persists without you replaying the login.
Playwright's own browser download is unnecessary
You are not launching a local browser, so playwright install can be skipped in CI. That usually saves more container build time than the automation itself takes.
Questions people actually ask
Do I still need `playwright install`?
No. You are attaching to a remote browser, not launching a local one, so the browser download can be dropped from your CI image. That usually saves more build time than the automation itself takes to run.
Why must I use browser.contexts()[0]?
connectOverCDP attaches to a browser that already has a context, and that context is where your restored profile lives. Calling newContext() gives you a second, empty one -- your cookies are there, just not in the context you are driving.
Do traces and video recording still work?
Tracing works, since it is a client-side feature. Video capture depends on the browser writing files locally, so use our session replay instead; it records the same thing without needing a shared filesystem.
Other integrations
- Puppeteer Puppeteer talks CDP natively, so connecting to Browserberg is a one-argument change from puppeteer.
- Selenium Selenium reaches Browserberg through Chrome's CDP support.
- Chrome DevTools Protocol If you would rather not use a driver library at all, a session is a plain CDP WebSocket.
- LangChain LangChain agents drive Browserberg today through Playwright's toolkit, pointed at a remote CDP endpoint.
- MCP A Model Context Protocol server that exposes Browserberg sessions as tools to any MCP client.
Point an existing script at us
Five browser hours free, no card. If it runs locally, it runs here with one line changed.