Jesse A. Green / notebook

Playwright — Administrator & Developer Guide

Generated May 2026 from microsoft/playwright at 5790370

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide covers the architecture, internals, deployment, security, and operational concerns of Playwright v1.60.0-next — Microsoft's cross-browser end-to-end testing and automation framework. It is written for platform engineers, DevOps teams, CI/CD administrators, and developers who need to understand how Playwright works under the hood, scale it across infrastructure, and troubleshoot production issues.

For installation walkthroughs, everyday CLI usage, test authoring patterns, and feature guides, see the companion User Guide.


1. Architecture Overview

1.1 Monorepo Structure

Playwright is organized as an npm workspaces monorepo under packages/*. The codebase spans 2,985 files and over 9 million characters of source. Each package has a sharply defined responsibility; understanding these boundaries is essential for anyone modifying or extending the framework.

Core Packages

Package Role
playwright Main package — test runner, fixtures, expect matchers, reporters, CLI commands (test, show-report, etc.)
playwright-core Core automation library — browser launching, CDP/protocol transport, server components, CLI commands (install, codegen, open, etc.)
playwright-test Thin re-export wrapper providing the @playwright/test npm package name
playwright-client Client-only package (no bundled browser binaries)

Browser-Specific Packages

Package Role
playwright-chromium Chromium-only automation package
playwright-firefox Firefox-only automation package
playwright-webkit WebKit-only automation package
playwright-browser-chromium Browser download metadata for Chromium
playwright-browser-firefox Browser download metadata for Firefox
playwright-browser-webkit Browser download metadata for WebKit

Component Testing

Package Role
playwright-ct-core Component testing core — mount fixture, router
playwright-ct-react Component testing adapter for React
playwright-ct-react17 Component testing adapter for React 17
playwright-ct-vue Component testing adapter for Vue

UI & Tooling Packages

Package Role
html-reporter HTML report viewer (React SPA)
trace-viewer Trace viewer (React SPA)
recorder Codegen recorder UI
dashboard Dashboard UI
playwright-cli-stub CLI stub entry point

Internal Shared Packages

Package Role
protocol Protocol type definitions (~259K chars) — the wire protocol spec between client and server
injected Scripts injected into browser pages: selectors, clock, highlights, storage, WebSocket mock
isomorphic Shared utilities: CSS parser, selector parser, locator generators, image utils, ARIA snapshots
utils Node.js utilities: comparators, crypto, debug, env, file utils, host platform detection, profiler, process launcher, zones
trace Trace format handling
web Shared web UI components

Note

The protocol package is the single source of truth for the wire format between client and server. All dispatchers and channel interfaces are generated or hand-aligned to match these type definitions. Any protocol change must start here.

1.2 Layered Data Flow

Every Playwright operation — whether launched from a test file, the CLI, or a remote connection — follows this layered path:

User Code (test files / scripts)
  |
  v
playwright (test runner: fixtures, workers, reporters)
  |
  v
playwright-core (client layer — Browser, Page, Frame API objects)
  |
  v
Protocol (JSON-RPC messages over pipe or WebSocket)
  |
  v
Server (browser management, dispatcher hierarchy)
  |
  v
Chromium / Firefox / WebKit (browser processes)
  |
  v
Injected Scripts (selectors, clock, highlights, storage, WebSocket mock)

The client layer constructs protocol messages. The server layer dispatches them to browser processes. The injected scripts run inside the browser's JavaScript context to evaluate selectors, manipulate the clock, and perform DOM operations. This separation means the Node.js process never directly touches the browser DOM — all interaction is mediated by the protocol.

1.3 Server Components

PlaywrightServer — A WebSocket server that exposes browser automation over the network. Used for remote browser access, grid setups, and the Playwright service. Configured via run-server CLI command with --port, --host, --path, --max-clients, --mode, and --artifacts-dir options.

DispatcherConnection + Dispatcher Hierarchy — The server-side object graph mirrors the client-side API. Each client-side object (Browser, BrowserContext, Page, Frame, etc.) has a corresponding dispatcher on the server that handles protocol messages and maintains state.

RootDispatcher
  └── PlaywrightDispatcher
        ├── BrowserTypeDispatcher
        │     └── BrowserDispatcher
        │           └── BrowserContextDispatcher
        │                 ├── PageDispatcher
        │                 │     └── FrameDispatcher
        │                 │           └── ElementHandleDispatcher
        │                 └── CDPSessionDispatcher
        └── ... (25+ dispatcher classes total)

ServerRegistry — Manages browser installations. Extends EventEmitter to notify listeners of installation events. Handles download, verification, and path resolution for all three browser engines.

1.4 Test Runner Architecture

The test runner (playwright package) has four major subsystems:

  1. Configuration — FullConfigInternal parses and validates playwright.config.ts. FullProjectInternal handles per-project configuration including dependencies and teardown ordering.

  2. Worker Pool — WorkerMain extends ProcessRunner to run tests in isolated worker processes. Workers communicate with the main process over IPC. The number of workers is controlled by the workers config option (default: '50%' of CPU cores).

  3. Fixture System — FixtureRunner and Fixture classes implement a dependency-injection system. Fixtures declare dependencies on other fixtures, and the runner resolves the dependency graph, sets up fixtures in order, and tears them down in reverse order.

  4. Tracing — TestTracing manages trace recording per test. Traces capture screenshots, network activity, DOM snapshots, and console output for post-mortem debugging.

1.5 Browser Patches

Playwright maintains custom patches for the browsers it drives:

Directory Purpose
browser_patches/firefox/ Firefox Juggler protocol — a custom CDP-like protocol that enables Playwright to control Firefox internals not exposed by standard APIs
browser_patches/webkit/ WebKit embedder patches for Playwright's WebKit automation
browser_patches/winldd/ Windows DLL dependency checker utility

These patches are applied to specific browser revisions that Playwright downloads and manages. This is why Playwright bundles its own browser binaries rather than using system-installed browsers.

1.6 Build System

The build toolchain uses a custom esbuild-based builder:

node utils/build/build.js

Key build dependencies:

  • TypeScript ^5.9.2
  • esbuild — fast bundling for packages
  • Vite — UI packages (html-reporter, trace-viewer, recorder, dashboard)
  • React / React-DOM — UI component rendering

2. System Requirements

2.1 Runtime Requirements

Requirement Minimum
Node.js 18 or later
npm 8+ (ships with Node 18+)
Disk space ~500 MB per browser engine (Chromium, Firefox, WebKit)
RAM 2 GB minimum for single browser; 4+ GB recommended for parallel execution

2.2 Supported Platforms

Playwright supports these host platforms for running tests:

OS Architectures
Ubuntu 20.04, 22.04, 24.04 (and Debian derivatives) x64, arm64
macOS 13 (Ventura), 14 (Sonoma), 15 (Sequoia) x64, arm64 (Apple Silicon)
Windows 10, 11, Server 2019, Server 2022 x64

Important

Windows ARM64 support is not yet available (tracked in issue #40202). Ubuntu 26.04 support is tracked in issue #40117. The platform detection logic in utils/ will throw "Unsupported platform: ..." for unrecognized host platforms.

2.3 System Dependencies (Linux)

On Linux, browsers require system shared libraries. Use the built-in dependency installer:

# Install system dependencies for all browsers
npx playwright install-deps

# Install dependencies for a specific browser
npx playwright install-deps chromium

For Docker environments, Playwright provides pre-built images (see Section 4.3).

2.4 Browser Installation Paths

Browser binaries are stored at platform-specific default locations unless overridden:

Platform Default Path
Linux $XDG_CACHE_HOME/ms-playwright (defaults to ~/.cache/ms-playwright)
macOS ~/Library/Caches/ms-playwright
Windows %LOCALAPPDATA%\ms-playwright

Override with PLAYWRIGHT_BROWSERS_PATH:

# Store browsers in a shared directory
export PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers
npx playwright install

3. Configuration Reference

3.1 Config File Resolution

Playwright looks for configuration in this order:

  1. playwright.config.ts
  2. playwright.config.js
  3. playwright.config.mjs
  4. playwright.config.cjs

The config file location determines the default testDir (the directory containing the config file).

3.2 Top-Level Configuration Options

The FullConfigInternal constructor defines every valid top-level option. Below is the complete reference:

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  // --- Test Discovery ---
  testDir: './tests',                    // Test directory (default: config file directory)
  testMatch: '**/*.@(spec|test).?(c|m)[jt]s?(x)', // Test file pattern
  testIgnore: undefined,                 // Glob patterns to ignore

  // --- Execution Control ---
  fullyParallel: false,                  // Run ALL tests in parallel (not just across files)
  workers: '50%',                        // Number or percentage of CPU cores
  retries: 0,                            // Retry count for failed tests
  repeatEach: 1,                         // Repeat each test N times
  maxFailures: 0,                        // Stop after N failures (0 = unlimited)
  timeout: 30000,                        // Per-test timeout in ms
  globalTimeout: 0,                      // Global timeout (0 = unlimited)
  forbidOnly: false,                     // Fail CI if test.only is present
  failOnFlakyTests: false,               // Treat flaky tests as failures

  // --- Filtering ---
  grep: /.*/,                            // Filter tests by title regex
  grepInvert: undefined,                 // Exclude tests matching regex
  tag: undefined,                        // Global tags (must start with @)

  // --- Output ---
  outputDir: 'test-results',             // Test artifacts directory
  preserveOutput: 'always',             // 'always' | 'never' | 'failures-only'
  quiet: false,                          // Suppress stdio
  reporter: [['list']],                  // Reporter configuration
  reportSlowTests: { max: 5, threshold: 300000 }, // Slow test reporting

  // --- Snapshots ---
  updateSnapshots: 'missing',            // 'all' | 'none' | 'missing'
  updateSourceMethod: 'patch',           // 'patch' | 'overwrite'
  ignoreSnapshots: false,                // Skip snapshot assertions
  respectGitIgnore: true,               // Honor .gitignore for snapshots

  // --- Setup/Teardown ---
  globalSetup: undefined,                // Path(s) to global setup file
  globalTeardown: undefined,             // Path(s) to global teardown file

  // --- Sharding ---
  shard: undefined,                      // { current: N, total: M }

  // --- Projects ---
  projects: [],                          // Array of project configurations

  // --- Web Server ---
  webServer: undefined,                  // Auto-start server config (single or array)

  // --- Metadata ---
  metadata: {},                          // Custom metadata object
  captureGitInfo: false,                 // Capture git info in test metadata

  // --- TypeScript ---
  tsconfig: undefined,                   // Custom TypeScript config path
});

Important

The workers option accepts either a number (4) or a percentage string ('50%'). Passing an invalid value triggers the error: "Workers ... must be a number or percentage". In CI environments, percentage-based workers automatically scale to the available cores.

3.3 Project-Level Configuration

Projects allow running the same tests against different browsers or configurations:

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      testDir: './tests',
      testMatch: '**/*.spec.ts',
      testIgnore: '**/mobile/**',
      outputDir: 'test-results/chromium',
      snapshotDir: './snapshots',
      snapshotPathTemplate: '{testDir}/__screenshots__/{testFilePath}/{arg}{ext}',
      timeout: 30000,
      retries: 2,
      repeatEach: 1,
      grep: /.*/,
      grepInvert: undefined,
      metadata: {},
      fullyParallel: true,
      ignoreSnapshots: false,
      respectGitIgnore: true,
      use: {
        browserName: 'chromium',
        headless: true,
        viewport: { width: 1280, height: 720 },
      },
      dependencies: ['setup'],         // Run 'setup' project first
      teardown: 'cleanup',             // Run 'cleanup' project after
    },
    {
      name: 'setup',
      testMatch: /global\.setup\.ts/,
    },
    {
      name: 'cleanup',
      testMatch: /global\.teardown\.ts/,
    },
  ],
});

Dependency rules enforced by the config validator:

  • A project listed in dependencies must exist by name — "Project ... depends on unknown project ..." is thrown otherwise.
  • A teardown project must not itself declare dependencies — "Teardown project ... must not have dependencies" is the error for violations.

3.4 Reporter Configuration

Built-in reporters:

Reporter Output Best For
list Detailed per-test output Local development (default for terminal)
line One-line-per-test updates Compact terminal output
dot Dots for pass/fail CI environments (default when CI env var is set)
json JSON to stdout Programmatic consumption
junit JUnit XML CI/CD integration (Jenkins, GitLab, etc.)
html Interactive HTML report Post-run analysis and sharing
blob Binary blob Merge sharded results
github GitHub Actions annotations GitHub Actions workflows
null No output Suppressing output entirely

Multiple reporters can be active simultaneously:

reporter: [
  ['list'],
  ['junit', { outputFile: 'results.xml' }],
  ['html', { open: 'never' }],
],

3.5 Web Server Configuration

Auto-start a dev server before tests:

webServer: {
  command: 'npm run dev',
  url: 'http://localhost:3000',
  reuseExistingServer: !process.env.CI,
  timeout: 120000,
  stdout: 'pipe',
  stderr: 'pipe',
},

Multiple servers are supported by passing an array.


4. Deployment & Scaling

4.1 CI/CD Integration

Sharding across machines:

# Machine 1
npx playwright test --shard=1/4

# Machine 2
npx playwright test --shard=2/4

# Machine 3
npx playwright test --shard=3/4

# Machine 4
npx playwright test --shard=4/4

Merge sharded results using the blob reporter:

# Each shard produces a blob
npx playwright test --shard=1/4 --reporter=blob

# Merge all blobs into a single HTML report
npx playwright merge-reports --reporter=html ./blob-reports

Caching browser binaries in CI:

# Cache key based on Playwright version
PLAYWRIGHT_VERSION=$(npx playwright --version)
# Cache directory: $PLAYWRIGHT_BROWSERS_PATH or default location

# GitHub Actions example
- uses: actions/cache@v4
  with:
    path: ~/.cache/ms-playwright
    key: playwright-${{ hashFiles('package-lock.json') }}

Tip

Set PLAYWRIGHT_BROWSERS_PATH to a directory within your CI cache path for reliable cache hits. The install --dry-run command shows what would be installed without downloading, useful for verifying cache coverage.

4.2 Remote Browser Execution

Running a Playwright Server:

# Start a remote browser server
npx playwright run-server \
  --port 3000 \
  --host 0.0.0.0 \
  --path /ws \
  --max-clients 10 \
  --mode default \
  --artifacts-dir /tmp/pw-artifacts

Launching via config file:

# launch-config.json
{
  "browser": "chromium",
  "headless": true,
  "port": 3000
}

npx playwright launch-server --config launch-config.json

Connecting from tests:

// Connect to a remote browser server
const browser = await chromium.connect('ws://remote-host:3000/ws');

Or via environment variables:

PW_TEST_CONNECT_WS_ENDPOINT=ws://remote-host:3000/ws npx playwright test
PW_TEST_CONNECT_HEADERS='{"Authorization":"Bearer token"}' npx playwright test
PW_TEST_CONNECT_EXPOSE_NETWORK="*" npx playwright test

4.3 Docker Deployment

Playwright provides Docker tooling in utils/docker/ for building images with pre-installed browsers and system dependencies.

Using the official Docker images:

FROM mcr.microsoft.com/playwright:v1.60.0-focal

WORKDIR /app
COPY package*.json ./
RUN npm ci
RUN npx playwright install --with-deps
COPY . .

CMD ["npx", "playwright", "test"]

Marking custom Docker images:

# Mark a Docker image so Playwright skips browser compatibility checks
npx playwright mark-docker-image

Tip

In Docker/CI environments, always use --with-deps during npx playwright install to ensure system libraries are present. Without it, browsers will fail to launch with missing shared library errors.

4.4 Worker Scaling

The workers configuration controls parallelism:

// Fixed count
workers: 4,

// Percentage of available CPUs
workers: '50%',

// Single worker (serial execution)
workers: 1,

Scaling considerations:

  • Each worker is a separate Node.js process running one or more browser instances
  • Memory usage scales linearly with worker count — budget ~300-500 MB per worker with a single browser
  • CPU-bound test suites benefit from worker counts up to the number of physical cores
  • I/O-bound suites (network-heavy tests) can exceed core count effectively
  • Set fullyParallel: true to parallelize tests within a single file across workers (default only parallelizes across files)

4.5 Browser Garbage Collection

Playwright automatically garbage-collects old browser versions. Control this behavior:

# Skip browser GC (useful in shared/cached environments)
export PLAYWRIGHT_SKIP_BROWSER_GC=1
npx playwright install

Use npx playwright install --list to see all installed browser versions across all Playwright installations on the system.


5. Operations

5.1 Browser Management

Installation commands:

# Install all browsers
npx playwright install

# Install specific browser
npx playwright install chromium
npx playwright install firefox
npx playwright install webkit

# Install with system dependencies (Linux)
npx playwright install --with-deps

# Dry run — show what would be installed
npx playwright install --dry-run

# List all installed browsers
npx playwright install --list

# Custom install path
PLAYWRIGHT_BROWSERS_PATH=/shared/browsers npx playwright install

Custom registry:

# Use a custom server for browser downloads (air-gapped environments)
export PLAYWRIGHT_SERVER_REGISTRY=https://internal-mirror.company.com/playwright
npx playwright install

Note

The PLAYWRIGHT_SERVER_REGISTRY environment variable redirects all browser download requests to a custom URL. This is essential for air-gapped or restricted network environments. The registry must mirror the same directory structure as the default Playwright CDN.

5.2 Debugging Facilities

Playwright Inspector:

# Launch with Inspector attached
PWDEBUG=1 npx playwright test

# Pause at end of test
PWPAUSE=1 npx playwright test

Debug logging:

# Enable protocol-level debug output
DEBUG=pw:api npx playwright test

# Enable all Playwright debug output
DEBUG=pw:* npx playwright test

# Write debug output to a file
DEBUG=pw:* DEBUG_FILE=playwright-debug.log npx playwright test

Runner-level debugging:

# Enable test runner debug output
PW_RUNNER_DEBUG=1 npx playwright test

Trace recording:

# Enable tracing for all tests
PWTEST_TRACE=1 npx playwright test

# View a trace file
npx playwright show-trace trace.zip

5.3 Report Management

HTML reports:

# Generate and auto-open HTML report
npx playwright show-report

# Custom report title
PLAYWRIGHT_HTML_TITLE="Nightly Regression" npx playwright test --reporter=html

# Merge sharded reports
npx playwright merge-reports --reporter=html ./blob-reports

JUnit for CI:

npx playwright test --reporter=junit > results.xml

5.4 Codegen and Recording

# Record user actions and generate test code
npx playwright codegen https://example.com

# Open a specific browser for manual testing
npx playwright open --browser=firefox https://example.com

5.5 Driver Mode

For language bindings (Python, Java, C#, Go), Playwright provides a pipe-based driver:

# Start the driver (used by non-Node.js SDKs)
npx playwright run-driver

# Configure SDK language name
PW_LANG_NAME=python npx playwright run-driver

Note

The run-driver command starts a JSON-RPC server over stdin/stdout pipes. The Python, Java, and C# Playwright SDKs use this to communicate with the Node.js server process. PW_LANG_NAME controls which SDK-specific behaviors are activated in the server.


6. Performance

6.1 Test Execution Optimization

Parallelism tuning:

Scenario Recommended workers fullyParallel
Local dev, fast feedback '50%' (default) false
CI with ample resources Number of cores true
CI with constrained RAM 2-4 false
Debugging a single test 1 false
Flake detection 1 with repeatEach: 10 false

Slow test detection:

The default reportSlowTests config flags tests exceeding 5 minutes (300,000 ms) and reports up to 5 of them. Adjust for your suite:

reportSlowTests: {
  max: 10,          // Report up to 10 slow tests
  threshold: 60000, // Flag anything over 1 minute
},

6.2 Browser Context Reuse

For test suites where browser startup is a bottleneck:

# Reuse browser context across tests (experimental)
PW_TEST_REUSE_CONTEXT=1 npx playwright test

Caution

Context reuse skips browser context teardown between tests. This speeds up execution but means tests share cookies, localStorage, and other state. Only use this when tests are designed for shared state, or in combination with explicit cleanup in beforeEach hooks.

6.3 Module Instrumentation

For diagnosing slow startup:

# Profile module loading times
PW_INSTRUMENT_MODULES=1 npx playwright test

This logs the time taken to load each module, helping identify slow require()/import() chains.

6.4 Snapshot Update Strategies

Strategy updateSnapshots Use Case
Add new only 'missing' (default) Normal development
Regenerate all 'all' After intentional visual changes
Strict match 'none' CI — fail on any missing snapshot

The updateSourceMethod option controls how test source files are modified when updating inline snapshots:

  • 'patch' (default) — applies minimal diffs
  • 'overwrite' — replaces the entire file

7. Security

7.1 Threat Model

Playwright executes arbitrary web content in browser processes. The security boundary is:

Node.js process (trusted) → Protocol → Browser (sandboxed) → Web content (untrusted)

Key security considerations:

  1. Browser sandbox — Playwright browsers run with their standard sandboxing. Chromium's multi-process sandbox, Firefox's content process isolation, and WebKit's WebProcess isolation all apply.

  2. Injected scripts — Scripts from the injected package run in the browser's main world. They have access to the page DOM and JavaScript context. These scripts are trusted code injected by Playwright, not by the web page.

  3. Remote server access — PlaywrightServer exposes browser automation over WebSocket. Anyone with network access to the server can control browsers, navigate to arbitrary URLs, and execute JavaScript.

Warning

The run-server command with --host 0.0.0.0 exposes browser automation to the network. There is no built-in authentication. Use network-level controls (firewalls, VPNs, private networks) to restrict access. In production grid setups, place the server behind an authenticating reverse proxy.

7.2 Sensitive Environment Variables

These variables carry credentials and should be treated as secrets in CI/CD:

Variable Contains
PLAYWRIGHT_SERVICE_ACCESS_KEY Authentication key for Playwright hosted service
PW_TEST_CONNECT_HEADERS Custom headers (may contain auth tokens) for remote connections

Warning

Never log or echo PLAYWRIGHT_SERVICE_ACCESS_KEY or PW_TEST_CONNECT_HEADERS in CI output. Use masked/secret variable features of your CI platform.

7.3 Network Exposure

webServer configuration — The webServer option starts a local development server. Ensure it binds only to localhost in CI environments to prevent unintended network exposure.

PW_TEST_CONNECT_EXPOSE_NETWORK — When connecting to a remote browser server, this variable controls which network targets the remote browser can access. Setting it to "*" grants access to all networks reachable from the server.

7.4 File System Access

Playwright writes to several directories:

Directory Contents Sensitivity
test-results/ (or outputDir) Screenshots, videos, traces, downloads May contain application data
Browser cache directory Browser binaries and profiles Contains cached web data
playwright-report/ HTML reports May contain screenshots of application state
Trace files Full DOM snapshots, network data, console logs High — may contain PII or secrets visible in the application

Caution

Trace files and HTML reports can contain sensitive application data including screenshots, network request/response bodies, cookies, and console output. Treat these artifacts with the same sensitivity as the application under test. Do not publish them to public storage without review.

7.5 TypeScript and Code Execution

Playwright's config file (playwright.config.ts) is executed as code. The test runner uses Node.js options for TypeScript support:

# Disable TypeScript ESM loader if it causes issues
PW_DISABLE_TS_ESM=1 npx playwright test

The NODE_OPTIONS environment variable is used internally to register the TypeScript loader. Be aware that overriding NODE_OPTIONS in your environment may interfere with Playwright's TypeScript support.


8. Developer Internals

8.1 Protocol Layer

The protocol package defines the complete wire protocol (~259K characters of type definitions). Communication between client and server uses JSON-RPC:

  • Pipe transport — Used for in-process communication (default when launching browsers locally). The Node.js process communicates with the browser server over stdin/stdout pipes.
  • WebSocket transport — Used for remote connections. The PlaywrightServer hosts a WebSocket endpoint that accepts JSON-RPC messages.

8.2 Dispatcher System

The dispatcher hierarchy is the server-side counterpart to the client API. There are 25+ dispatcher classes:

Core dispatchers:

  • Dispatcher — base class with serialization, event emission, and lifecycle management
  • RootDispatcher — root of the dispatcher tree for a connection
  • DispatcherConnection — manages the full dispatcher tree and protocol message routing
  • PlaywrightDispatcher — top-level dispatcher exposing browser types and devices

Browser lifecycle:

  • BrowserTypeDispatcher → BrowserDispatcher → BrowserContextDispatcher → PageDispatcher → FrameDispatcher → ElementHandleDispatcher

Supporting dispatchers:

  • CDPSessionDispatcher — raw CDP protocol access (Chromium only)
  • Plus dispatchers for Dialog, Download, Request, Response, Route, WebSocket, Worker, etc.

8.3 Injected Script System

The injected package contains scripts that run inside browser page contexts:

Class Purpose
InjectedScript Main entry point — selector evaluation, element interaction, waiting
SelectorEvaluatorImpl CSS and custom selector engine evaluation
BindingsController Manages page bindings (exposing Node.js functions to the page)
ClockController Fake timers and clock manipulation
ConsoleAPI Console message interception
Highlight Element highlighting for codegen and debugging
StorageScript localStorage/sessionStorage manipulation
UtilityScript Shared utilities for injected code
WebSocketMock WebSocket interception and mocking

These scripts are bundled at build time and injected via the protocol's evaluateExpression mechanism.

8.4 Selector Engine Architecture

The isomorphic package contains the selector parsing and evaluation infrastructure:

  • CSS Parser — CSSParserToken with 20+ token subclasses, handles the full CSS selector syntax
  • Selector Parser — Parses Playwright's extended selector syntax (text=, css=, xpath=, role=, chained selectors with >>)
  • Locator Generators — Language-specific code generators that produce locator expressions:
    • JavaScriptLocatorFactory
    • PythonLocatorFactory
    • JavaLocatorFactory
    • CSharpLocatorFactory

These are used by the codegen recorder to produce test code in the target language.

8.5 Fixture System Internals

The FixtureRunner resolves a dependency graph of fixtures:

  1. Each Fixture instance declares its dependencies (other fixtures it needs)
  2. The runner topologically sorts the dependency graph
  3. Setup runs in dependency order; teardown runs in reverse
  4. Fixtures can be scoped to test (per-test) or worker (per-worker process)

Error conditions:

  • "Cannot provide fixture value for the second time" — a fixture's use() callback was invoked more than once
  • "use() was not called in fixture ..." — a fixture function completed without calling the provided use() function
  • "Playwright detected inconsistent test.use() options" — conflicting use() declarations across test files sharing a worker

8.6 Shared Utilities

The utils package provides Node.js-level infrastructure:

Module Purpose
comparators Image comparison (pixel diff, SSIM)
crypto Hashing and random ID generation
debug Debug logging (integrates with the debug npm package)
env Environment variable reading and validation
fileUtils File I/O helpers with atomic writes
hostPlatform Host OS/architecture detection (overridable via PLAYWRIGHT_HOST_PLATFORM_OVERRIDE)
profiler Performance measurement
processLauncher Cross-platform process spawning with cleanup
zones Async context tracking (Zone.js-like)

The isomorphic package also provides:

  • LRUCache — least-recently-used cache
  • ManualPromise — externally resolvable Promise
  • Semaphore — concurrency limiter
  • MultiMap — map with multiple values per key
  • InvalidSelectorError — typed error for selector parsing failures

8.7 ARIA Snapshot System

The isomorphic package includes ARIA snapshot generation — a tree-based representation of the accessibility structure of a page. This powers the toMatchAriaSnapshot() assertion in the test runner.


9. Integration Points

9.1 Playwright Service

Playwright can connect to Microsoft's hosted service or a self-hosted equivalent:

PLAYWRIGHT_SERVICE_URL=https://playwright-service.example.com
PLAYWRIGHT_SERVICE_ACCESS_KEY=your-key
PLAYWRIGHT_SERVICE_RUN_ID=unique-run-id
PLAYWRIGHT_SERVICE_OS=linux  # or windows

9.2 VS Code Extension

Playwright integrates with VS Code through the official extension. Known issue #40226 tracks cases where the extension fails to discover tests.

9.3 Component Testing

The component testing packages (playwright-ct-*) integrate with framework build tools:

// playwright-ct.config.ts
import { defineConfig } from '@playwright/experimental-ct-react';

export default defineConfig({
  use: {
    ctPort: 3100,
    ctTemplateDir: './playwright',
  },
});

The PLAYWRIGHT_TEST_BASE_URL environment variable overrides the component test server URL.

9.4 Dashboard

The dashboard package provides a UI for viewing test results. Enable via:

PLAYWRIGHT_DASHBOARD=1 npx playwright test

9.5 Custom Sockets Directory

For environments with restrictions on the default socket path:

PLAYWRIGHT_SOCKETS_DIR=/custom/path/sockets npx playwright test

10. Troubleshooting

10.1 Browser Launch Failures

Error: Unsupported browser ...

  • Cause: Passed a browser name other than chromium, firefox, or webkit
  • Solution: Use one of the three supported browser names
  • Prevention: Validate browser names in your config against the allowed set

Error: Directory does not exist: ...

  • Cause: The configured testDir, outputDir, or other path does not exist on disk
  • Solution: Create the directory or correct the path in playwright.config.ts
  • Prevention: Use relative paths anchored to the config file location

Error: Browser fails to launch with missing shared library errors (Linux)

  • Cause: System dependencies not installed
  • Solution: Run npx playwright install-deps or use the --with-deps flag
  • Prevention: Use Playwright Docker images or include install-deps in your CI setup

Tip

The npx playwright install --dry-run command shows exactly which browsers would be downloaded and their expected paths, without performing any downloads. Use this to verify your CI cache is correctly configured.

10.2 Configuration Errors

Error: Cannot use --browser option when configuration file defines projects

  • Cause: The --browser CLI flag conflicts with project-based configuration
  • Solution: Remove --browser from the CLI and configure browsers in projects instead
  • Prevention: Choose one approach — CLI flags for simple setups, projects for multi-browser

Error: Tag must start with @ symbol

  • Cause: A tag in config or CLI does not begin with @
  • Solution: Prefix all tags with @ (e.g., @smoke, @regression)

Error: Workers ... must be a number or percentage

  • Cause: Invalid workers value (e.g., a non-numeric string)
  • Solution: Use a positive integer or a percentage string like '50%'

Error: Project ... depends on unknown project ...

  • Cause: A dependencies entry references a project name that does not exist
  • Solution: Verify project names match exactly (case-sensitive)

Error: Teardown project ... must not have dependencies

  • Cause: A project designated as teardown also declares dependencies
  • Solution: Remove dependencies from the teardown project — it runs unconditionally after its parent

Note

The error "Playwright detected inconsistent test.use() options" occurs when tests in the same worker process declare different use() options. Either move conflicting tests to separate projects or ensure consistent use() declarations within each project.

10.3 Runtime Issues

Error: Unexpected browserName ..., must be one of chromium, firefox or webkit

  • Cause: The use.browserName option in config or test.use() has a typo or invalid value
  • Solution: Set browserName to exactly 'chromium', 'firefox', or 'webkit'

Issue: Tests stuck at about:blank (GitHub #31050, 50+ comments)

  • Cause: Navigation race conditions, especially with single-page apps
  • Solution: Use waitUntil: 'networkidle' or explicit waiting for application-specific elements rather than relying on default navigation completion

Issue: Proxy authentication hangs (GitHub #40194)

  • Cause: Browser-level proxy auth dialogs are not automatically handled
  • Solution: Provide proxy credentials in the proxy configuration object rather than relying on interactive authentication

Issue: Dialog handler not working as expected (GitHub #11014, 37 comments)

  • Cause: Dialog handlers must be registered before the action that triggers the dialog
  • Solution: Always call page.on('dialog', handler) before the click or navigation that produces the dialog

Caution

The --only-changed flag is not supported in UI mode. Attempting to use it produces: "--only-changed is not supported in UI mode". Use CLI mode for changed-file-only test execution.

10.4 Android Automation

Error: No devices found

  • Cause: No Android device connected or ADB not configured
  • Solution: Connect a device via USB with USB debugging enabled, or start an emulator

Error: More than one device found. Please specify deviceSerialNumber

  • Cause: Multiple Android devices/emulators are connected
  • Solution: Pass the deviceSerialNumber option to specify which device to use. List devices with adb devices.

10.5 WebKit-Specific Issues

  • Issue #40268: WebKit WASM — WebAssembly-related failures in WebKit
  • Issue #40244: WebKit formData() — FormData parsing issues in WebKit

These are browser-engine-level issues tracked upstream in the Playwright patched WebKit build.

10.6 TypeScript Issues

Issue #38586: TypeScript declare keyword handling

  • Certain TypeScript declaration patterns may not be recognized by Playwright's TypeScript loader

Disabling TypeScript ESM loader:

PW_DISABLE_TS_ESM=1 npx playwright test

Use this when the experimental TypeScript ESM loader conflicts with your project's module setup.


Appendix A: Complete Environment Variable Reference

Variable Purpose Default
PLAYWRIGHT_BROWSERS_PATH Custom browser installation directory Platform default (see Section 2.4)
PLAYWRIGHT_SKIP_BROWSER_GC Skip browser garbage collection Not set
PLAYWRIGHT_SERVER_REGISTRY Custom browser download registry URL Official CDN
PLAYWRIGHT_HOST_PLATFORM_OVERRIDE Override host platform detection Auto-detected
PLAYWRIGHT_SOCKETS_DIR Custom sockets directory OS default
PLAYWRIGHT_NO_COPY_PROMPT Disable copy prompt in CLI tools Not set
PLAYWRIGHT_HTML_TITLE Custom HTML report title "Playwright Test Report"
PLAYWRIGHT_DASHBOARD Enable dashboard binding Not set
PLAYWRIGHT_TEST_BASE_URL Base URL for component tests Not set
PLAYWRIGHT_SERVICE_URL Playwright service URL Not set
PLAYWRIGHT_SERVICE_ACCESS_KEY Playwright service auth key Not set
PLAYWRIGHT_SERVICE_RUN_ID Playwright service run ID Not set
PLAYWRIGHT_SERVICE_OS Playwright service OS Not set
PWDEBUG Enable Playwright Inspector (set to 1) Not set
PWPAUSE Pause at test end Not set
PWTEST_MODE Test mode override Not set
PWTEST_TRACE Enable tracing in tests Not set
PW_CLI_DISPLAY_VERSION Override displayed CLI version Package version
PW_EXTENSION_MODE Enable extension mode Not set
PW_LANG_NAME SDK language name for driver Not set
PW_INSTRUMENT_MODULES Enable module load instrumentation Not set
PW_RUNNER_DEBUG Enable runner debug output Not set
PW_TEST_REUSE_CONTEXT Reuse browser context Not set
PW_TEST_CONNECT_WS_ENDPOINT WebSocket endpoint for remote connection Not set
PW_TEST_CONNECT_HEADERS Custom headers for remote connection Not set
PW_TEST_CONNECT_EXPOSE_NETWORK Expose network for remote connection Not set
PW_DISABLE_TS_ESM Disable TypeScript ESM loader Not set
DEBUG Debug namespace (uses debug npm package) Not set
DEBUG_FILE Write debug output to file Not set
NODE_OPTIONS Node.js options (used for TS loader) Not set
XDG_CACHE_HOME XDG cache directory (Linux browser path) ~/.cache
LOCALAPPDATA Local app data (Windows browser path) System default

Appendix B: Key Source Locations

Component Path
Test runner entry packages/playwright/
Core automation packages/playwright-core/
Protocol definitions packages/protocol/
Injected scripts packages/injected/
Selector/locator utilities packages/isomorphic/
Node.js utilities packages/utils/
Dispatcher hierarchy packages/playwright-core/src/server/dispatchers/
Browser patches browser_patches/
Docker tooling utils/docker/
Build system utils/build/build.js
HTML reporter UI packages/html-reporter/
Trace viewer UI packages/trace-viewer/
Codegen recorder UI packages/recorder/