Skip to content

Connect Playwright to a session

Point an existing Playwright script at a Browserberg session with one line: connectUrl carries a short-lived access token and connectOverCDP does the rest.

Last updated:

One line

A session is a Chrome DevTools Protocol endpoint. chromium.connectOverCDP(session.connectUrl) replaces chromium.launch(), and the script you already have runs against a browser in the EU. The connectUrl on every session response carries an access token that the fleet checks at the WebSocket upgrade and that lives five minutes from the response that returned it; once the socket is open the token’s expiry no longer matters. A caller that waited longer re-mints with POST /v1/sessions/:id/connect-token, or simply fetches the session again.

Connect and drive

import { chromium } from 'playwright-core';
import { Browserberg } from '@browserberg/sdk';

const bb = new Browserberg({
  apiKey: process.env.BROWSERBERG_API_KEY!,
  baseUrl: 'https://browserberg.com',
});

// connectUrl carries a short-lived access token. Connect within five minutes
// of the call that returned it; sessions.connectToken() re-mints one later.
await using session = await bb.sessions.create({ ttlSeconds: 600 });
const browser = await chromium.connectOverCDP(session.connectUrl);

const [context] = browser.contexts();
const page = context.pages()[0] ?? (await context.newPage());
await page.goto('https://example.com');
console.log('title:', await page.title());
console.log('token expires:', session.connectUrlExpiresAt ? 'set' : 'not set');

await browser.close();

Re-mint a connect token

BASE="https://browserberg.com"
AUTH="Authorization: Bearer $BROWSERBERG_API_KEY"

SID=$(curl -s -X POST "$BASE/v1/sessions" -H "$AUTH" -H "Content-Type: application/json" -d '{"ttlSeconds": 300}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["session"]["id"])')

# A fresh connect URL for a caller that waited longer than the token in the create response lives.
curl -s -X POST "$BASE/v1/sessions/$SID/connect-token" -H "$AUTH" \
  | python3 -c 'import json,sys; t=json.load(sys.stdin); print("has token:", "?t=" in t["connectUrl"]); print("expires:", "expiresAt" in t)'

curl -s -X DELETE "$BASE/v1/sessions/$SID" -H "$AUTH" -o /dev/null -w 'released: %{http_code}\n'

What to know

Name Type Description
browser.contexts()[0] tip A session already has a context and a page. Reusing them keeps a restored profile; a fresh context does not.
browser.close() tip Closing over CDP does not release the session or capture its profile. Release through the API (`await using` in the TypeScript SDK does it on scope exit) and let the teardown path do the capture.
Token in the URL tip Treat `connectUrl` as a credential for five minutes: do not log it, and do not hand it to a model. The MCP tools strip it before it reaches one.