Doramagic Project Pack · Human Manual
playwright
Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine
Playwright Introduction and Project Overview
Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Package Ecosystem and Monorepo Structure, Test Runner and Execution Engine
Playwright Introduction and Project Overview
1. Overview
Playwright is a powerful end-to-end testing framework developed by Microsoft that enables reliable browser automation. It supports testing across multiple browsers (Chromium, Firefox, WebKit) with a single unified API, making it ideal for modern web application testing.
The project provides comprehensive tools for browser automation, test execution, debugging, and trace inspection. Playwright is designed to handle complex web scenarios including single-page applications, modern JavaScript frameworks, and sophisticated user interactions.
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
2. Project Architecture
2.1 Core Packages
The Playwright project is organized as a monorepo with several key packages:
| Package | Purpose |
|---|---|
playwright | Main package with full test runner and all browser support |
playwright-core | Core browser automation library without bundled browsers |
trace-viewer | Web-based trace analysis and visualization tool |
html-reporter | Test report generation and visualization |
injected | In-browser script injection utilities |
2.2 High-Level Architecture
graph TD
A[Playwright Test Runner] --> B[playwright-core]
B --> C[Browser Drivers]
C --> D[Chromium]
C --> E[Firefox]
C --> F[WebKit]
B --> G[Connection Layer]
G --> H[Channel Owners]
H --> I[Page]
H --> J[Request/Response]
H --> K[Route]
H --> L[Tracing]
H --> M[WebSocket]
A --> N[HTML Reporter]
A --> O[Trace Viewer]Sources: packages/playwright-core/src/client/connection.ts
2.3 Channel Owner System
Playwright uses a channel-based communication system where various browser objects are managed through factory functions:
graph LR
A[Local Utils] --> B[Page]
A --> C[Playwright]
A --> D[Request]
A --> E[Response]
A --> F[Route]
A --> G[Tracing]
A --> H[WebSocket]The connection layer registers object factories for different types:
Page: (parent, type, guid, init) => new Page(parent, type, guid, init),
Request: (parent, type, guid, init) => new Request(parent, type, guid, init),
Response: (parent, type, guid, init) => new Response(parent, type, guid, init),
Route: (parent, type, guid, init) => new Route(parent, type, guid, init),
Tracing: (parent, type, guid, init) => new Tracing(parent, type, guid, init),
Sources: packages/playwright-core/src/client/connection.ts:1-20
3. Browser Automation Capabilities
3.1 CLI Client (playwright-cli)
The CLI client provides an interactive shell for browser automation tasks:
| Command Category | Features |
|---|---|
| Navigation | goto, back, forward, reload |
| Interaction | click, fill, type, check, select |
| Capture | screenshot, pdf, snapshot |
| Tabs | tab-list, tab-new, tab-close, tab-select |
| Storage | state-save, state-load, cookie-*, localstorage-* |
| Network | route, unroute, route-list |
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
3.2 Injected Script API
When Playwright injects scripts into web pages, a dedicated API becomes available:
window.playwright = {
$: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
$$: (selector: string) => this._querySelectorAll(selector),
inspect: (selector: string) => this._inspect(selector),
selector: (element: Element) => this._selector(element),
generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => this._ariaSnapshot(element, options),
resume: () => this._resume(),
...new Locator(this._injectedScript, ''),
};
The injected script is automatically installed on page load and provides DOM querying, locator generation, and ARIA snapshot capabilities.
Sources: packages/injected/src/consoleApi.ts
3.3 ARIA Role Utilities
Playwright automatically maps HTML elements to ARIA roles for accessibility testing:
| Element | Role Mapping |
|---|---|
<H1> - <H6> | heading |
<BUTTON> | button |
<A> | link |
<INPUT type="search"> | searchbox / combobox (with list) |
<DIALOG> | dialog |
<NAV> | navigation |
<HEADER> | banner (unless landmark prevented) |
<FOOTER> | contentinfo (unless landmark prevented) |
<IMG alt=""> | presentation (empty alt, no title) |
'INPUT': (e: Element) => {
const type = (e as HTMLInputElement).type.toLowerCase();
if (type === 'search')
return e.hasAttribute('list') ? 'combobox' : 'searchbox';
// ...
}
Sources: packages/injected/src/roleUtils.ts
4. Test Execution Framework
4.1 Running Tests
Playwright tests are executed using the standard Playwright test runner:
# Run all tests
PLAYWRIGHT_HTML_OPEN=never npx playwright test
# Run with custom npm script
PLAYWRIGHT_HTML_OPEN=never npm run special-test-command
The environment variable PLAYWRIGHT_HTML_OPEN=never prevents the interactive HTML report from opening automatically.
Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md
4.2 Debug Mode
Debugging tests uses the CLI debug mode which pauses execution and provides debugging instructions:
PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli
When debugging instructions appear with a session name (e.g., tw-abcdef), attach using:
playwright-cli attach tw-abcdef
Available debugging commands:
| Command | Purpose |
|---|---|
playwright-cli resume | Resume test execution |
playwright-cli snapshot | Get inventory of interactive elements |
playwright-cli click e5 | Interact with element by ref |
playwright-cli eval | Read URL/state |
playwright-cli show --annotate | Request user annotation |
Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md
5. Browser Session Management
5.1 Named Sessions
Playwright CLI supports multiple named browser sessions:
# Create new browser session named "mysession" with persistent profile
playwright-cli -s=mysession open example.com --persistent
# Use specific session
playwright-cli -s=mysession click e6
# Close named browser
playwright-cli -s=mysession close
# Delete user data for persistent session
playwright-cli -s=mysession delete-data
5.2 Global Session Management
# List all browser sessions
playwright-cli list
# Close all browsers
playwright-cli close-all
# Forcefully kill all browser processes
playwright-cli kill-all
5.3 Environment Variable
Set a default session via environment variable:
export PLAYWRIGHT_CLI_SESSION="mysession"
playwright-cli open example.com # Uses "mysession" automatically
Sources: packages/playwright-core/src/tools/cli-client/skill/references/session-management.md
6. Trace Viewer
6.1 Overview
The Trace Viewer is a Progressive Web App for analyzing Playwright traces locally without sending data elsewhere:
graph LR
A[Playwright Test] --> B[Trace.zip]
B --> C[Trace Viewer]
C --> D[Actions View]
C --> E[Requests View]
C --> F[Console View]
C --> G[Snapshots]6.2 CLI Trace Commands
# Open and inspect trace
npx playwright trace open <trace.zip>
# List all actions
npx playwright trace actions
# Filter actions by pattern
npx playwright trace actions --grep "click"
# Show only failed actions
npx playwright trace actions --errors-only
# View specific action details
npx playwright trace action <action-id>
# View DOM snapshot for action
npx playwright trace snapshot <action-id>
# Evaluate JavaScript on snapshot
npx playwright trace snapshot <action-id> -- eval "document.body.outerHTML"
# Export attachments
npx playwright trace attachments
npx playwright trace attachment 1 -o out.png
6.3 Typical Investigation Workflow
# 1. Open the trace
npx playwright trace open test-results/my-test/trace.zip
# 2. View all actions
npx playwright trace actions
# 3. Find failed actions
npx playwright trace actions --errors-only
# 4. Inspect specific action
npx playwright trace action 12
# 5. View page state at that moment
npx playwright trace snapshot 12
# 6. Query DOM for details
npx playwright trace snapshot 12 -- eval "document.querySelector('.error-message').textContent"
# 7. Check network failures
npx playwright trace requests --failed
# 8. Check console errors
npx playwright trace console --errors-only
Sources: packages/playwright-core/src/tools/trace/SKILL.md
6.4 Trace Viewer UI Components
The trace viewer web application includes:
| Component | File | Purpose |
|---|---|---|
| WorkbenchLoader | workbenchLoader.tsx | Main application entry, handles file uploads and drag-drop |
| BrowserFrame | browserFrame.tsx | Renders browser chrome with address bar |
| MetadataView | metadataView.tsx | Displays test metadata (viewport, user agent, baseURL) |
| TestCaseView | testCaseView.tsx | Shows individual test case details and results |
The workbench loader provides a progressive web app experience with local-only processing:
<div className='info'>Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere,
it opens it locally.</div>
Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx
7. Key Features Summary
| Feature | Description |
|---|---|
| Cross-browser | Chromium, Firefox, WebKit support with single API |
| Auto-waiting | Actions wait for elements to be actionable |
| Web-first assertions | Built-in assertion library |
| Tracing | Comprehensive action tracing and debugging |
| Locators | Multiple strategies: CSS, ARIA, text, role |
| Network interception | Mock and modify network requests |
| Storage state | Save/restore authentication and cookies |
| CLI tools | Interactive browser automation shell |
8. Architecture Diagram: End-to-End Test Flow
sequenceDiagram
participant T as Test
participant R as Playwright Runner
participant C as CLI Client
participant P as Browser
participant TV as Trace Viewer
T->>R: npx playwright test
R->>P: Launch browser
R->>P: Inject script
T->>C: playwright-cli attach
Note over C,P: Interactive debugging
P->>TV: Generate trace.zip
TV->>T: Analyze failures9. Resources and Further Reading
- Main Documentation: Playwright CLI capabilities and commands
- Test Debugging: Debug mode and CLI attachment workflow
- Trace Analysis: Using trace viewer for post-mortem analysis
- Session Management: Multi-browser concurrent testing patterns
- Storage State: Authentication and state persistence patterns
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
Package Ecosystem and Monorepo Structure
Related topics: Playwright Introduction and Project Overview, Client-Server Communication Architecture
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Playwright Introduction and Project Overview, Client-Server Communication Architecture
Package Ecosystem and Monorepo Structure
Playwright is organized as a monorepo using npm workspaces, enabling centralized version management and shared tooling across multiple specialized packages. The repository contains the main playwright package alongside browser-specific packages, core libraries, and supporting tools.
Repository Overview
The Playwright monorepo follows a multi-package architecture where:
- The root
package.jsondefines shared scripts, build tooling, and workspace configuration - Individual packages under
packages/contain focused, modular functionality - Examples under
examples/demonstrate real-world usage patterns
graph TD
Root[Root package.json<br/>v1.61.0-next] --> Core[playwright-core]
Root --> Main[playwright]
Root --> Chromium[playwright-browser-chromium]
Root --> Firefox[playwright-browser-firefox]
Root --> Webkit[playwright-browser-webkit]
Root --> Injected[injected]
Root --> TraceViewer[trace-viewer]
Root --> HtmlReporter[html-reporter]
Core --> Injected
Main --> Core
Chromium --> Core
Firefox --> Core
Webkit --> CoreCore Packages
playwright
The main public package that provides the high-level API for browser automation. It re-exports types and utilities from playwright-core while bundling browser automation capabilities.
playwright-core
The foundational package containing all browser automation logic. This package:
- Defines client-side abstractions (
Page,Request,Response,Route,WebSocket,Worker) - Manages channel-based communication between client and server
- Implements the
LocalUtilsfactory for shared utilities
The connection layer registers object factories for all domain objects:
registerObjectFactories({
LocalUtils: (parent, type, guid, init) => {
const result = new LocalUtils(parent, type, guid, init);
if (!this._localUtils)
this._localUtils = result;
return result;
},
Page: (parent, type, guid, init) => new Page(parent, type, guid, init),
Request: (parent, type, guid, init) => new Request(parent, type, guid, init),
Response: (parent, type, guid, init) => new Response(parent, type, guid, init),
Route: (parent, type, guid, init) => new Route(parent, type, guid, init),
Tracing: (parent, type, guid, init) => new Tracing(parent, type, guid, init),
WebSocket: (parent, type, guid, init) => new WebSocket(parent, type, guid, init),
Worker: (parent, type, guid, init) => new Worker(parent, type, guid, init),
});
Sources: packages/playwright-core/src/client/connection.ts:10-35
Browser Packages
Browser-specific packages provide automatic browser installation and management. Each package depends on playwright-core.
| Package | Purpose | Dependencies |
|---|---|---|
playwright-browser-chromium | Chromium browser support | playwright-core |
playwright-browser-firefox | Firefox browser support | playwright-core |
playwright-browser-webkit | WebKit browser support | playwright-core |
The browser packages expose a standard interface:
{
"name": "@playwright/browser-webkit",
"version": "1.61.0-next",
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.mjs",
"require": "./index.js",
"default": "./index.js"
}
},
"dependencies": {
"playwright-core": "1.61.0-next"
}
}
Sources: packages/playwright-browser-webkit/package.json
Injected Scripts Package
The injected package contains scripts that run within the browser context, providing accessibility utilities and developer inspection capabilities.
Console API Installation
The injected script installs a playwright object onto window when install() is called:
install() {
if (this._injectedScript.window.playwright)
return;
this._injectedScript.window.playwright = {
$: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
$$: (selector: string) => this._querySelectorAll(selector),
inspect: (selector: string) => this._inspect(selector),
selector: (element: Element) => this._selector(element),
generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => {
return this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body, options || { mode: 'default' });
},
resume: () => this._resume(),
...new Locator(this._injectedScript, ''),
};
}
Sources: packages/injected/src/consoleApi.ts:10-30
Role Utilities
The roleUtils.ts file maps HTML elements to their ARIA roles for accessibility testing:
'DIALOG': () => 'dialog',
'FORM': (e: Element) => hasExplicitAccessibleName(e) ? 'form' : null,
'HEADER': (e: Element) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : 'banner',
'IMG': (e: Element) => (e.getAttribute('alt') === '') && !e.getAttribute('title') && !hasGlobalAriaAttribute(e) && !hasTabIndex(e) ? 'presentation' : 'img',
Sources: packages/injected/src/roleUtils.ts:1-50
Tooling Packages
trace-viewer
A React-based Progressive Web Application for inspecting Playwright trace files. The trace viewer provides:
- Drop-zone interface for loading trace files locally
- Progress dialogs for trace processing
- Version display showing the Playwright version
- No data transmission—opens files locally
<div className='info'>Playwright Trace Viewer is a Progressive Web App, it does not send your trace anywhere,
it opens it locally.</div>
<div className='version'>Playwright v{__APP_VERSION__}</div>
Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx:1-30
html-reporter
Generates HTML test reports with:
- Test case location linking
- Duration tracking
- Project and tag labeling
- Annotation display
- Retry labeling for failed tests
<CopyToClipboardContainer value={`${test.location.file}:${test.location.line}`}>
{test.location.file}:{test.location.line}
</CopyToClipboardContainer>
<TraceLink test={test} trailingSeparator={true} />
<div className='test-case-duration'>{msToString(test.duration)}</div>
Sources: packages/html-reporter/src/testCaseView.tsx:1-30
CLI Tools
playwright-cli
A command-line tool for browser automation and page interaction. Available commands include:
# Core commands
playwright-cli open # Open browser
playwright-cli goto <url> # Navigate
playwright-cli click <element> # Click element
playwright-cli type <text> # Type text
# Snapshot and evaluation
playwright-cli snapshot # Get page snapshot
playwright-cli eval "code" # Execute JS
# Tab management
playwright-cli tab-list # List tabs
playwright-cli tab-new <url> # New tab
# State management
playwright-cli state-save <file> # Save state
playwright-cli state-load <file> # Load state
# Network interception
playwright-cli route "<pattern>" # Intercept routes
playwright-trace
Inspect trace files from the command line:
npx playwright trace open <trace.zip> # Open and extract trace
npx playwright trace actions # List all actions
npx playwright trace action <action-id> # View action details
npx playwright trace console # View console messages
npx playwright trace errors # View errors
npx playwright trace snapshot <action-id> # View DOM snapshot
npx playwright trace close # Close trace
Build and Test Scripts
The root package.json defines comprehensive test and lint scripts:
| Script | Purpose |
|---|---|
ctest | Chromium tests |
ftest | Firefox tests |
wtest | WebKit tests |
atest | Android tests |
etest | Electron tests |
itest | Installation tests |
stest | Stress tests |
biditest | BiDi protocol tests |
ttest | Playwright Test runner tests |
lint | Full linting suite |
tsc | TypeScript compilation |
{
"scripts": {
"ctest": "playwright test --config=tests/library/playwright.config.ts --project=chromium-*",
"ftest": "playwright test --config=tests/library/playwright.config.ts --project=firefox-*",
"wtest": "playwright test --config=tests/library/playwright.config.ts --project=webkit-*",
"test": "playwright test --config=tests/library/playwright.config.ts",
"eslint": "eslint --cache",
"tsc": "tsc -p ."
}
}
Sources: package.json:1-50
Monorepo Structure Summary
graph TD
subgraph "Root"
RootPkg[package.json<br/>v1.61.0-next]
end
subgraph "Core Packages"
Core[playwright-core<br/>Automation core]
Injected[injected<br/>Browser scripts]
end
subgraph "Public Packages"
Main[playwright<br/>Main API]
Chromium[playwright-browser-chromium]
Firefox[playwright-browser-firefox]
Webkit[playwright-browser-webkit]
end
subgraph "Tooling"
CLI[playwright-cli<br/>CLI tool]
Trace[playwright-trace<br/>Trace CLI]
Viewer[trace-viewer<br/>Trace PWA]
Reporter[html-reporter<br/>Test reports]
end
subgraph "Examples"
Todo[todomvc]
Svgomg[svgomg]
end
Main --> Core
Chromium --> Core
Firefox --> Core
Webkit --> Core
CLI --> Core
Trace --> Core
Viewer --> Core
Reporter --> Core
Core --> InjectedPackage Versioning
All packages in the monorepo share the same version number for consistency:
{
"version": "1.61.0-next",
"engines": {
"node": ">=18"
}
}
Browser packages declare explicit dependencies on playwright-core:
"dependencies": {
"playwright-core": "1.61.0-next"
}
This ensures version alignment across the ecosystem while allowing independent releases when necessary.
Sources: packages/playwright-core/src/client/connection.ts:10-35
Client-Server Communication Architecture
Related topics: Package Ecosystem and Monorepo Structure, Browser Launch and Process Management
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Package Ecosystem and Monorepo Structure, Browser Launch and Process Management
Client-Server Communication Architecture
Overview
Playwright's Client-Server Communication Architecture enables the automation of web browsers through a well-defined message-passing system. The architecture separates the client API (used by test developers) from the server-side browser automation engine, allowing tests to control Chromium, Firefox, and WebKit browsers running either locally or in remote environments.
High-Level Architecture
graph TD
subgraph Client["Client Side (Node.js)"]
API[Test API<br/>playwright.click()]
CO[ChannelOwner<br/>Base Class]
CONN[Connection]
end
subgraph Server["Server Side (Node.js + Browser)"]
DIS[Dispatcher]
CH[Channel Handlers]
BR[Browser<br/>Chromium/Firefox/WebKit]
end
API --> CO
CO --> CONN
CONN -->|Protocol Messages| DIS
DIS --> CH
CH --> BR
style Client fill:#e1f5fe
style Server fill:#fff3e0The architecture follows a factory pattern where the Connection class registers object factories for all protocol-defined objects. When the client creates a Page or BrowserContext, the corresponding factory is invoked to create a client-side proxy object.
Core Components
ChannelOwner (Client-Side Base Class)
The ChannelOwner class serves as the base for all client-side objects that communicate with the server. It provides:
- Message routing: Sends commands to the server and receives responses
- Event handling: Subscribes to server-side events
- Lifecycle management: Tracks object disposal and cleanup
| Property | Type | Description | |
|---|---|---|---|
channel | Channel | The communication channel to the server | |
connection | Connection | Reference to the parent connection | |
guid | string | Unique identifier for this object | |
parent | `ChannelOwner \ | null` | Parent object in the hierarchy |
Sources: packages/playwright-core/src/client/channelOwner.ts
Connection (Client-Side Hub)
The Connection class manages all client-server communication and object lifecycle.
// Connection registers factories for all protocol objects
registerObjectFactories(factories: Record<string, ChannelFactory>) {
// Creates appropriate client-side objects for each type
}
Registered Object Factories:
| Object Type | Factory Creates | Purpose |
|---|---|---|
Browser | Browser instance | Main browser process |
BrowserContext | Context instance | Isolated browsing sessions |
Page | Page instance | Single tab/page |
Request | Request instance | HTTP request tracking |
Response | Response instance | HTTP response data |
Route | Route instance | Network request interception |
Tracing | Tracing instance | Trace collection |
WebSocket | WebSocket instance | WebSocket communication |
Worker | Worker instance | Web Workers |
LocalUtils | Utility instance | Local utility functions |
Sources: packages/playwright-core/src/client/connection.ts:1-50
Dispatcher (Server-Side Handler)
The Dispatcher class is the server-side counterpart that handles messages from clients.
graph LR
MSG[Incoming<br/>Message] --> DIS[Dispatcher]
DIS -->|Route| HAND[Channel Handler]
HAND -->|Execute| BR[Browser API]
BR -->|Result| RES[Response<br/>to Client]Key responsibilities:
- Deserialize incoming messages
- Route to appropriate channel handler
- Execute browser automation commands
- Send responses back to client
Sources: packages/playwright-core/src/server/dispatchers/dispatcher.ts
Protocol Channels
The protocol defines typed channels for all communication between client and server.
// Generated from protocol definitions
interface Channels {
Browser: {
// Methods
newContext(options?: BrowserNewContextOptions): Promise<BrowserContext>;
close(): Promise<void>;
// Events
on('disconnected', callback: () => void): void;
};
Page: {
click(selector: string, options?: PageClickOptions): Promise<void>;
fill(selector: string, value: string): Promise<void>;
// ...
};
}
Sources: packages/protocol/src/channels.d.ts
Communication Flow
Method Invocation Flow
sequenceDiagram
participant Client as Test Code
participant CO as ChannelOwner
participant CONN as Connection
participant Wire as Wire Protocol
participant DIS as Dispatcher
participant Impl as Implementation
Client->>CO: page.click('#button')
CO->>CONN: sendMessage('click', args)
CONN->>Wire: serialize & send
Wire->>DIS: deliver message
DIS->>Impl: invoke method
Impl-->>DIS: return result
DIS-->>Wire: send response
Wire-->>CONN: receive response
CONN-->>CO: deserialize result
CO-->>Client: Promise resolvesObject Creation Flow
When a client requests a new object (e.g., browser.newContext()):
- Server creates the implementation object
- Server creates a dispatcher wrapper
- Server returns the new object's channel reference to client
- Client's connection factory creates appropriate
ChannelOwnersubclass - Client receives a proxy object to interact with the new object
graph TD
subgraph Server["Server"]
IMPL[Implementation]
DISP[Dispatcher]
end
subgraph Client["Client"]
FACT[Factory]
PROXY[ChannelOwner Proxy]
end
IMPL -->|creates| DISP
DISP -->|returns guid| FACT
FACT -->|creates| PROXYRemote Connections
Playwright supports remote browser connections through PlaywrightConnection.
graph TD
subgraph Local["Test Machine"]
TEST[Test Code]
CLIENT[Local Client]
end
subgraph Remote["Remote Machine"]
SERVER[Playwright Server]
BROWSER[Browser]
end
TEST --> CLIENT
CLIENT -->|WebSocket| SERVER
SERVER --> BROWSERThe remote connection maintains the same channel-based communication but uses WebSocket transport instead of in-process communication.
Sources: packages/playwright-core/src/remote/playwrightConnection.ts
Message Protocol
Message Structure
interface ProtocolMessage {
id: string; // Unique message ID
guid: string; // Target object GUID
method: string; // Method name
params?: object; // Method parameters
type: 'request' | 'response' | 'event';
}
Event Subscription
Clients subscribe to server-side events through the channel system:
// Server emits event
dispatcher.dispatchEvent('eventName', payload);
// Client receives via callback
page.on('close', () => {
console.log('Page closed');
});
Object Hierarchy
graph TD
P[Playwright] --> BC[Browser]
BC --> BCT[BrowserContext]
BCT --> PGE[Page]
PGE --> W[Worker]
PGE --> R[Route]
BCT --> RS[Request]
BCT --> RS2[Response]
style P fill:#c8e6c9
style BC fill:#fff9c4
style BCT fill:#bbdefb
style PGE fill:#ffccbcAll objects inherit from ChannelOwner and maintain references to their parent connection.
Error Handling
The architecture handles errors through:
- Sync errors: Caught and returned as rejected promises
- Async errors: Propagated through the message response
- Disconnection: Server sends 'disconnected' event to notify clients
try {
await page.click('#missing');
} catch (e) {
// Error contains reason and stack
console.log(e.message); // Target closed, did you mean to close the browser?
}
Key Design Patterns
Factory Pattern
Object factories in Connection create the appropriate ChannelOwner subclass based on protocol type.
Proxy Pattern
ChannelOwner instances are proxies that forward method calls to the server.
Observer Pattern
Event subscriptions allow clients to react to server-side state changes.
Promise-based Async
All operations return Promises, enabling async/await usage in tests.
Summary
Playwright's Client-Server Communication Architecture provides:
- Type safety: Protocol definitions ensure consistent interfaces
- Location transparency: Local and remote execution use the same API
- Extensibility: New object types can be added to the protocol
- Performance: Optimized message serialization and batching
- Debuggability: Clear message flow between components
Sources: packages/playwright-core/src/client/channelOwner.ts
Browser Launch and Process Management
Related topics: Client-Server Communication Architecture, Browser Implementations and Protocol Support
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Client-Server Communication Architecture, Browser Implementations and Protocol Support
Browser Launch and Process Management
Overview
Browser Launch and Process Management is a core subsystem in Playwright responsible for spawning, communicating with, and lifecycle-managing browser processes. This subsystem abstracts the complexity of launching different browser types (Chromium, Firefox, WebKit) across different environments, handling both in-process and out-of-process execution models while maintaining reliable communication channels.
The system provides:
- Cross-browser abstraction - Unified API for launching Chromium, Firefox, and WebKit
- Process lifecycle management - Spawning, health monitoring, graceful termination
- Dual execution modes - In-process and out-of-process browser execution
- Transport layer abstraction - Message-based IPC between Node.js and browser processes
- Resource cleanup - Proper disposal of browser instances and associated resources
Sources: packages/playwright-core/src/server/browserType.ts:1-50
Architecture
High-Level Components
graph TD
A[Playwright Client API] --> B[BrowserType]
B --> C{Launch Mode}
C -->|Out-of-Process| D[OutOfProcess]
C -->|In-Process| E[InProcess]
D --> F[ProcessLauncher]
D --> G[Transport Layer]
E --> H[BrowserProcess]
F --> I[Browser Executable]
G --> J[Browser Server]
H --> ICore Component Roles
| Component | Package | Responsibility |
|---|---|---|
BrowserType | playwright-core | Entry point for browser launching, delegates to appropriate implementation |
OutOfProcess | playwright-core | Manages out-of-process browser execution with separate server process |
InProcess | playwright-core | Manages in-process browser execution within Node.js |
ProcessLauncher | utils | Core process spawning and management utilities |
Transport | playwright-core | Message-based IPC communication layer |
Browser | playwright-core | Abstract browser base class with lifecycle management |
Sources: packages/playwright-core/src/server/browserType.ts:1-100
Launch Modes
Playwright supports two distinct browser launch modes, each suited for different use cases.
Out-of-Process Mode
The out-of-process (OOP) mode spawns browser processes as separate OS processes, with communication handled via WebSocket or pipe-based transport layers.
Characteristics:
- Process isolation - Browser crashes do not affect the Node.js process
- Cross-language support - Enables Playwright bindings in languages other than Node.js
- Resource efficiency - Better for running multiple browser instances
- Security - Browser runs in separate sandboxed process
graph LR
A[Node.js Process] <-->|WebSocket/Pipes| B[Browser Server Process]
B --> C[Browser Executable]The OutOfProcess class handles:
- Spawning the browser server executable
- Establishing transport connection
- Handshake and version negotiation
- Proxying API calls to the browser
Sources: packages/playwright-core/src/outofprocess.ts:1-80
In-Process Mode
The in-process mode runs browser execution within the Node.js process itself, useful for scenarios requiring tighter integration.
Characteristics:
- Direct execution - No inter-process communication overhead
- Debugging simplicity - Easier to debug browser and client code together
- Shared memory - Direct access to browser resources
- Limited isolation - Browser crashes may affect Node.js process
The InProcess class provides a simplified launch path that instantiates browser internals directly without spawning separate processes.
Sources: packages/playwright-core/src/inprocess.ts:1-60
Mode Selection
// Out-of-process (default)
const browser = await chromium.launch({ headless: true });
// In-process via browser type's `launchServer`
const server = await chromium.launchServer({ headless: true });
Process Lifecycle
Launch Sequence
sequenceDiagram
participant Client
participant BrowserType
participant Launcher
participant Browser
participant Transport
Client->>BrowserType: launch(options)
BrowserType->>Launcher: spawn(executable, args)
Launcher->>Browser: new Browser(transport)
Browser->>Transport: connect()
Transport-->>Browser: connection established
Browser->>Browser: initialize()
Browser-->>BrowserType: ready
BrowserType-->>Client: Browser instanceLifecycle States
| State | Description | Transitions |
|---|---|---|
Launching | Process is being spawned | → Connected or Failed |
Connected | Transport layer established | → Initialized or Closed |
Initialized | Browser fully ready | → Closed |
Failed | Launch or initialization failed | Terminal state |
Closed | Browser process terminated | Terminal state |
Sources: packages/playwright-core/src/server/browser.ts:1-150
Termination
Browser termination follows a controlled shutdown sequence:
- Graceful close request - Send close command to browser
- Resource cleanup - Dispose contexts, pages, and handlers
- Process termination - Kill the browser executable if still running
- Transport cleanup - Close connections and cleanup pipes
graph TD
A[Browser.close called] --> B{Force kill?}
B -->|No| C[Graceful shutdown]
B -->|Yes| D[Kill process]
C --> E[Wait for exit]
E --> F[Force kill if timeout]
D --> G[Cleanup resources]
F --> G
G --> H[Done]Transport Layer
The transport layer enables message-based communication between the Node.js client and browser process.
Message Protocol
Messages follow a structured format with JSON-serialized headers and binary payloads:
┌─────────────────────────────────────────┐
│ Message Header (JSON) │
│ { id, method, params, binaryLength } │
├─────────────────────────────────────────┤
│ Binary Payload (if binaryLength > 0) │
└─────────────────────────────────────────┘
Transport Implementations
| Type | Use Case | Package |
|---|---|---|
PipeTransport | Local Windows processes | playwright-core |
StdioTransport | Unix domain sockets | playwright-core |
WebSocketTransport | Remote/cloud browsers | playwright-core |
Sources: packages/playwright-core/src/server/transport.ts:1-100
Connection Establishment
class Transport {
constructor(connection: Connection) {
this._connection = connection;
}
async connect(pipe: Pipe): Promise<void> {
// Establish connection to browser process
}
send(message: ProtocolMessage): void {
// Serialize and send message
}
async close(): Promise<void> {
// Graceful transport shutdown
}
}
Process Launcher
The ProcessLauncher utility provides cross-platform process spawning and management.
Launch Options
| Option | Type | Description | |
|---|---|---|---|
executablePath | string | Path to browser executable | |
args | string[] | Command-line arguments | |
env | Record<string,string> | Environment variables | |
cwd | string | Working directory | |
stdio | `'pipe' \ | 'inherit'` | Standard IO mode |
detach | boolean | Run in detached mode | |
timeout | number | Launch timeout in ms |
Sources: packages/utils/processLauncher.ts:1-120
Process Monitoring
The launcher maintains process health through:
- Exit detection - Monitoring for unexpected process termination
- Output capture - Collecting stdout/stderr for debugging
- Resource limits - Optional memory and CPU limits
- Cleanup hooks - Automatic resource disposal on exit
Error Handling
interface LaunchError {
reason: 'executable-not-found' | 'timeout' | 'crash' | 'protocol-error';
message: string;
stack?: string;
}
Browser Type Registry
Each browser type (Chromium, Firefox, WebKit) extends the base BrowserType class with browser-specific logic.
Browser Executable Resolution
graph TD
A[launch called] --> B{Find browser?}
B -->|User path| C[Validate executable]
B -->|Default| D[Check installed browsers]
C -->|Valid| E[Launch browser]
C -->|Invalid| F[Throw error]
D -->|Found| E
D -->|Not found| G[Prompt installation]BrowserType Interface
interface BrowserType {
name(): string;
executablePath(): string;
launch(options?: LaunchOptions): Promise<Browser>;
launchServer(options?: LaunchOptions): Promise<BrowserServer>;
launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
executable(): string;
defaultArgs(options?: LaunchOptions): string[];
}
Sources: packages/playwright-core/src/server/browserType.ts:100-200
Configuration Options
Common Launch Options
| Option | Default | Description |
|---|---|---|
headless | true | Run browser in headless mode |
args | [] | Additional browser arguments |
channel | undefined | Browser channel (e.g., 'chrome', 'msedge') |
chromiumSandbox | true | Enable Chromium sandbox (Linux) |
devtools | false | Open DevTools on launch |
downloadPath | undefined | Custom download directory |
env | process.env | Environment variables |
executablePath | undefined | Custom browser executable path |
firefoxUserPrefs | {} | Firefox-specific preferences |
proxy | undefined | Proxy configuration |
timeout | 30000 | Launch timeout in milliseconds |
viewport | { width: 1280, height: 720 } | Default viewport size |
Browser-Specific Options
#### Chromium
| Option | Type | Description |
|---|---|---|
chromiumSandbox | boolean | Enable Linux sandbox |
proxy | ProxySettings | HTTP/SOCKS proxy |
downloadContentTypes | string[] | Content types to download |
#### Firefox
| Option | Type | Description | ||
|---|---|---|---|---|
firefoxUserPrefs | `Record<string, string \ | number \ | boolean>` | Gecko preferences |
firefoxExtensionPaths | string[] | Extension directories |
#### WebKit
| Option | Type | Description |
|---|---|---|
wkWebKitExperimentalSimulateSaturation | boolean | Simulate saturation |
wkWebKitExperimentalLayoutMetrics | boolean | Enable layout metrics |
Integration with CLI Tools
The browser launch system integrates with Playwright's CLI tooling for interactive browser automation.
CLI Session Management
# Open browser with named session
playwright-cli -s=mysession open https://example.com
# Create persistent profile
playwright-cli open https://example.com --persistent
# Browser selection
playwright-cli open https://example.com --browser=firefox
The CLI layer uses the same BrowserType APIs to establish browser sessions, with session state managed through the browser's context persistence mechanisms.
Best Practices
Resource Management
- Always close browsers - Use
browser.close()in try/finally blocks - Handle launch failures - Wrap launch calls in try/catch for graceful error handling
- Use context isolation - Launch separate contexts instead of separate browsers when possible
- Set appropriate timeouts - Adjust timeouts for slow environments
Launch Example
import { chromium } from 'playwright';
async function run() {
let browser;
try {
browser = await chromium.launch({
headless: true,
timeout: 30000,
args: ['--disable-gpu', '--no-sandbox'],
});
const context = await browser.newContext();
const page = await context.newPage();
// Perform actions...
} catch (error) {
console.error('Browser launch failed:', error);
} finally {
if (browser) {
await browser.close();
}
}
}
Summary
The Browser Launch and Process Management system provides a robust foundation for browser automation in Playwright. By abstracting the complexities of process spawning, inter-process communication, and lifecycle management, it enables developers to work with browsers through a clean, consistent API regardless of the underlying browser type or execution environment.
Key takeaways:
- Dual execution modes support both isolated (OOP) and integrated (in-process) browser execution
- Transport abstraction enables reliable message passing across different IPC mechanisms
- Lifecycle management ensures proper resource cleanup and graceful degradation
- Browser type registry provides consistent APIs across Chromium, Firefox, and WebKit
Sources: packages/playwright-core/src/server/browserType.ts:1-50
Test Runner and Execution Engine
Related topics: Playwright Introduction and Project Overview, Locators, Selectors, and Element Interaction, Assertions, Matchers, and Expect API
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Playwright Introduction and Project Overview, Locators, Selectors, and Element Interaction, Assertions, Matchers, and Expect API
Test Runner and Execution Engine
The Playwright Test Runner is the core execution engine responsible for discovering, scheduling, and running end-to-end tests across multiple browsers and processes. It provides a complete test isolation model, automatic retry logic, parallel execution, and seamless integration with fixtures for test setup and teardown.
Architecture Overview
The test runner follows a multi-process architecture designed for scalability and isolation. At a high level, it consists of a central TestRunner process that coordinates test execution, multiple Worker processes that execute tests in isolated browser contexts, and a Dispatcher that manages the assignment of tests to available workers.
graph TD
A[TestRunner<br/>Main Process] --> B[Dispatcher<br/>Test Assignment]
B --> C[Worker Host 1<br/>Process]
B --> D[Worker Host 2<br/>Process]
B --> E[Worker Host N<br/>Process]
C --> F[Browser Context 1]
D --> G[Browser Context 2]
E --> H[Browser Context N]
F --> I[Page 1]
G --> J[Page 2]
H --> K[Page N]Core Components
| Component | File Location | Responsibility |
|---|---|---|
| TestRunner | packages/playwright/src/runner/testRunner.ts | Entry point; orchestrates the full test run lifecycle |
| Dispatcher | packages/playwright/src/runner/dispatcher.ts | Distributes tests to workers and tracks completion |
| TestLoader | packages/playwright/src/common/testLoader.ts | Discovers and parses test files |
| Fixtures | packages/playwright/src/common/fixtures.ts | Manages test fixtures and dependencies |
| PoolBuilder | packages/playwright/src/common/poolBuilder.ts | Creates and manages browser context pools |
| WorkerHost | packages/playwright/src/runner/workerHost.ts | Manages worker process lifecycle |
| WorkerMain | packages/playwright/src/worker/workerMain.ts | Worker process entry point; runs actual tests |
Sources: packages/playwright/src/runner/testRunner.ts:1-50 Sources: packages/playwright/src/runner/dispatcher.ts:1-60
Test Discovery and Loading
The test discovery process begins with the TestLoader, which recursively scans the project for test files matching the configured patterns. Playwright supports both .spec.ts and .spec.js file extensions by default, though these patterns are fully configurable through playwright.config.ts.
Loading Pipeline
graph LR
A[Test Files<br/>*.spec.ts] --> B[TestLoader]
B --> C[Parse Test Cases]
C --> D[Extract Fixtures]
D --> E[Build Test Tree]
E --> F[Dispatcher]The TestLoader performs the following operations:
- File Discovery — Scans the specified test directory for files matching the glob patterns defined in the configuration.
- Syntax Parsing — Parses each test file to extract
test,test.describe, andtest.beforeEachdeclarations. - Fixture Extraction — Identifies fixture dependencies declared via
test.use()or fixture function signatures. - Test Tree Construction — Builds a hierarchical structure representing test suites and individual test cases.
Sources: packages/playwright/src/common/testLoader.ts:1-80
Configuration Files
Playwright recognizes two primary configuration file formats:
| File | Format | Priority |
|---|---|---|
playwright.config.ts | TypeScript | Highest |
playwright.config.js | JavaScript | Lower |
playwright.config.mjs | ES Module | Lower |
The configuration defines critical execution parameters including:
// Example playwright.config.ts structure
export default defineConfig({
timeout: 30000, // Per-test timeout in milliseconds
retries: 0, // Number of retries on failure
workers: process.env.CI ? 1 : undefined, // Parallel workers
reporter: 'html', // Output format
use: {
baseURL: 'http://localhost',
headless: true,
viewport: { width: 1280, height: 720 },
ignoreHTTPSErrors: false,
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
Sources: package.json:test-scripts Sources: README.md:test-configuration
Worker Process Model
Each worker process operates as an independent execution unit, running in a separate Node.js process for complete isolation. The WorkerHost manages the lifecycle of these processes, handling creation, communication, and graceful termination.
Worker Lifecycle
stateDiagram-v2
[*] --> Spawning: Start Worker
Spawning --> Initializing: Worker PID obtained
Initializing --> Ready: Fixtures initialized
Ready --> Running: Test assigned
Running --> Ready: Test complete
Running --> Retrying: Test failed, retries remaining
Retrying --> Running: Retry attempt
Retrying --> Failed: No retries left
Running --> Failed: Test failed, no retries
Ready --> Shutdown: All tests complete
Failed --> [*]: Worker terminated
Shutdown --> [*]: Cleanup completeWorker Communication
Workers communicate with the main process through an IPC (Inter-Process Communication) channel. The protocol supports the following message types:
| Message Type | Direction | Purpose |
|---|---|---|
init | Main → Worker | Initialize worker with config |
run | Main → Worker | Execute a specific test |
stop | Main → Worker | Cancel running test |
done | Worker → Main | Report test result |
error | Worker → Main | Report runtime error |
teardown | Main → Worker | Graceful shutdown |
Sources: packages/playwright/src/runner/workerHost.ts:1-100 Sources: packages/playwright/src/worker/workerMain.ts:1-50
Dispatcher and Test Assignment
The Dispatcher is the central coordinator responsible for assigning tests to available workers while respecting configured parallelism limits. It maintains a queue of pending tests and dynamically allocates them based on worker availability.
Test Assignment Algorithm
graph TD
A[Test Queue] --> B{Workers Available?}
B -->|Yes| C[Pop Next Test]
C --> D{Test has deps?}
D -->|No| E[Assign to available worker]
D -->|Yes| F[Wait for deps]
F --> D
E --> G[Execute Test]
G --> H[Test Result]
H --> I{Success?}
I -->|Yes| J[Mark complete]
I -->|No| K{Retries left?}
K -->|Yes| L[Re-queue for retry]
K -->|No| M[Mark failed]
J --> A
L --> A
M --> AThe dispatcher implements the following strategies:
- Load Balancing — Tests are distributed evenly across workers to maximize throughput.
- Retry Logic — Failed tests are automatically re-queued up to the configured retry count.
- Serial Execution per Worker — Each worker processes one test at a time to maintain isolation.
- Sharding — Tests can be sharded across multiple machines using
--shardflag.
Sources: packages/playwright/src/runner/dispatcher.ts:50-200
Parallelism Configuration
| Config Option | CLI Flag | Description |
|---|---|---|
workers | --workers | Number of parallel worker processes |
retries | --retries | Number of retry attempts per failed test |
timeout | --timeout | Per-test timeout in milliseconds |
shard | --shard=N/M | Shard tests across M machines, run shard N |
# Run with 4 workers
npx playwright test --workers=4
# Run with retries and extended timeout
npx playwright test --retries=2 --timeout=60000
# Run shard 1 of 3
npx playwright test --shard=1/3
Fixture System
Fixtures provide a dependency injection mechanism for test setup and teardown. They ensure that resources are properly initialized before tests run and cleaned up afterward.
Fixture Types
| Type | Scope | Usage |
|---|---|---|
static | Across all tests | Global configuration |
worker | Per worker process | Shared within one worker |
test | Per test execution | Fresh for each test |
session | Across all workers | Shared global state |
import { test as baseTest, expect } from '@playwright/test';
// Define a fixture with automatic cleanup
export const test = baseTest.extend({
// Auto-cleanup database for each test
database: async ({}, use) => {
const db = await createTestDatabase();
await use(db);
await db.cleanup();
},
// Reuse authenticated page across all tests in a worker
authenticatedPage: async ({ browser }, use) => {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('/login');
await page.fill('#username', 'testuser');
await page.fill('#password', 'testpass');
await page.click('#submit');
await use(page);
await context.close();
},
});
Sources: packages/playwright/src/common/fixtures.ts:1-100
Built-in Fixtures
Playwright provides several built-in fixtures that are automatically available to all tests:
| Fixture | Type | Description |
|---|---|---|
page | test | Fresh page for each test |
context | test | Fresh browser context |
browser | worker | Browser instance shared in worker |
request | test | APIRequestContext for REST testing |
火 | test | Playwright test object |
Browser Context Pooling
The PoolBuilder manages a pool of browser contexts to optimize resource usage. Rather than creating a new context for each test (which can be expensive), the pool maintains a set of reusable contexts.
Pooling Strategy
graph TD
A[Test Request] --> B{Idle Context Available?}
B -->|Yes| C[Use Pooled Context]
B -->|No| D{Max Pool Size Reached?}
D -->|No| E[Create New Context]
D -->|Yes| F[Wait for Available]
E --> C
F --> C
C --> G[Test Execution]
G --> H{Context Satisfies Test?}
H -->|Yes| I[Return to Pool]
H -->|No| J[Destroy Context]
J --> K[Create Fresh Context]
K --> IContext Configuration
Each project can define its own context configuration:
export default defineConfig({
projects: [
{
name: 'chromium',
use: {
browserName: 'chromium',
viewport: { width: 1920, height: 1080 },
permissions: ['geolocation'],
storageState: './auth.json',
launchOptions: {
args: ['--disable-dev-shm-usage'],
},
},
},
],
});
Sources: packages/playwright/src/common/poolBuilder.ts:1-80
Debug Mode and CLI Integration
Playwright provides a CLI-based debugging mode that allows interactive inspection of test execution. When running with --debug=cli, the test runner pauses at the start and exposes a debug session.
Debug Workflow
graph TD
A[npx playwright test --debug=cli] --> B[Test Paused at Start]
B --> C[Debugging Instructions<br/>Session: tw-XXXX]
C --> D[playwright-cli attach tw-XXXX]
D --> E[Interactive Commands]
E --> F[snapshot, click, fill, etc.]
F --> G[Test Continues]
G --> H[Capture Results]
H --> I[Generate Report]Debug Commands
| Command | Purpose |
|---|---|
playwright-cli snapshot | Get current page snapshot with element refs |
playwright-cli click <ref> | Click an element by its reference |
playwright-cli fill <ref> <text> | Fill input field |
playwright-cli eval <expression> | Execute JavaScript in page context |
playwright-cli resume | Continue test execution |
playwright-cli screenshot | Capture current page state |
# Start test in debug mode
PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli
# In another terminal, attach to the debug session
playwright-cli attach tw-abcdef
# Explore the page
playwright-cli snapshot
playwright-cli click e15
playwright-cli eval "document.title"
Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md:1-50
Tracing and Debugging
Playwright includes a comprehensive tracing system that captures detailed execution information for post-mortem analysis.
Trace Contents
| Category | Captured Data |
|---|---|
| Actions | Clicks, fills, navigations with timestamps |
| DOM Snapshots | Before/after state for each action |
| Screenshots | Visual state at key moments |
| Network | All HTTP requests/responses |
| Console | Console.log output and errors |
| Errors | Stack traces for failures |
Trace Commands
# Open a trace file
npx playwright trace open trace.zip
# List all actions
npx playwright trace actions
# View specific action details
npx playwright trace action <action-id>
# Get DOM snapshot at an action
npx playwright trace snapshot <action-id>
# View console errors
npx playwright trace console --errors-only
graph LR
A[Test Execution] --> B[trace-{timestamp}.trace]
A --> C[trace-{timestamp}.network]
A --> D[resources/]
B --> E[Action Log]
C --> F[Network Activity]
D --> G[Cached Assets]
E --> H[Trace Viewer]
F --> H
G --> HSources: packages/playwright-core/src/tools/trace/SKILL.md:1-80
Execution Flow Summary
The complete test execution flow follows these stages:
sequenceDiagram
participant User
participant TestRunner
participant TestLoader
participant Dispatcher
participant WorkerHost
participant Worker
User->>TestRunner: npx playwright test
TestRunner->>TestLoader: Load tests
TestLoader-->>TestRunner: Test tree
TestRunner->>Dispatcher: Initialize
TestRunner->>WorkerHost: Spawn workers
WorkerHost->>Worker: Start process
loop For each test
Dispatcher->>WorkerHost: Assign test
WorkerHost->>Worker: Run test
Worker->>PoolBuilder: Request context
PoolBuilder-->>Worker: Context
Worker->>Fixtures: Setup fixtures
Fixtures-->>Worker: Fixture values
Worker->>Worker: Execute test body
Worker->>Fixtures: Teardown fixtures
Worker-->>WorkerHost: Test result
WorkerHost-->>Dispatcher: Result
end
Dispatcher-->>TestRunner: All complete
TestRunner->>User: ReportCommand-Line Interface
Common Commands
| Command | Description |
|---|---|
npx playwright test | Run all tests |
npx playwright test <file> | Run specific file |
npx playwright test --debug | Run in debug mode |
npx playwright test --list | List all tests without running |
npx playwright show-report | Open HTML report |
Configuration via CLI
# Override config values
npx playwright test --project=chromium --timeout=30000
# Run only matching tests
npx playwright test --grep="login"
# Run only failed tests from last run
npx playwright test --last-failed
# Update snapshots
npx playwright test --update-snapshots
Integration with Trace Viewer
The trace viewer is a Progressive Web App that opens trace files locally without sending data anywhere. It provides visual debugging capabilities.
graph TD
A[Trace.zip] --> B[WorkbenchLoader]
B --> C[TraceModel]
C --> D[Actions Panel]
C --> E[Screenshots Panel]
C --> F[Network Panel]
C --> G[Console Panel]
D --> H[Unified Timeline]
E --> H
F --> H
G --> HTo use the trace viewer:
- Run a test that generates a trace (using
trace: 'on'in config) - Locate the trace file in
test-results/<test-name>/trace.zip - Open at trace.playwright.dev or via CLI
Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx:1-60
Summary
The Playwright Test Runner provides a production-grade testing infrastructure with:
- Multi-process isolation ensuring test independence
- Automatic resource management through fixture cleanup
- Flexible parallelism configurable per project and CI environment
- Rich debugging via CLI integration and trace playback
- Cross-browser support executing tests on Chromium, Firefox, and WebKit
- Comprehensive reporting with built-in HTML reports and trace viewer
The architecture cleanly separates concerns between test discovery (TestLoader), orchestration (Dispatcher), execution (Workers), and resource management (Fixtures, PoolBuilder), making it both maintainable and extensible.
Locators, Selectors, and Element Interaction
Related topics: Test Runner and Execution Engine, Assertions, Matchers, and Expect API
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Test Runner and Execution Engine, Assertions, Matchers, and Expect API
Locators, Selectors, and Element Interaction
This page describes how Playwright locates DOM elements and interacts with them programmatically. The system consists of client-side Locator APIs, an in-browser Injected Script that evaluates selectors, and a server-side Selector Manager that registers and manages selector engines.
Architecture Overview
Playwright uses a layered architecture for element location:
| Layer | Package | Responsibility |
|---|---|---|
| Client API | playwright-core/src/client/locator.ts | Fluent locator interface exposed to test authors |
| Server Manager | playwright-core/src/server/selectors.ts | Registers selector engines, manages context |
| Injected Script | packages/injected/src/ | Runs in browser context, evaluates selectors |
graph TD
A[Test Author Code] --> B[Locator API]
B --> C[Selector Manager]
C --> D[Registered Selector Engines]
D --> E[Injected Script]
E --> F[Browser DOM]
B -->|locator.click/hover/fill| G[Action Commands]
E -->|querySelector, querySelectorAll| FSources: packages/playwright-core/src/client/locator.ts Sources: packages/playwright-core/src/server/selectors.ts
Locator API
The Locator class provides a fluent API for finding and interacting with elements. It differs from ElementHandle by using *strict* mode by default and automatically retrying until elements are actionable.
Core Locator Methods
| Method | Description |
|---|---|
click() | Click the element |
fill() | Fill input field with text |
hover() | Hover over element |
dblclick() | Double-click element |
check() / uncheck() | Toggle checkbox/radio |
selectOption() | Select option(s) from dropdown |
scrollIntoViewIfNeeded() | Scroll element into view |
tap() | Perform tap gesture |
dragAndDrop() | Drag and drop operations |
Locator vs ElementHandle
| Aspect | Locator | ElementHandle |
|---|---|---|
| Evaluation | Re-evaluated on each action | Captured once |
| Strict mode | Enabled by default | Must be manually enforced |
| Retries | Auto-retries until actionable | Single attempt |
| Shadow DOM | Traverses automatically | Manual shadow traversal |
The injected script exposes locator helpers via window.playwright:
this._injectedScript.window.playwright = {
$: (selector: string, strict?: boolean) => this._querySelector(selector, !!strict),
$$: (selector: string) => this._querySelectorAll(selector),
inspect: (selector: string) => this._inspect(selector),
selector: (element: Element) => this._selector(element),
generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language),
ariaSnapshot: (element?: Element, options?: AriaTreeOptions) => { ... },
resume: () => this._resume(),
...new Locator(this._injectedScript, ''),
};
Sources: packages/injected/src/consoleApi.ts:1-30
Selector Engine Architecture
Playwright supports multiple built-in selector engines that can be combined using the >> combinator.
Selector Engine Types
| Engine | Prefix | Example | Description |
|---|---|---|---|
| CSS | (default) | div.button | Standard CSS selectors |
| Role | role/ | role=button[name="Submit"] | ARIA role matching |
| Text | text/ | text="Log In" | Text content matching |
| Test ID | testId= | testId=submit-btn | data-testid attribute |
| Label | label= | label=Username | Form label association |
| Alt Text | alt= | alt=Profile Photo | Image alt attributes |
| Title | title= | title=Settings | Title attribute |
| XPath | xpath= | xpath=//button[1] | XPath expressions |
| Regex | /regex/ | /^submit.*$/i | Pattern matching |
Selector Evaluation Flow
graph LR
A[Selector String] --> B[Parse & Split by >>]
B --> C[Engine Registry Lookup]
C --> D{Engine Type?}
D -->|CSS| E[query/queryAll]
D -->|Role| F[Role Selector Engine]
D -->|Text| G[Text Selector Engine]
D -->|Other| H[Custom Engine]
E --> I[Evaluate in DOM]
F --> I
G --> I
H --> I
I --> J[Match Results]Engine Registration
Selector engines are registered with the SelectorEngine class:
type SelectorEngine = {
name: string;
create?(root: Preview<Element>, target: Element, context: SelectorInjectedContext): Selector;
query(root: Element, selector: Selector): Element | null;
queryAll?(root: Element, selector: Selector): Element[];
};
Sources: packages/injected/src/selectorEngine.ts
Role Selector Engine
The role selector engine matches elements by their ARIA role with optional name and properties filters.
Supported ARIA Roles
The engine recognizes all standard ARIA roles including: button, link, checkbox, radio, textbox, searchbox, combobox, listbox, menu, menuitem, tab, tablist, dialog, alertdialog, and many more.
Role Selector Syntax
role=button[name="Submit"]
role=link[name="Documentation"]
role=textbox[name="Email"][include-hidden]
role=menuitemcheckbox[name="Bold"][checked]
Role Matching Logic
graph TD
A[Input: role=button] --> B[Get all elements with role=button]
B --> C{has name filter?}
C -->|Yes| D[Filter by accessible name]
C -->|No| E[Return all matches]
D --> F{Matches found?}
F -->|Yes| E
F -->|No| G[Return empty]
E --> H[Apply other filters]Sources: packages/injected/src/roleSelectorEngine.ts
Selector Evaluator
The SelectorEvaluator class performs actual DOM matching using registered engines.
Key Methods
| Method | Signature | Purpose |
|---|---|---|
query | (selector: ParsedSelector, root: Element, strict: boolean) | Find single element |
queryAll | (selector: ParsedSelector, root: Element) | Find all matches |
parseSelector | (selector: string) | Parse selector string |
preusable | () | Create context for reuse |
Selector Parsing
Selectors are parsed into a structured format:
type ParsedSelector = {
parsed: {
engineName: string;
strict: boolean;
chain: {
engine: string;
selector: string;
distance: number;
shadow: ShadowRootLevel[];
}[];
};
};
Sources: packages/injected/src/selectorEvaluator.ts
Selector Generator
The selector generator suggests optimal selectors for elements during codegen and when using playwright codegen.
Generation Strategy
| Priority | Selector Type | Example |
|---|---|---|
| 1 | Test ID | [data-testid="submit"] |
| 2 | Accessible | role=button[name="Submit"] |
| 3 | Text | text="Submit" |
| 4 | CSS | #submit-btn |
| 5 | Relative | nth=5 |
Generator Implementation
The generator analyzes elements and ranks candidate selectors by:
- Uniqueness - Does this selector match exactly one element?
- Stability - Will this selector survive UI changes?
- Readability - Is this selector meaningful to humans?
- Brevity - Shorter selectors preferred when equivalent
Sources: packages/injected/src/selectorGenerator.ts
Injected Script Integration
The InjectedScript class provides the bridge between Node.js and browser contexts.
Architecture
graph TD
A[Playwright Node.js] -->|Evaluate| B[InjectedScript]
B --> C[Query Selector Engines]
B --> D[Locator Generation]
B --> E[ARIA Snapshot]
B --> F[Console API]
C --> G[DOM Manipulation]
D --> H[Selector Suggestions]
E --> I[Accessibility Tree]
G --> J[User Actions]
J -->|click, hover, type| K[Event Dispatch]Console API Methods
| Method | Description |
|---|---|
playwright.$() | Query single element |
playwright.$$() | Query all elements |
playwright.inspect() | Highlight element |
playwright.selector() | Generate selector for element |
playwright.generateLocator() | Generate in specific language |
playwright.ariaSnapshot() | Get accessibility snapshot |
Sources: packages/injected/src/injectedScript.ts
Using Locators with playwright-cli
The CLI tool supports all selector types for element interaction:
Element Targeting Methods
# Using snapshot refs (from playwright-cli snapshot)
playwright-cli click e15
# CSS selectors
playwright-cli click "#main > button.submit"
# Role locators
playwright-cli click "getByRole('button', { name: 'Submit' })"
# Test IDs
playwright-cli click "getByTestId('submit-button')"
Interaction Commands
| Command | Description | Example |
|---|---|---|
click | Click element | playwright-cli click e5 |
fill | Type into input | playwright-cli fill e4 "hello world" |
hover | Hover over element | playwright-cli hover e4 |
select | Select dropdown option | playwright-cli select e9 "option-value" |
check/uncheck | Toggle checkbox | playwright-cli check e12 |
drag | Drag and drop | playwright-cli drop e4 --data="text/plain=hello" |
upload | Upload file | playwright-cli upload ./document.pdf |
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
Selector Manager
The server-side SelectorManager handles registration and lifecycle of selector engines across browser contexts.
Manager Responsibilities
| Responsibility | Description |
|---|---|
| Engine Registration | Register built-in and custom engines |
| Context Management | Create/destroy selector contexts |
| Session Handling | Maintain state across browser sessions |
| Channel Communication | Bridge between server and injected script |
Custom Selector Registration
// Register a custom selector engine
await test.selectors.register({
name: 'my-selector',
query: async (root, selector) => {
return root.querySelector(selector);
},
queryAll: async (root, selector) => {
return [...root.querySelectorAll(selector)];
}
});
Sources: packages/playwright-core/src/server/selectors.ts
Element Interaction Flow
sequenceDiagram
participant T as Test Code
participant L as Locator API
participant S as Selector Manager
participant I as Injected Script
participant B as Browser DOM
T->>L: locator.click("button")
L->>S: query("button")
S->>I: evaluate querySelector
I->>B: query DOM
B->>I: return Element
I->>S: return Element
S->>L: return Element
L->>L: waitForElement
L->>T: click completeBest Practices
Preferred Selector Order
- Test IDs (
data-testid) — Most stable and explicit - Role + Name — Semantically meaningful and accessible
- Text Content — Human-readable but may change
- CSS Classes/IDs — Fast but brittle
- XPath — Last resort; hard to maintain
Anti-Patterns to Avoid
| Anti-Pattern | Problem | Alternative |
|---|---|---|
Index-based nth= | Breaks with layout changes | Use role/name filtering |
| Deep CSS paths | Fragile to DOM changes | Use semantic selectors |
| Dynamic attributes | Unstable in CI | Use stable test IDs |
| Coordinates | Resolution-dependent | Use element targets |
Summary
Playwright's locator and selector system provides a flexible, multi-engine approach to DOM element identification:
- Locator API offers a fluent, retry-based interface for test authors
- Multiple selector engines handle CSS, ARIA roles, text, and custom selectors
- Injected Script enables browser-side evaluation without round-trips
- Selector Generator helps discover optimal selectors during development
The architecture prioritizes accessibility (role selectors), stability (test IDs), and developer experience (fluent API) while maintaining performance through optimized DOM queries.
Assertions, Matchers, and Expect API
Related topics: Test Runner and Execution Engine, Locators, Selectors, and Element Interaction
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Test Runner and Execution Engine, Locators, Selectors, and Element Interaction
Assertions, Matchers, and Expect API
Playwright's assertion system provides a powerful, auto-retrying mechanism for validating application state during end-to-end testing. The expect API combined with matchers enables test authors to write expressive, readable assertions that automatically wait for conditions to be met rather than requiring manual polling or arbitrary timeouts.
Overview
Playwright's assertion framework is built on three core concepts that work together to provide reliable test assertions:
| Component | Purpose |
|---|---|
| Expect API | Core assertion function that wraps values and provides matcher methods |
| Matchers | Individual comparison functions that validate specific conditions |
| Expect Utils | Shared utility functions for handling timeouts, polling, and error messages |
The architecture follows a layered approach where the expect function creates an expectation object that chains matcher methods. Each matcher returns either a pass result or throws an error with detailed context about what failed.
graph TD
A[Test Code] --> B[expect value]
B --> C[Expectation Object]
C --> D[Matcher Methods]
D --> E{Auto-retry Loop}
E -->|condition met| F[Pass - Continue]
E -->|condition not met| G[Wait and Retry]
G --> E
E -->|timeout exceeded| H[Throw ExpectationError]
F --> I[Test Continues]
H --> J[Test Fails]Core Files and Structure
Expect Implementation
The main expect function is defined in packages/playwright/src/matchers/expect.ts. This file exports the expect function and the Expect class that handles the retry logic and matcher invocation.
Key responsibilities:
- Creating expectation objects from actual values
- Managing auto-retry mechanisms with configurable timeouts
- Formatting error messages with expected vs. actual values
- Supporting both synchronous and asynchronous expectations
Matchers Module
The matchers are defined in packages/playwright/src/matchers/matchers.ts. This file contains all built-in matcher functions that can be chained off the expect call.
Isomorphic Utilities
Shared assertion utilities in packages/isomorphic/expectUtils.ts and packages/isomorphic/assert.ts provide platform-agnostic functionality used across different Playwright packages.
Expect API Reference
Basic Usage
import { test, expect } from '@playwright/test';
test('login page', async ({ page }) => {
await page.goto('/login');
// Basic equality assertion
await expect(page).toHaveTitle('Login');
// Locator assertion with auto-wait
await expect(page.getByRole('button', { name: 'Submit' })).toBeVisible();
// Text content assertion
await expect(page.locator('.error')).toHaveText('Invalid credentials');
});
Configuration Options
| Option | Type | Default | Description | |
|---|---|---|---|---|
timeout | number | Matcher's default | Maximum time to retry the assertion | |
message | `string \ | function` | auto-generated | Custom error message on failure |
containsText | `string \ | RegExp` | - | Pattern that should appear in error |
Built-in Matchers
Web-First Assertions
Playwright provides specialized "web-first" assertions optimized for UI testing. These assertions automatically wait for the expected state before failing.
#### Visibility and Presence
| Matcher | Description |
|---|---|
toBeVisible() | Element is visible and not obscured |
toBeHidden() | Element is not visible |
toBeAttached() | Element is present in DOM |
toBeEnabled() | Element is enabled (not disabled) |
toBeDisabled() | Element is disabled |
toBeEditable() | Element is editable |
toBeFocused() | Element has focus |
#### Content Assertions
| Matcher | Description |
|---|---|
toHaveText(expected, options?) | Element contains exact or partial text |
toContainText(expected) | Element contains text (partial match) |
toHaveValue(value) | Input element has specific value |
toHaveValues(values) | Multiple select or checkbox group values |
toHaveTitle(title) | Page has specific title |
toHaveURL(url) | Page has specific URL |
toHaveScreenshot(name, options?) | Element/page matches screenshot |
#### Form and Input Assertions
| Matcher | Description |
|---|---|
toBeChecked() | Checkbox or radio is checked |
toHaveChecked() | Checkbox with specific state |
toBeSelected() | Option is selected in select element |
toBeRequired() | Input is marked as required |
toBeValid() | Input passes validation constraints |
Negation
All matchers support negation using .not:
await expect(page.getByRole('button')).not.toBeDisabled();
await expect(page.locator('.loading')).not.toBeVisible();
Snapshot Testing
Playwright supports snapshot testing through dedicated matchers that compare rendered output against stored baselines.
Visual Snapshots
The toMatchSnapshot matcher captures and compares images:
test('screenshot comparison', async ({ page }) => {
await page.goto('/dashboard');
await expect(page).toMatchScreenshot('dashboard.png', {
fullPage: true,
animations: 'disabled'
});
});
Parameters:
| Parameter | Type | Description | |
|---|---|---|---|
name | string | Snapshot file name | |
options?.fullPage | boolean | Capture entire scrollable page | |
options?.animations | `'disabled' \ | 'allow'` | Animation handling |
options?.mask | locator[] | Elements to mask in screenshot | |
options?.threshold | number | Pixel matching threshold 0-1 |
Aria Snapshots
The toMatchAriaSnapshot matcher compares the semantic structure of the page:
test('page structure', async ({ page }) => {
await page.goto('/form');
await expect(page).toMatchAriaSnapshot(`
- heading "Create Account"
- textbox "Email"
- textbox "Password"
- button "Submit"
`);
});
Parameters:
| Parameter | Type | Description | |
|---|---|---|---|
snapshot | string | Expected ARIA tree structure | |
options?.timeout | number | Retry timeout in ms | |
options?.matcher | `string \ | RegExp` | Custom snapshot matcher |
Updating Snapshots
When UI changes are intentional, update snapshots using the CLI:
npx playwright test --update-snapshots
# or
npx playwright test -u
Custom Matchers
Defining Custom Matchers
Extend the expect object with custom matchers for project-specific assertions:
// expect.d.ts or custom expect file
import { expect as baseExpect } from '@playwright/test';
export { test } from '@playwright/test';
export const expect = baseExpect.extend({
async toHaveAnalyticsEvent(
locator: Locator,
eventName: string,
options?: { timeout?: number }
) {
const timeout = options?.timeout ?? 1000;
const analyticsData: string[] = [];
const listener = (event: ConsoleMessage) => {
if (event.type() === 'log') {
analyticsData.push(event.text());
}
};
locator.page().on('console', listener);
try {
await page.waitForFunction(
(name) => window.analytics?.events?.includes(name),
eventName,
{ timeout }
);
return { pass: true };
} catch {
return {
pass: false,
message: () => `Expected analytics event "${eventName}" was not fired`,
};
} finally {
locator.page().off('console', listener);
}
},
});
Using Custom Matchers
import { expect } from './expect';
test('analytics tracking', async ({ page }) => {
await page.goto('/products');
await page.click('.buy-button');
// Uses custom matcher
await expect(page).toHaveAnalyticsEvent('purchase_initiated');
});
Auto-Retry Behavior
Playwright assertions automatically retry until the condition is met or timeout expires. This eliminates flaky tests caused by timing issues.
Retry Loop Flow
sequenceDiagram
participant T as Test
participant E as Expect
participant M as Matcher
participant P as Page
T->>E: expect(locator).toBeVisible()
Note over E: Create Expectation
loop Retry until timeout
E->>M: Compare current state
M->>P: Query element state
alt Condition met
M-->>E: Pass
E-->>T: Continue
else Condition not met
M-->>E: Fail
E->>E: Wait (default: 100ms)
end
end
Note over E: Timeout exceeded
E-->>T: Throw ExpectationErrorTimeout Configuration
// Per-assertion timeout
await expect(page.locator('.loading')).toBeHidden({ timeout: 5000 });
// Global default timeout
// In playwright.config.ts:
export default {
expect: {
timeout: 5000,
},
};
Timeout Inheritance
| Configuration Location | Value |
|---|---|
| Assertion option | { timeout: 3000 } |
expect config section | 5000 |
| Test fixture | Inherited |
| Default | 1000 (1 second) |
Error Messages
Playwright generates detailed, actionable error messages when assertions fail.
Error Message Structure
expect(received).toHaveText(expected)
Expected string: "Welcome, John"
Received string: "Welcome, Guest"
Custom Messages
await expect(page.locator('.balance')).toHaveText(
'$100.00',
{ message: 'Balance should reflect completed transaction' }
);
// Or use a function for dynamic messages
await expect(page.locator('.status')).toHaveText(
'Active',
{ message: () => `Expected status for user ${userId} to be Active` }
);
TypeScript Integration
Type Safety
All matchers are fully typed and provide autocomplete support:
// TypeScript infers expected type
await expect(page.locator('input')).toHaveValue('hello');
// For complex matchers, types are enforced
await expect(page).toHaveScreenshot('button.png', {
// options type is inferred
fullPage: true,
animations: 'disabled'
});
Generic Assertions
For custom assertion types, use generics:
expect.extend({
async toHaveData属性<T>(
this: jest.MatcherContext,
received: T,
key: string,
value: unknown
) {
const data = (received as any)[key];
return {
pass: data === value,
message: () => `Expected ${key} to be ${value}, got ${data}`,
};
},
});
Best Practices
Prefer Web-First Assertions
Always use Playwright's built-in web-first assertions over raw comparisons:
// ❌ Fragile - no auto-wait
expect(await page.textContent('button')).toBe('Submit');
// ✅ Reliable - auto-waits and handles timing
await expect(page.getByRole('button')).toHaveText('Submit');
Combine Matchers
Chain multiple matchers for comprehensive checks:
await expect(page.getByRole('textbox', { name: 'Email' }))
.toBeVisible()
.toBeEnabled()
.toBeFocused()
.toHaveAttribute('type', 'email');
Use Descriptive Names
Name expectations clearly for better test output:
// ❌ Unclear
await expect(page.locator('.main')).toHaveScreenshot('shot.png');
// ✅ Clear intent
await expect(page).toMatchScreenshot('checkout-page-cart-items.png');
Summary
The Assertions, Matchers, and Expect API form the foundation of Playwright's verification capabilities. Key takeaways:
| Aspect | Key Point |
|---|---|
| Auto-retry | Assertions automatically wait for conditions, reducing flakiness |
| Web-first | Built specifically for dynamic web applications |
| Rich matchers | Comprehensive set of UI-specific assertions |
| Snapshot support | Visual and semantic snapshot testing built-in |
| Extensibility | Custom matchers via expect.extend |
| TypeScript | Full type safety and autocomplete support |
The system is designed to make tests reliable by default, allowing developers to focus on test logic rather than timing and synchronization concerns.
Source: https://github.com/microsoft/playwright / Human Manual
Browser Implementations and Protocol Support
Related topics: Browser Launch and Process Management, CLI, MCP Server, and Agent Integration
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Browser Launch and Process Management, CLI, MCP Server, and Agent Integration
Browser Implementations and Protocol Support
Overview
Playwright's browser implementation architecture provides a unified automation API across three major browser engines: Chromium, Firefox, and WebKit. The architecture abstracts browser-specific differences through a common interface while supporting multiple protocols for communication between the Node.js process and browser instances. This design enables developers to write browser automation code once and execute it across different browsers without modification.
The browser implementations are organized in the packages/playwright-core/src/server/ directory, with each browser type having its own subdirectory containing browser-specific initialization, connection, and protocol handling code. This modular structure allows for independent development and maintenance of each browser's implementation while sharing common infrastructure through the core playwright-core package.
Architecture Overview
graph TD
subgraph "Playwright Core API"
A[chromium.launch()] --> B[BrowserType]
C[firefox.launch()] --> B
D[webkit.launch()] --> B
end
subgraph "Protocol Layer"
B --> E[CDP Connection]
B --> F[BiDi Protocol]
end
subgraph "Browser Implementations"
E --> G[Chromium Browser]
E --> H[WebKit Browser]
F --> I[Firefox Browser]
F --> J[Chromium via BiDi]
F --> K[WebKit via BiDi]
end
subgraph "Browser Processes"
G --> L[Chromium Process]
H --> M[WebKit Process]
I --> N[Firefox + Juggler]
endBrowser Package Structure
Playwright provides separate packages for each browser to optimize installation and distribution. The packages enable automatic installation of browser binaries when imported.
| Package Name | Description | Auto-Install | Main Export |
|---|---|---|---|
playwright-chromium | Chromium browser support | Yes | chromium |
@playwright/browser-chromium | Chromium browser support | Yes | chromium |
playwright | All browsers | Yes | chromium, firefox, webkit |
playwright-core | All browsers | No | chromium, firefox, webkit |
@playwright/browser-webkit | WebKit browser support | Yes | webkit |
playwright-browser-webkit | WebKit browser support | Yes | webkit |
Each package exports a chromium, firefox, or webkit object that provides the BrowserType interface for launching browser instances. The packages share common dependencies through playwright-core, which contains the actual implementation logic.
Chromium Implementation
The Chromium implementation consists of two main components: the browser type definition and the actual browser instance management.
Chromium Architecture
graph TD
A[chromium.launch()] --> B[Chromium#44;BrowserType]
B --> C[ChromiumBrowser#44;ConnectedBrowser]
C --> D[CDP Session]
C --> E[ChromiumBrowserContext]
D --> F[Chrome DevTools Protocol]
E --> G[ChromiumPage]
G --> FBrowser Type (`chromium.ts`)
The Chromium browser type class extends the base BrowserType interface and provides the specific configuration for launching Chromium instances. This file contains:
- Launch options: Configuration for headless mode, viewport, user agent, and other browser settings
- Browser binary path: Resolution logic for finding the Chromium executable
- Connection establishment: Code for establishing CDP connections to the browser
- Feature detection: Capabilities and features specific to Chromium
Browser Instance (`crBrowser.ts`)
The Chromium browser instance class manages the lifecycle of a connected Chromium browser. Key responsibilities include:
- Page management: Creating and tracking page instances
- Context management: Handling browser contexts for isolation
- CDP session handling: Managing DevTools protocol sessions
- Process management: Monitoring and terminating the browser process
Firefox Implementation
Firefox requires special handling due to its architecture. Unlike Chromium and WebKit which support CDP directly, Firefox uses a patched version called Juggler.
Firefox Architecture with Juggler
graph TD
A[firefox.launch()] --> B[Firefox#44;BrowserType]
B --> C[FFBrowser#44;ConnectedBrowser]
C --> D[Juggler Bridge]
D --> E[CDP to Juggler Translation]
E --> F[Firefox Browser Process]
subgraph "Browser Patches"
G[Juggler Protocol]
H[CDP Emulator]
I[Automation Hooks]
end
D --> G
G --> H
G --> IJuggler Protocol Handler
The Firefox implementation uses Juggler, a custom protocol handler that bridges Playwright's CDP-based API with Firefox's automation capabilities. The Juggler component:
- Patches Firefox: Modifies Firefox behavior to enable automation
- Protocol translation: Converts CDP commands to Firefox-specific commands
- Event forwarding: Streams events from Firefox back to Playwright
This architecture allows Playwright to provide a consistent API across all browsers while accommodating Firefox's different internal architecture.
Browser Type (`firefox.ts`)
The Firefox browser type handles:
- Binary detection: Locating the Firefox executable
- Profile management: Creating temporary profiles for isolation
- Launch configuration: Setting up Firefox-specific options
- Juggler injection: Ensuring Juggler is properly initialized
Browser Instance (`ffBrowser.ts`)
The Firefox browser instance provides:
- Page tracking: Managing page instances within Firefox
- Context handling: Isolating browsing contexts
- Protocol communication: Managing Juggler-based communication
WebKit Implementation
WebKit powers Safari and other browsers. Playwright's WebKit implementation provides support for this browser engine through a combination of native CDP support and custom protocol handling.
WebKit Architecture
graph TD
A[webkit.launch()] --> B[WebKit#44;BrowserType]
B --> C[WKBrowser#44;ConnectedBrowser]
C --> D[WebKit Protocol Handler]
D --> E[CDP Compatible Layer]
E --> F[WebKit Browser Process]
C --> G[WebKitBrowserContext]
G --> H[WKPage]
H --> DBrowser Type (`webkit.ts`)
The WebKit browser type includes:
- Executable resolution: Finding WebKit-based browsers
- Launch parameters: Configuring WebKit-specific options
- Connection setup: Establishing protocol communication
Browser Instance (`wkBrowser.ts`)
The WebKit browser instance manages:
- Page lifecycle: Creating and managing page instances
- Protocol sessions: Handling WebKit's protocol communication
- Feature compatibility: Ensuring WebKit-specific features work correctly
BiDi Protocol Support
The WebDriver BiDi (Bidirectional) protocol is a standardized web automation protocol that provides bidirectional communication between automation tools and browsers. Playwright's support for BiDi enables:
- Standardization: Using the W3C-standardized protocol
- Cross-browser compatibility: A single protocol approach
- Reduced complexity: Simpler protocol handling compared to CDP
BiDi Architecture
graph TD
A[BiDi Browser Connection] --> B[BidiBrowser#44;ConnectedBrowser]
B --> C[BiDi Session]
C --> D[Command Handler]
C --> E[Event Handler]
D --> F[Browser Commands]
E --> G[Browser Events]
B --> H[BrowserContext]
H --> I[Page]
subgraph "BiDi Protocol Messages"
J[JSON-RPC 2.0]
K[WebSocket Transport]
end
C --> J
J --> KBiDi Browser (`bidiBrowser.ts`)
The BiDi browser implementation provides:
- Session management: Creating and maintaining BiDi sessions
- Command routing: Dispatching commands to appropriate handlers
- Event subscription: Managing browser event subscriptions
- Context isolation: Supporting multiple browser contexts
Protocol Communication
Playwright supports multiple communication protocols for interacting with browsers. Understanding these protocols helps in debugging and extending Playwright's capabilities.
Chrome DevTools Protocol (CDP)
CDP is the primary protocol used by Chromium and partially by WebKit. It provides:
- Complete browser control: Full access to browser features
- Rich debugging: Detailed debugging capabilities
- Real-time events: Immediate event notifications
WebDriver BiDi
BiDi is the W3C-standardized protocol for browser automation:
- Cross-browser support: Standard protocol across all browsers
- Bidirectional communication: Events flow both directions
- Simpler model: Less complex than CDP for basic operations
Protocol Selection
| Feature | CDP | BiDi |
|---|---|---|
| Browser support | Chromium, WebKit | All browsers |
| Event subscription | Full | Full |
| Performance | Optimized | Standard |
| Standardization | Google-specific | W3C standard |
Launch Configuration
Each browser type accepts launch options that configure how the browser instance is created.
Common Launch Options
| Option | Type | Description | Chromium | Firefox | WebKit |
|---|---|---|---|---|---|
headless | boolean | Run without visible UI | ✓ | ✓ | ✓ |
args | string[] | Additional browser arguments | ✓ | ✓ | ✓ |
executablePath | string | Custom browser executable | ✓ | ✓ | ✓ |
timeout | number | Launch timeout in ms | ✓ | ✓ | ✓ |
viewport | Viewport | Default page viewport | ✓ | ✓ | ✓ |
userAgent | string | Custom user agent | ✓ | ✓ | ✓ |
locale | string | Browser locale | ✓ | ✓ | ✓ |
proxy | ProxyConfig | Proxy settings | ✓ | ✓ | ✓ |
Headless Mode
Headless mode runs the browser without visible UI, essential for CI/CD environments and server-side automation. All three browsers support headless execution with identical behavior.
Persistent Contexts
Playwright supports persistent browser contexts that maintain state across sessions:
graph LR
A[User Data Directory] --> B[Browser Profile]
B --> C[Cookies]
B --> D[Local Storage]
B --> E[Session Storage]
B --> F[Cache]Browser Contexts and Pages
Architecture
graph TD
Browser --> Context1[BrowserContext]
Browser --> Context2[BrowserContext]
Context1 --> Page1[Page]
Context1 --> Page2[Page]
Context2 --> Page3[Page]
Page1 --> CDPSession[CDP Session]
Page2 --> CDPSessionBrowserContext
Browser contexts provide isolation between different automation sessions:
- Separate storage: Each context has its own cookies, cache, and storage
- Independent state: Actions in one context don't affect others
- Parallel execution: Contexts can run simultaneously
- Resource isolation: Memory and process isolation
Page
Pages represent individual browser tabs or windows:
- Navigation: Loading URLs and managing history
- Interaction: Clicking, typing, and other user actions
- Evaluation: Running JavaScript in the page context
- Capture: Taking screenshots and generating PDFs
Process Architecture
Browser Process Model
graph TD
subgraph "Node.js Process"
A[Playwright API]
B[Connection]
end
subgraph "Browser Process"
C[Browser Main Process]
D[Renderer Process 1]
E[Renderer Process 2]
F[Renderer Process N]
end
B --> C
C --> D
C --> E
C --> FProcess Communication
The communication between Node.js and browser processes varies by browser:
- Chromium: Direct CDP over WebSocket or pipe
- Firefox: Juggler bridge acting as intermediary
- WebKit: CDP-compatible protocol over WebSocket
Version Compatibility
Playwright maintains compatibility matrices for browser versions to ensure stable automation:
| Playwright Version | Chromium | Firefox | WebKit |
|---|---|---|---|
| 1.61.0-next | Latest | Latest | Latest |
| Stable releases | Bundled | Bundled | Bundled |
Browser binaries are downloaded and managed by Playwright's installer, ensuring version compatibility between the library and browser binaries.
Extension Points
The browser implementation architecture supports extension through:
Custom Browser Executables
const browser = await chromium.launch({
executablePath: '/path/to/custom/chromium'
});
Protocol Interceptors
Extensions can intercept and modify protocol messages for debugging or custom behavior.
Custom Context Options
Browser contexts accept custom options specific to each browser implementation.
Troubleshooting
Browser Installation Issues
# Install all browsers
npx playwright install
# Install specific browser
npx playwright install chromium
npx playwright install firefox
npx playwright install webkit
Connection Issues
Connection problems typically manifest as timeout errors during launch or operation. The trace viewer tool (npx playwright trace) helps diagnose these issues by capturing detailed protocol communication.
Platform-Specific Considerations
Each browser may have platform-specific requirements:
- Chromium: Generally has few platform-specific issues
- Firefox: Requires Juggler patches for all platforms
- WebKit: May require platform-specific dependencies
Summary
Playwright's browser implementation architecture provides a robust, extensible foundation for cross-browser automation. By abstracting browser-specific details through a common interface while supporting multiple communication protocols, Playwright enables developers to write reliable browser automation code that works consistently across Chromium, Firefox, and WebKit.
The architecture's modular design allows for independent browser implementations while sharing common infrastructure, making it possible to add new browser support or extend existing capabilities without affecting the overall system.
Source: https://github.com/microsoft/playwright / Human Manual
Trace Viewer and Debugging Tools
Related topics: Test Runner and Execution Engine, CLI, MCP Server, and Agent Integration
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Test Runner and Execution Engine, CLI, MCP Server, and Agent Integration
Trace Viewer and Debugging Tools
Overview
Playwright's Trace Viewer and Debugging Tools provide comprehensive execution tracing capabilities for debugging and analyzing browser automation tests. The tracing system captures detailed execution traces including DOM snapshots, screenshots, network activity, and console logs, enabling developers to reconstruct and analyze exactly what happened during test execution.
The trace infrastructure consists of three main components:
| Component | Purpose | Location |
|---|---|---|
| Trace Recorder | Captures actions, snapshots, and metadata during test execution | packages/playwright-core/src/server/trace/recorder/ |
| Trace Viewer | Progressive Web App for visual trace inspection | packages/trace-viewer/ |
| Trace Model | Data structures and loading logic for trace files | packages/isomorphic/trace/ |
Sources: packages/trace-viewer/src/index.tsx
Architecture
graph TD
A[Test Execution] --> B[Tracing Recorder]
B --> C[Snapshotter]
B --> D[Action Logger]
B --> E[Network Monitor]
C --> F[DOM Snapshots]
D --> G[Action Log]
E --> H[Network Events]
F --> I[trace-{timestamp}.trace]
G --> I
H --> J[trace-{timestamp}.network]
I --> K[Trace ZIP Archive]
J --> K
K --> L[Trace Viewer PWA]
K --> M[playwright trace CLI]Core Components
#### Trace Recorder (packages/playwright-core/src/server/trace/recorder/tracing.ts)
The Tracing class manages the recording process for browser contexts. It initializes snapshot capture, action logging, and network monitoring.
| Method | Description |
|---|---|
start() | Initializes trace recording with snapshotter and action collectors |
stop() | Finalizes and writes trace files |
snapshot() | Captures current DOM state |
#### Snapshotter (packages/playwright-core/src/server/trace/recorder/snapshotter.ts)
Captures DOM snapshots before and after each action, enabling reconstruction of page state at any point during test execution.
Sources: packages/playwright-core/src/server/trace/recorder/snapshotter.ts
#### Trace Model (packages/isomorphic/trace/traceModel.ts)
The TraceModel class represents the in-memory structure of a trace file, containing:
| Property | Type | Description |
|---|---|---|
actions | ActionTrace[] | All recorded actions |
events | TraceEvent[] | Network, console, and other events |
snapshots | Snapshot[] | DOM snapshots |
#### Trace Loader (packages/isomorphic/trace/traceLoader.ts)
Handles parsing and loading of trace files from disk or network.
Sources: packages/isomorphic/trace/traceLoader.ts
Trace File Format
When tracing starts, Playwright creates a traces/ directory containing several files:
File Structure
| File | Format | Contents |
|---|---|---|
trace-{timestamp}.trace | Binary/JSON | Action log with DOM snapshots, screenshots, timing |
trace-{timestamp}.network | Binary/JSON | Complete network activity including headers, bodies, timing |
resources/ | Directory | Cached resources (images, fonts, scripts) |
Trace Archive
All trace files are packaged into a .zip archive for easy sharing and analysis:
# Default location
test-results/{test-name}/trace.zip
Captured Data Categories
| Category | Details |
|---|---|
| Actions | Clicks, fills, hovers, keyboard input, navigations |
| DOM | Full DOM snapshot before/after each action |
| Screenshots | Visual state at each step |
| Network | All requests, responses, headers, bodies, timing |
| Console | Browser console messages and stdout/stderr |
| Errors | Error messages with stack traces |
Sources: packages/playwright-core/src/tools/cli-client/skill/references/tracing.md
Trace Viewer UI
The Trace Viewer is a Progressive Web App that runs locally in the browser without sending trace data anywhere.
graph LR
A[Open trace.zip] --> B[Extract & Parse]
B --> C[Action Timeline]
B --> D[Snapshot View]
B --> E[Network Log]
B --> F[Console Output]Key Features
| Feature | Description |
|---|---|
| Action Timeline | Visual representation of all actions with timing |
| DOM Snapshots | Interactive DOM inspection at any action point |
| Network Log | Filterable view of all HTTP requests/responses |
| Console View | Console messages with filtering by type |
| Error Tracking | Consolidated view of all errors with stack traces |
Loading Traces
Traces can be loaded in multiple ways:
- Local File: Drop
.zipfile directly into the viewer - URL Parameter: Pass
?trace=with trace URL - Upload Button: Select file via browser dialog
The viewer displays a progress indicator during trace loading:
<Dialog open={showProgressDialog} isModal={true}>
<div className='progress-content'>
<div className='title'>Loading Playwright Trace...</div>
<div className='progress-wrapper'>
<div className='inner-progress'
style={{ width: progress.total ? (100 * progress.done / progress.total) + '%' : 0 }}>
</div>
</div>
</div>
</Dialog>
Sources: packages/trace-viewer/src/ui/workbench.tsx
CLI Commands
Trace Recording Commands
| Command | Description |
|---|---|
playwright-cli tracing-start | Start trace recording |
playwright-cli tracing-stop | Stop trace recording and save |
Trace Inspection Commands
| Command | Description |
|---|---|
npx playwright trace open <trace.zip> | Open and extract trace |
npx playwright trace close | Remove extracted trace data |
npx playwright trace actions | List all actions |
npx playwright trace actions --grep "click" | Filter actions by pattern |
npx playwright trace actions --errors-only | Show only failed actions |
npx playwright trace action <id> | Show details for one action |
npx playwright trace requests | List all network requests |
npx playwright trace requests --failed | Show only failed requests |
npx playwright trace request <id> | Show request details |
npx playwright trace console | Show console messages |
npx playwright trace console --errors-only | Show only errors |
npx playwright trace errors | Show all errors with stack traces |
npx playwright trace snapshot <id> | Get DOM snapshot |
npx playwright trace attachments | List trace attachments |
Example Workflow
# 1. Open trace and view metadata
npx playwright trace open test-results/my-test/trace.zip
# 2. List all actions
npx playwright trace actions
# 3. Show only failed actions
npx playwright trace actions --errors-only
# 4. Get details for specific action
npx playwright trace action 12
# 5. View DOM at that point
npx playwright trace snapshot 12
# 6. Check for network failures
npx playwright trace requests --failed
# 7. View console errors
npx playwright trace console --errors-only
Sources: packages/playwright-core/src/tools/trace/SKILL.md
Integration with Test Debugging
Debug Mode
Run tests in debug mode with CLI integration:
PLAYWRIGHT_HTML_OPEN=never npx playwright test --debug=cli
This command:
- Pauses test execution at start
- Prints debugging instructions with session name
- Allows attaching via
playwright-clito explore the page
Attaching to Test Session
# After starting debug mode, attach to the printed session
playwright-cli attach tw-abcdef
Available exploration commands while attached:
| Command | Description |
|---|---|
playwright-cli snapshot | Get current DOM snapshot |
playwright-cli click <ref> | Interact with elements |
playwright-cli eval <js> | Execute JavaScript |
playwright-cli show --annotate | Launch annotation dashboard |
playwright-cli resume | Resume test execution |
Spec-Driven Testing Workflow
The debugging tools integrate with Playwright's spec-driven testing approach:
- Create seed test that navigates to the application
- Run seed in debug mode and attach via CLI
- Explore the app to understand interactive surfaces
- Write spec file documenting expected behavior
- Generate tests from the spec
Sources: packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md
API Reference
JavaScript Execution in CLI
Execute arbitrary JavaScript in the browser context:
# Basic evaluation
playwright-cli eval "document.title"
# With return value
playwright-cli run-code "async page => await page.title()"
# Read from clipboard
playwright-cli run-code "async page => {
await page.context().grantPermissions(['clipboard-read']);
return await page.evaluate(() => navigator.clipboard.readText());
}"
Page Information
# Get page title
playwright-cli run-code "async page => await page.title()"
# Get current URL
playwright-cli run-code "async page => page.url()"
# Get viewport size
playwright-cli run-code "async page => page.viewportSize()"
Snapshot with Custom Depth
# Default snapshot
playwright-cli snapshot
# Snapshot with element bounding boxes
playwright-cli snapshot --boxes
# Limited depth for performance
playwright-cli snapshot --depth=4
# Snapshot specific element
playwright-cli snapshot "#main"
Sources: packages/playwright-core/src/tools/cli-client/skill/references/running-code.md
Storage State Management
Saving Authentication State
# Step 1: Login and save state
playwright-cli open https://app.example.com/login
playwright-cli snapshot
playwright-cli fill e1 "[email protected]"
playwright-cli fill e2 "password123"
playwright-cli click e3
playwright-cli state-save auth.json
# Step 2: Later, restore state
playwright-cli state-load auth.json
playwright-cli open https://app.example.com/dashboard
# Already authenticated
Cookie Management
| Command | Description |
|---|---|
playwright-cli cookie-list | List all cookies |
playwright-cli cookie-get <name> | Get specific cookie |
playwright-cli cookie-set <name> <value> | Set a cookie |
playwright-cli cookie-delete <name> | Delete a cookie |
playwright-cli cookie-clear | Clear all cookies |
Local/Session Storage
# List storage items
playwright-cli localstorage-list
playwright-cli sessionstorage-list
# Get specific value
playwright-cli localstorage-get theme
playwright-cli sessionstorage-get step
# Set value
playwright-cli localstorage-set theme dark
playwright-cli sessionstorage-set step 3
# Delete/Clear
playwright-cli localstorage-delete theme
playwright-cli localstorage-clear
Sources: packages/playwright-core/src/tools/cli-client/skill/references/storage-state.md
Advanced Features
Persistent Profiles
Browser profiles can be persisted to disk for testing scenarios requiring persistent state:
# Auto-generated profile location
playwright-cli open https://example.com --persistent
# Custom profile directory
playwright-cli open https://example.com --profile=/path/to/profile
# Create named session with persistent profile
playwright-cli -s=mysession open example.com --persistent
Network Interception
# Mock responses
playwright-cli route "**/*.jpg" --status=404
playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
# List and remove routes
playwright-cli route-list
playwright-cli unroute "**/*.jpg"
Highlighting Elements
# Highlight an element
playwright-cli highlight e5
# Highlight with custom style
playwright-cli highlight e5 --style="outline: 3px dashed red"
# Hide highlights
playwright-cli highlight --hide
Video Recording
# Start video recording
playwright-cli video-start video.webm
# Add chapter markers
playwright-cli video-chapter "Chapter Title" --description="Details" --duration=2000
# Stop recording
playwright-cli video-stop
Best Practices
| Practice | Description |
|---|---|
Use --debug=cli | Always debug through test execution, not direct URL opening |
| Capture specific actions | Use --grep flags to narrow focus during investigation |
| Save authentication state | Reuse authenticated sessions instead of repeating login |
| Use raw output | Pipe CLI output to tools like jq for scripting |
| Clean up traces | Run playwright-cli trace close after investigation |
Raw Output for Scripting
# Get JSON output for processing
playwright-cli list --json
# Pipe to jq for data extraction
playwright-cli --raw eval "JSON.stringify(performance.timing)" | jq '.loadEventEnd - .navigationStart'
# Save to file
playwright-cli --raw snapshot > before.yml
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
Sources: packages/trace-viewer/src/index.tsx
CLI, MCP Server, and Agent Integration
Related topics: Trace Viewer and Debugging Tools
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Trace Viewer and Debugging Tools
CLI, MCP Server, and Agent Integration
Overview
Playwright provides a comprehensive command-line interface (CLI), MCP (Model Context Protocol) server, and agent integration system that enables automated browser control, testing, and inspection workflows. These three interconnected components form the foundation of Playwright's external interaction layer, allowing developers and AI agents to programmatically control browsers, execute tests, and analyze application behavior.
The CLI layer (playwright-cli) provides a human-readable command interface for browser automation, while the MCP server exposes these capabilities to AI agents and automated systems. The agent integration system coordinates between tools, manages browser sessions, and maintains state across operations.
Architecture Overview
graph TD
A[User / AI Agent] --> B[CLI Interface<br/>playwright-cli]
A --> C[MCP Server<br/>Model Context Protocol]
B --> D[Tool Backend<br/>packages/playwright-core/src/tools/backend/tools.ts]
C --> D
D --> E[Browser Factory<br/>browserFactory.ts]
E --> F[Browser Pool<br/>Chromium, Firefox, WebKit]
D --> G[Session Manager]
G --> H[State: Cookies, LocalStorage,<br/>SessionStorage]
D --> I[Trace Viewer<br/>trace viewer package]CLI (`playwright-cli`)
Purpose and Scope
The playwright-cli tool provides a command-line interface for browser automation and testing. It is defined in packages/playwright-core/src/tools/cli-client/cli.ts and offers a comprehensive set of commands for interacting with browsers without writing code directly.
The CLI accepts commands like open, goto, click, fill, snapshot, and many others, making browser automation accessible through a simple shell interface.
Core Commands
#### Browser Lifecycle
| Command | Description |
|---|---|
playwright-cli open [url] | Opens a new browser and optionally navigates to URL |
playwright-cli close | Closes the current browser session |
playwright-cli close-all | Closes all browser sessions |
playwright-cli kill-all | Forcefully terminates all browser processes |
#### Navigation
| Command | Description |
|---|---|
playwright-cli goto <url> | Navigate to the specified URL |
playwright-cli go-back | Navigate back in browser history |
playwright-cli go-forward | Navigate forward in browser history |
playwright-cli reload | Reload the current page |
#### Element Interaction
| Command | Description | Example |
|---|---|---|
playwright-cli click <ref> | Click an element by ref | playwright-cli click e15 |
playwright-cli dblclick <ref> | Double-click an element | playwright-cli dblclick e7 |
playwright-cli fill <ref> <text> | Fill input field | playwright-cli fill e5 "text" |
playwright-cli type <text> | Type text into focused element | playwright-cli type "search" |
playwright-cli press <key> | Press a keyboard key | playwright-cli press Enter |
playwright-cli select <ref> <value> | Select dropdown option | playwright-cli select e9 "value" |
playwright-cli check <ref> | Check a checkbox | playwright-cli check e12 |
playwright-cli uncheck <ref> | Uncheck a checkbox | playwright-cli uncheck e12 |
playwright-cli hover <ref> | Hover over an element | playwright-cli hover e4 |
playwright-cli drag <src> <target> | Drag element to target | playwright-cli drag e2 e8 |
#### Data Input
| Command | Description |
|---|---|
playwright-cli upload <path> | Upload file to element |
playwright-cli drop <ref> --path=<file> | Drop file onto element |
playwright-cli drop <ref> --data=<type>=<data> | Drop data onto element |
Snapshot and Inspection
The snapshot command captures the current page state, including interactive elements with their refs:
playwright-cli snapshot
playwright-cli snapshot --filename=state.yaml
playwright-cli snapshot "#main"
playwright-cli snapshot --depth=4
playwright-cli snapshot --boxes
Elements can be targeted using refs from snapshots, CSS selectors, or Playwright locators:
# Using ref
playwright-cli click e15
# Using CSS selector
playwright-cli click "#main > button.submit"
# Using role locator
playwright-cli click "getByRole('button', { name: 'Submit' })"
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
Storage Management
# State persistence
playwright-cli state-save [filename]
playwright-cli state-load [filename]
# Cookies
playwright-cli cookie-list [--domain=<domain>]
playwright-cli cookie-get <name>
playwright-cli cookie-set <name> <value> [--domain=<domain>] [--httpOnly] [--secure]
playwright-cli cookie-delete <name>
playwright-cli cookie-clear
# LocalStorage
playwright-cli localstorage-list
playwright-cli localstorage-get <key>
playwright-cli localstorage-set <key> <value>
playwright-cli localstorage-delete <key>
playwright-cli localstorage-clear
# SessionStorage
playwright-cli sessionstorage-list
playwright-cli sessionstorage-get <key>
playwright-cli sessionstorage-set <key> <value>
playwright-cli sessionstorage-delete <key>
playwright-cli sessionstorage-clear
Sources: packages/playwright-core/src/tools/cli-client/skill/references/session-management.md
Network Interception
# Mock network responses
playwright-cli route "**/*.jpg" --status=404
playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
playwright-cli route-list
playwright-cli unroute "**/*.jpg"
playwright-cli unroute
Tracing
# Start/stop trace recording
playwright-cli tracing-start
playwright-cli tracing-stop
# Video chapters
playwright-cli video-start <file.webm>
playwright-cli video-chapter "Title" --description="Details" --duration=2000
playwright-cli video-stop
Sources: packages/playwright-core/src/tools/cli-client/skill/references/tracing.md
Tab Management
playwright-cli tab-list
playwright-cli tab-new [url]
playwright-cli tab-close [index]
playwright-cli tab-select <index>
Dialog Handling
playwright-cli dialog-accept [text]
playwright-cli dialog-dismiss
Advanced: JavaScript Execution
playwright-cli run-code "async page => await page.title()"
playwright-cli eval "document.title"
playwright-cli eval "el => el.textContent" <ref>
Sources: packages/playwright-core/src/tools/cli-client/skill/references/running-code.md
Browser Sessions
Sessions allow multiple independent browser instances with optional persistence:
# Named session with persistent profile
playwright-cli -s=mysession open https://example.com --persistent
# With custom profile directory
playwright-cli -s=mysession open https://example.com --profile=/path/to/profile
# Session management
playwright-cli -s=mysession click e6
playwright-cli -s=mysession close
playwright-cli -s=mysession delete-data
# List and cleanup
playwright-cli list
playwright-cli close-all
playwright-cli kill-all
Session name can be set via environment variable:
export PLAYWRIGHT_CLI_SESSION="mysession"
MCP Server Integration
Purpose and Architecture
The MCP (Model Context Protocol) server provides programmatic access to Playwright's browser automation capabilities for AI agents. The server is defined in packages/playwright-core/src/tools/mcp/index.ts and exposes a standardized interface for browser control operations.
graph LR
A[AI Agent] -->|MCP Protocol| B[MCP Server<br/>index.ts]
B --> C[Browser Factory<br/>browserFactory.ts]
B --> D[Browser Model<br/>browserModel.ts]
C --> E[Chromium]
C --> F[Firefox]
C --> G[WebKit]
D --> H[Browser State<br/>and Context]Browser Factory (`browserFactory.ts`)
The BrowserFactory class is responsible for creating and managing browser instances. It provides methods for launching browsers with various configurations:
class BrowserFactory {
async launch(options?: BrowserLaunchOptions): Promise<Browser>;
async connect(browserWSEndpoint: string): Promise<Browser>;
async close(): Promise<void>;
}
The factory handles:
- Browser type selection (Chromium, Firefox, WebKit)
- Launch option configuration
- Browser connection management
- Resource cleanup
Sources: packages/playwright-core/src/tools/mcp/browserFactory.ts
Browser Model (`browserModel.ts`)
The BrowserModel maintains state and context for browser instances:
class BrowserModel {
id: string;
browser: Browser;
context: BrowserContext;
pages: Page[];
sessionName?: string;
createdAt: Date;
}
Key responsibilities:
- Tracking active pages and contexts
- Managing browser lifecycle
- Providing access to current state
- Handling browser events
Sources: packages/playwright-core/src/tools/mcp/browserModel.ts
MCP Tool Interface
The MCP server exposes tools through the tools.ts backend:
// Defined in packages/playwright-core/src/tools/backend/tools.ts
export interface Tool {
name: string;
description: string;
execute(params: ToolParams): Promise<ToolResult>;
}
Available tool categories include:
- Navigation tools (goto, back, forward, reload)
- Interaction tools (click, fill, select, hover)
- Inspection tools (snapshot, screenshot, content)
- Storage tools (cookies, localStorage, sessionStorage)
Dashboard and Visualization
Dashboard Application (`dashboardApp.ts`)
The Playwright dashboard provides a visual interface for analyzing test results and traces:
graph TD
A[Test Execution] --> B[Trace Files<br/>.zip format]
B --> C[Trace Viewer]
C --> D[Dashboard App<br/>dashboardApp.ts]
D --> E[Action Timeline]
D --> F[Network Log]
D --> G[Console Output]
D --> H[Screenshots]The dashboard displays:
- Test action timeline with timing information
- Network request/response logs
- Console messages and errors
- DOM snapshots at each step
- Screenshots for visual verification
Sources: packages/playwright-core/src/tools/dashboard/dashboardApp.ts
Trace Viewer (`workbenchLoader.tsx`)
The trace viewer is a Progressive Web App that loads locally without sending data externally:
// Loading states
interface LoadState {
showFileUploadDropArea: boolean;
showProgressDialog: boolean;
processingErrorMessage?: string;
traceURL?: string;
}
Key features:
- Drag-and-drop trace file loading
- File browser selection
- Progress indication during trace parsing
- Local-only processing for privacy
Sources: packages/trace-viewer/src/ui/workbenchLoader.tsx
Dashboard React Component
The main dashboard component renders the UI:
// packages/dashboard/src/dashboard.tsx
export const Dashboard: React.FC<DashboardProps> = ({ traceData }) => {
// Renders action tree, network log, console output, snapshots
};
Spec-Driven Testing Workflow
The CLI supports a specification-driven testing workflow documented in spec-driven-testing.md:
graph LR
A[Write Spec File<br/>specs/feature.plan.md] --> B[Generate Tests]
B --> C[Execute Tests]
C --> D[Generate Traces]
D --> E[Analyze Results]
E --> F[Annotate & Feedback]Spec File Structure
# <Feature> Test Plan
## Application Overview
<Description>
## Test Scenarios
### 1. <Group Name>
**Seed:** `tests/seed.spec.ts`
#### 1.1. <scenario-name>
**File:** `tests/<group>/<scenario>.spec.ts`
**Steps:**
1. <User step>
- expect: <outcome>
2. <Next step>
- expect: <outcome>
Test Generation Flow
- Create seed test that navigates to the app
- Explore app using
playwright-cli attachandsnapshot - Write spec file with test scenarios
- Generate actual test code from spec
- Execute and capture traces
- Review results in trace viewer
Sources: packages/playwright-core/src/tools/cli-client/skill/references/spec-driven-testing.md
Trace CLI Tool
Command Reference
# Open and analyze traces
npx playwright trace open <trace.zip>
npx playwright trace close
# List actions
npx playwright trace actions
npx playwright trace actions --grep "click"
npx playwright trace actions --errors-only
# View specific action
npx playwright trace action <action-id>
# View requests, console, errors
npx playwright trace requests
npx playwright trace console
npx playwright trace errors
# Get DOM snapshot
npx playwright trace snapshot <action-id>
Sources: packages/playwright-core/src/tools/trace/SKILL.md
Trace File Structure
When tracing is enabled, Playwright creates:
| File/Directory | Content |
|---|---|
trace-{timestamp}.trace | Action log with DOM snapshots, screenshots, timing |
trace-{timestamp}.network | Complete network activity log |
resources/ | Cached resources for replay |
Tool Backend Architecture
The tool backend (packages/playwright-core/src/tools/backend/tools.ts) serves as the coordination layer:
graph TD
A[CLI / MCP Server] --> B[Tool Backend<br/>tools.ts]
B --> C[Browser Tool]
B --> D[Page Tool]
B --> E[Storage Tool]
B --> F[Trace Tool]
C --> G[Playwright Core API]
D --> G
E --> G
F --> GTool Categories
| Category | Tools |
|---|---|
| Browser | launch, connect, close, context |
| Navigation | goto, back, forward, reload |
| Interaction | click, fill, select, hover, drag, type, press |
| Snapshot | snapshot, screenshot, pdf |
| Storage | cookies, localStorage, sessionStorage |
| Network | route, unroute, route-list |
Package Structure
| Package | Purpose |
|---|---|
playwright | Main package with all browser support |
@playwright/test | Testing framework with reporters |
playwright-core | Core API without browser binaries |
@playwright/browser-chromium | Chromium browser support |
@playwright/browser-firefox | Firefox browser support |
@playwright/browser-webkit | WebKit browser support |
Sources: package.json, packages/playwright-test/package.json, packages/playwright-webkit/package.json
Environment Variables
| Variable | Purpose |
|---|---|
PLAYWRIGHT_CLI_SESSION | Default session name for CLI |
PLAYWRIGHT_HTML_OPEN | Controls browser launch behavior in tests |
PLAYWRIGHT_BROWSERS_PATH | Custom browser installation directory |
Error Handling Patterns
# Try-catch in run-code
playwright-cli run-code "async page => {
try {
await page.getByRole('button', { name: 'Submit' }).click({ timeout: 1000 });
return 'clicked';
} catch (e) {
return 'element not found';
}
}"
Installation and Usage
CLI Installation
# Use via npx (no installation required)
npx --no-install playwright-cli --version
# Or install globally
npm install -g playwright-cli
Testing Commands
From the root package.json:
| Script | Purpose |
|---|---|
npm run test | Run library tests |
npm run ctest | Chromium tests only |
npm run ftest | Firefox tests only |
npm run wtest | WebKit tests only |
npm run biditest | Bidi protocol tests |
Summary
The Playwright CLI, MCP Server, and Agent Integration system provides a layered approach to browser automation:
- CLI Layer: Human-friendly command interface for browser automation tasks
- MCP Layer: Programmatic interface for AI agents and automated systems
- Tool Backend: Coordination layer that manages browser factories and models
- Dashboard/Trace Viewer: Visualization tools for analyzing test results
These components work together to enable comprehensive browser testing and automation workflows, from simple interactive sessions to complex AI-driven testing scenarios.
Sources: packages/playwright-core/src/tools/cli-client/skill/SKILL.md
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
First-time setup may fail or require extra isolation and rollback planning.
First-time setup may fail or require extra isolation and rollback planning.
First-time setup may fail or require extra isolation and rollback planning.
The project should not be treated as fully validated until this signal is reviewed.
Doramagic Pitfall Log
Doramagic extracted 16 source-linked risk signals. Review them before installing or handing real data to the project.
1. Installation risk: [Feature]: Fail tests on page errors
- Severity: high
- Finding: Installation risk is backed by a source signal: [Feature]: Fail tests on page errors. Treat it as a review item until the current version is checked.
- User impact: First-time setup may fail or require extra isolation and rollback planning.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40880
2. Installation risk: [Feature]: Ubuntu 26.04 LTS support
- Severity: high
- Finding: Installation risk is backed by a source signal: [Feature]: Ubuntu 26.04 LTS support. Treat it as a review item until the current version is checked.
- User impact: First-time setup may fail or require extra isolation and rollback planning.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40117
3. Installation risk: [Feature]: trace correlation hooks for external observability/replay systems
- Severity: high
- Finding: Installation risk is backed by a source signal: [Feature]: trace correlation hooks for external observability/replay systems. Treat it as a review item until the current version is checked.
- User impact: First-time setup may fail or require extra isolation and rollback planning.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40887
4. Project risk: [Feature]: support signal in waitFor* APIs
- Severity: high
- Finding: Project risk is backed by a source signal: [Feature]: support signal in waitFor* APIs. Treat it as a review item until the current version is checked.
- User impact: The project should not be treated as fully validated until this signal is reviewed.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40578
5. Maintenance risk: [BUG] "NS_BINDING_ABORTED" error in Firefox
- Severity: high
- Finding: Maintenance risk is backed by a source signal: [BUG] "NS_BINDING_ABORTED" error in Firefox. Treat it as a review item until the current version is checked.
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/20749
6. Security or permission risk: Developers should check this security_permissions risk before relying on the project: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
- Severity: high
- Finding: Developers should check this security_permissions risk before relying on the project: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
- User impact: Developers may expose sensitive permissions or credentials: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only. Context: Observed when using node, docker, playwright, linux
- Evidence: failure_mode_cluster:github_issue | fmev_32d5131674a6cea46a3dd9fea57edcee | https://github.com/microsoft/playwright/issues/40892 | [Bug]: MCP createUserDataDir writes profile data to PLAYWRIGHT_BROWSERS_PATH, fails when path is read-only
7. Security or permission risk: [Feature]: Trace viewer: Add timeout-risk highlighting for actions in Playwright traces
- Severity: high
- Finding: Security or permission risk is backed by a source signal: [Feature]: Trace viewer: Add timeout-risk highlighting for actions in Playwright traces. Treat it as a review item until the current version is checked.
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: Source-linked evidence: https://github.com/microsoft/playwright/issues/40681
8. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: In VS Code, tests are not displayed in the Testing section.
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [Bug]: In VS Code, tests are not displayed in the Testing section.
- User impact: Developers may fail before the first successful local run: [Bug]: In VS Code, tests are not displayed in the Testing section.
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: In VS Code, tests are not displayed in the Testing section.. Context: Observed when using node, playwright, windows, macos
- Evidence: failure_mode_cluster:github_issue | fmev_429f2bbd1fa3334bca8aae5ee7df68b8 | https://github.com/microsoft/playwright/issues/40481 | [Bug]: In VS Code, tests are not displayed in the Testing section.
9. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
- User impact: Developers may fail before the first successful local run: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1. Context: Observed when using node, playwright
- Evidence: failure_mode_cluster:github_issue | fmev_09c75aac9731971717426ccfbe72651b | https://github.com/microsoft/playwright/issues/40904 | [Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted with NO_COLOR=1
10. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
- User impact: Developers may fail before the first successful local run: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite. Context: Observed when using node, playwright, windows
- Evidence: failure_mode_cluster:github_issue | fmev_bd2b1ca9bdfc4104afb98768ab5f87d4 | https://github.com/microsoft/playwright/issues/40889 | [Bug]: VSCode extension aborts run after a single slow (>10s) API test — subsequent tests never execute despite
11. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
- User impact: Developers may fail before the first successful local run: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials. Context: Observed when using node, playwright, windows, linux
- Evidence: failure_mode_cluster:github_issue | fmev_f50999f1a6066b929ea1a2971fefc95a | https://github.com/microsoft/playwright/issues/40768 | [Bug]: WebKit on Windows hangs when CONNECT proxy closes socket after 407 doesn't reconnect with credentials
12. Installation risk: Developers should check this installation risk before relying on the project: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
- Severity: medium
- Finding: Developers should check this installation risk before relying on the project: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
- User impact: Developers may fail before the first successful local run: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
- Recommended check: Before packaging this project, run the relevant install/config/quickstart check for: [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length. Context: Observed when using node, playwright, macos
- Evidence: failure_mode_cluster:github_issue | fmev_0f40df2fb212e08cdc02306a91f914c1 | https://github.com/microsoft/playwright/issues/40878 | [Bug]: playwright-cli open fails with EINVAL when session name is long on macOS due to unix socket path length
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using playwright with real data or production workflows.
- [[Feature]: Expose securityDetails() on APIResponse for HTTPS monitoring](https://github.com/microsoft/playwright/issues/40905) - github / github_issue
- [[Bug]: Reporter ignores NO_COLOR — colors and cursor codes still emitted](https://github.com/microsoft/playwright/issues/40904) - github / github_issue
- [[Bug]: Unable to Listen to Download Event While Using window.showSaveFil](https://github.com/microsoft/playwright/issues/31162) - github / github_issue
- [[Feature]: Fail tests on page errors](https://github.com/microsoft/playwright/issues/40880) - github / github_issue
- [[Feature]: trace correlation hooks for external observability/replay sys](https://github.com/microsoft/playwright/issues/40887) - github / github_issue
- [[Bug]: Trace viewer does not capture some dynamically added CSS classes](https://github.com/microsoft/playwright/issues/40895) - github / github_issue
- [[Regression]: install-deps --dry-run can no longer be used to generate i](https://github.com/microsoft/playwright/issues/40885) - github / github_issue
- [[Feature]: Trace viewer: Add timeout-risk highlighting for actions in Pl](https://github.com/microsoft/playwright/issues/40681) - github / github_issue
- [[Bug]: In VS Code, tests are not displayed in the Testing section.](https://github.com/microsoft/playwright/issues/40481) - github / github_issue
- [[Bug]: playwright-cli open fails with EINVAL when session name is long o](https://github.com/microsoft/playwright/issues/40878) - github / github_issue
- [[BUG] "NS_BINDING_ABORTED" error in Firefox](https://github.com/microsoft/playwright/issues/20749) - github / github_issue
- [[Feature]: Ubuntu 26.04 LTS support](https://github.com/microsoft/playwright/issues/40117) - GitHub / issue
Source: Project Pack community evidence and pitfall evidence