System Architecture
Components
Chrome Extension
The extension acts as a bridge between your browser tabs and the relay server:- Uses
chrome.debuggerAPI to attach to tabs where you click the extension icon - Connects to WebSocket server at
localhost:19988via the/extensionendpoint - Receives Chrome DevTools Protocol (CDP) commands from Playwright clients
- Sends CDP events (page loads, network activity, etc.) back to clients
- Automatically reconnects when the relay server restarts
- Only controls tabs where the icon was clicked (green = active, gray = inactive)
- Survives server restarts by reconnecting with the same stable key
- Shows Chrome’s automation banner on controlled tabs for transparency
WebSocket Relay Server
The relay server runs onlocalhost:19988 and routes CDP messages:
Source: playwriter/src/relay-state.ts
/extension- WebSocket endpoint for Chrome extension connections/cdp/:clientId- CDP endpoint for Playwright clients (MCP, CLI, programmatic use)- Maintains session state using Zustand for deterministic state transitions
- Handles reconnections without losing client sessions
- Logs all CDP traffic to
~/.playwriter/cdp.jsonlfor debugging
MCP Server
The Model Context Protocol server provides a singleexecute tool that:
- Spawns the relay server in the background if not running
- Connects to relay via Playwright’s
connectOverCDP()API - Executes JavaScript code in isolated session sandboxes
- Returns results back to AI agents (Claude, OpenCode, etc.)
playwriter/src/mcp.ts
Communication Flow
1. Extension → Relay → Client
When the extension attaches to a tab:2. Client → Relay → Extension
When a client sends a CDP command:Session Isolation
Playwriter provides isolated session sandboxes for multi-agent workflows:- Each session has its own
stateobject (persisted betweenexecute()calls) - Sessions share browser tabs (all agents see the same
context.pages()) - To avoid interference, agents create their own pages and store them in
state.page
Security
Playwriter is designed for local-only automation:- Local only: WebSocket server binds to
localhost:19988(not0.0.0.0) - Origin validation: Only accepts connections from official extension IDs
- Explicit consent: Only tabs where you clicked the extension icon are controlled
- Visible automation: Chrome shows automation banner on controlled tabs
- No remote access by default: Malicious websites cannot connect
Backward Compatibility
The WebSocket protocol between extension and relay must never introduce breaking changes. Extensions are distributed via Chrome Web Store and updates propagate slowly. The relay server must support older extension versions indefinitely. New features should be opt-in and detected via version negotiation (extension sends?v= query param on connect).
Debugging
All CDP traffic is logged to files for debugging:jq to analyze:
Related
- Sessions - Session isolation and state persistence
- State Management - How relay state is managed
- Accessibility Snapshots - How element refs work