The relay server bridges Playwright with the Playwriter Chrome extension over WebSocket.
Starting the Server
startPlayWriterCDPRelayServer
Starts a WebSocket relay server that connects Playwright to your Chrome browser via the extension.
import { startPlayWriterCDPRelayServer } from 'playwriter'
const server = await startPlayWriterCDPRelayServer({
port: 19988,
host: '127.0.0.1',
token: 'optional-auth-token',
logger: console,
})
// Later:
server.close()
Parameters:
host
string
default:"127.0.0.1"
Host to bind the server to
Optional authentication token for remote access
Logger with log(...) and error(...) methods (e.g., console)
Returns: Promise<RelayServer>
type RelayServer = {
close(): void
on<K extends keyof RelayServerEvents>(event: K, listener: RelayServerEvents[K]): void
off<K extends keyof RelayServerEvents>(event: K, listener: RelayServerEvents[K]): void
}
Getting the CDP URL
getCdpUrl
Returns the WebSocket URL for connecting Playwright to the relay server.
import { getCdpUrl } from 'playwriter'
const url = getCdpUrl({ port: 19988 })
// 'ws://127.0.0.1:19988/cdp'
Parameters:
Returns: string - WebSocket URL for Playwright
Connecting with Playwright
Once the server is running, connect Playwright using connectOverCDP:
import { chromium } from 'playwright-core'
import { startPlayWriterCDPRelayServer, getCdpUrl } from 'playwriter'
const server = await startPlayWriterCDPRelayServer()
const browser = await chromium.connectOverCDP(getCdpUrl())
const page = browser.contexts()[0].pages()[0]
await page.goto('https://example.com')
// Don't call browser.close() - it closes the user's Chrome!
server.close()
Never call browser.close() when connected to the user’s Chrome - it will close all their tabs!
Remote Access
For remote access over the internet or LAN, use the token parameter:
Host:
npx -y playwriter serve --token my-secret
Client:
const browser = await chromium.connectOverCDP(
'ws://remote-host:19988/cdp?token=my-secret'
)
See Remote Access for more details on tunneling with traforo.
Server Events
The relay server emits events you can listen to:
server.on('cdp:command', ({ clientId, command }) => {
console.log('CDP command from Playwright:', command.method)
})
server.on('cdp:event', ({ event, sessionId }) => {
console.log('CDP event from extension:', event.method)
})
server.on('cdp:response', ({ clientId, response }) => {
console.log('CDP response to Playwright')
})
Multiple Extensions
If you have multiple Chrome profiles with Playwriter installed, specify which one to use:
const url = getCdpUrl({ port: 19988, extensionId: 'profile:user@example.com' })
const browser = await chromium.connectOverCDP(url)
The relay server automatically selects the extension with active tabs if only one is active.