Repository: microsoft/playwright
Stars: 86684
CLAUDE.md
Monorepo Packages
| Package | npm name | Purpose |
|---------|----------|---------|
| playwright-core | playwright-core | Browser automation engine: client, server, dispatchers, protocol |
| playwright | playwright | Test runner + browser automation (public package) |
| playwright-test | @playwright/test | Test runner entry point |
| playwright-client | @playwright/client | Standalone client package |
| protocol | (internal) | RPC protocol definitions (protocol.yml → generated channels.d.ts) |
Browser Packages
playwright-chromium, playwright-firefox, playwright-webkit — per-browser distributions.playwright-browser-chromium, playwright-browser-firefox, playwright-browser-webkit — binary packages.
Tooling Packages
| Package | Purpose |
|---------|---------|
| html-reporter | HTML test report viewer |
| trace-viewer | Trace viewer UI |
| recorder | Test recorder |
| web | Shared web UI components |
| injected | Scripts injected into browser pages |
Component Testing
playwright-ct-core, playwright-ct-react, playwright-ct-vue
Key Directories
| Directory | Purpose |
|-----------|---------|
| tests/ | All test suites (page, library, playwright-test, mcp, components, etc.) |
| docs/src/ | API documentation — source of truth for public TypeScript types |
| docs/src/api/ | Per-class API reference (class-page.md, class-locator.md, etc.) |
| utils/ | Build scripts, code generation, linting, doc tools |
| browser_patches/ | Browser engine patches |
Build
npm run build # Full build
npm run watch # Watch mode (recommended during development)Assume watch is running and code is up to date. Generated files (types, channels, validators) are produced by watch automatically.
Lint and type check
npm run flintRuns all lint checks in parallel: eslint, tsc, doclint, check-deps, generate_channels, generate_types, lint-tests, test-types, lint-packages, code-snippet linting.
Always run flint before committing. Do not use tsc --noEmit or individual lint commands separately.
Test Commands
| Command | Scope |
|---------|-------|
| npm run ctest <filter> | Chromium only library tests — use during development |
| npm run test <filter> -- --project=<chromium,firefix,webkit> | All library / per project |
| npm run ttest <filter> | Test runner (tests/playwright-test/) |
| npm run ctest-mcp <filter> | Chromium only MCP tools (tests/mcp/) |
| npm run test-mcp <filter> -- --project=<chromium,firefox,webkit> | MCP tools (tests/mcp/) |
Filtering
npm run ctest tests/page/locator-click.spec.ts # Specific file
npm run ctest tests/page/locator-click.spec.ts:12 # Specific location
npm run ctest -- --grep "should click" # By test name
npm run ctest-mcp snapshot # By file name partTest Directories and Fixtures
| Directory | Import | Key Fixtures | What to Test |
|-----------|--------|--------------|--------------|
| tests/page/ | import { test, expect } from './pageTest' | page, server, browserName | User interactions: click, fill, navigate, locators, assertions |
| tests/library/ | import { browserTest, expect } from '../config/browserTest' | browser, context, browserType | Browser/context lifecycle, cookies, permissions, browser-specific features |
| tests/playwright-test/ | import { test, expect } from './playwright-test-fixtures' | test runner fixtures | Test runner: reporters, config, annotations, retries |
| tests/mcp/ | import { test, expect } from './fixtures' | client, server | MCP tools via client.callTool() |
Decision rule: Does the test need browser/browserType/context → tests/library/. Just needs page + server → tests/page/.
DEPS System
Import boundaries are enforced via DEPS.list files (52+ across the repo), checked by npm run flint.
Key rule: Client code NEVER imports server code. Server code NEVER imports client code. Communication is only through the protocol.
When creating or moving files, update the relevant DEPS.list to declare allowed imports. Files marked "strict" can only import what is explicitly listed.
Coding Convention
For exported classes:
- private _method() — only used within the class itself
- _method() (no private) — used by other code in the same file, but not outside the file
- method() (public) — used in other files
Non-exported classes have no naming convention; they are internal implementation details.
Commit Convention
Before committing, run npm run flint and fix errors.
Semantic commit messages: label(scope): description
Labels: fix, feat, chore, docs, test, devops
git checkout -b fix-39562
... make changes ...
git add <changed-files>
git commit -m "$(cat <<'EOF'
fix(proxy): handle SOCKS proxy authenticationFixes: https://github.com/microsoft/playwright/issues/39562
EOF
)"
git push origin fix-39562
gh pr create --repo microsoft/playwright --head username:fix-39562 \
--title "fix(proxy): handle SOCKS proxy authentication" \
--body "$(cat <<'EOF'
Summary
- <describe the change very! briefly>Fixes https://github.com/microsoft/playwright/issues/39562
EOF
)"
Never add Co-Authored-By agents in commit message.
Never add "Generated with" in commit message.
Never add test plan to PR description. Keep PR description short — a few bullet points at most.
Branch naming for issue fixes: fix-<issue-number>
Never git push without an explicit instruction to push. Applies even when a PR is already open for the branch — additional commits are immediately visible to reviewers. Commit locally, report what was committed, and wait. Only push when the user's message contains "push", "upload", "create PR", "ship it", or equivalent.
Development Guides
Detailed guides for common development tasks:
- Architecture: Client, Server, and Dispatchers — package layout, protocol layer, ChannelOwner/SdkObject/Dispatcher base classes, DEPS rules, end-to-end RPC flow, object lifecycle
- Adding and Modifying APIs — 6-step process: define docs → implement client → define protocol → implement dispatcher → implement server → write tests
- MCP Tools and CLI Commands — defineTool()/defineTabTool(), tool capabilities, CLI declareCommand(), config options, testing with MCP fixtures
- Vendoring Dependencies — bundle architecture, esbuild setup, typed wrappers, adding deps to existing bundles
README.md
🎭 Playwright
 <!-- GEN:chromium-version-badge --><!-- GEN:stop --> <!-- GEN:firefox-version-badge --><!-- GEN:stop --> <!-- GEN:webkit-version-badge --><!-- GEN:stop --> 
Documentation | API reference
Playwright is a framework for web automation and testing. It drives Chromium, Firefox, and WebKit with a single API — in your tests, in your scripts, and as a tool for AI agents.
Get Started
Choose the path that fits your workflow:
| | Best for | Install |
|---|---|---|
| Playwright Test | End-to-end testing | npm init playwright@latest |
| Playwright CLI | Coding agents (Claude Code, Copilot) | npm i -g @playwright/cli@latest |
| Playwright MCP | AI agents and LLM-driven automation | npx @playwright/mcp@latest |
| Playwright Library | Browser automation scripts | npm i playwright |
| VS Code Extension | Test authoring and debugging in VS Code | Install from Marketplace |
---
Playwright Test
Playwright Test is a full-featured test runner built for end-to-end testing. It runs tests across Chromium, Firefox, and WebKit with full browser isolation, auto-waiting, and web-first assertions.
Install
npm init playwright@latestOr add manually:
npm i -D @playwright/test
npx playwright installWrite a test
import { test, expect } from '@playwright/test';test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Run tests
npx playwright testTests run in parallel across all configured browsers, in headless mode by default. Each test gets a fresh browser context — full isolation with near-zero overhead.
Key capabilities
Auto-wait and web-first assertions. No artificial timeouts. Playwright waits for elements to be actionable, and assertions automatically retry until conditions are met.
Locators. Find elements with resilient locators that mirror how users see the page:
page.getByRole('button', { name: 'Submit' })
page.getByLabel('Email')
page.getByPlaceholder('Search...')
page.getByTestId('login-form')Test isolation. Each test runs in its own browser context — equivalent to a fresh browser profile. Save authentication state once and reuse it across tests:
// Save state after login
await page.context().storageState({ path: 'auth.json' });// Reuse in other tests
test.use({ storageState: 'auth.json' });
Tracing. Capture execution traces, screenshots, and videos on failure. Inspect every action, DOM snapshot, network request, and console message in the Trace Viewer:
// playwright.config.ts
export default defineConfig({
use: {
trace: 'on-first-retry',
},
});npx playwright show-trace trace.zip<!-- TODO: screenshot of trace viewer -->
Parallelism. Tests run in parallel by default across all configured browsers.
---
Playwright CLI
Playwright CLI is a command-line interface for browser automation designed for coding agents. It's more token-efficient than MCP — commands avoid loading large tool schemas and accessibility trees into the model context.
Install
npm install -g @playwright/cli@latestOptionally install skills for richer agent integration:
playwright-cli install --skillsUsage
Point your coding agent at a task:
Test the "add todo" flow on https://demo.playwright.dev/todomvc using playwright-cli.
Take screenshots for all successful and failing scenarios.Or run commands directly:
playwright-cli open https://demo.playwright.dev/todomvc/ --headed
playwright-cli type "Buy groceries"
playwright-cli press Enter
playwright-cli screenshotSession monitoring
Use playwright-cli show to open a visual dashboard with live screencast previews of all running browser sessions. Click any session to zoom in and take remote control.
playwright-cli show<!-- TODO: screenshot of playwright-cli show dashboard -->
Full CLI documentation | GitHub
---
Playwright MCP
The Playwright MCP server gives AI agents full browser control through the Model Context Protocol. Agents interact with pages using structured accessibility snapshots — no vision models or screenshots required.
Setup
Add to your MCP client (VS Code, Cursor, Claude Desktop, Windsurf, etc.):
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
}
}
}One-click install for VS Code:
For Claude Code:
claude mcp add playwright npx @playwright/mcp@latestHow it works
Ask your AI assistant to interact with any web page:
Navigate to https://demo.playwright.dev/todomvc and add a few todo items.The agent sees the page as a structured accessibility tree:
- heading "todos" [level=1]
- textbox "What needs to be done?" [ref=e5]
- listitem:
- checkbox "Toggle Todo" [ref=e10]
- text: "Buy groceries"It uses element refs like e5 and e10 to click, type, and interact — deterministically and without visual ambiguity. Tools cover navigation, form filling, screenshots, network mocking, storage management, and more.
Full MCP documentation | GitHub
---
Playwright Library
Use playwright as a library for browser automation scripts — web scraping, PDF generation, screenshot capture, and any workflow that needs programmatic browser control without a test runner.
Install
npm i playwrightExamples
Take a screenshot:
import { chromium } from 'playwright';const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev/');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
Generate a PDF:
import { chromium } from 'playwright';const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://playwright.dev/');
await page.pdf({ path: 'page.pdf', format: 'A4' });
await browser.close();
Emulate a mobile device:
import { chromium, devices } from 'playwright';const browser = await chromium.launch();
const context = await browser.newContext(devices['iPhone 15']);
const page = await context.newPage();
await page.goto('https://playwright.dev/');
await page.screenshot({ path: 'mobile.png' });
await browser.close();
Intercept network requests:
import { chromium } from 'playwright';const browser = await chromium.launch();
const page = await browser.newPage();
await page.route('/*.{png,jpg,jpeg}', route => route.abort());
await page.goto('https://playwright.dev/');
await browser.close();
Library documentation | API reference
---
VS Code Extension
The Playwright VS Code extension brings test running, debugging, and code generation directly into your editor.
<!-- TODO: hero screenshot of VS Code with Playwright sidebar -->
Run and debug tests from the editor with a single click. Set breakpoints, inspect variables, and step through test execution with a live browser view.
Generate tests with CodeGen. Click "Record new" to open a browser — navigate and interact with your app while Playwright writes the test code for you.
Pick locators. Hover over any element in the browser to see the best available locator, then click to copy it to your clipboard.
Trace Viewer integration. Enable "Show Trace Viewer" in the sidebar to get a full execution trace after each test run — DOM snapshots, network requests, console logs, and screenshots at every step.
Install the extension | VS Code guide
---
Cross-Browser Support
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium<sup>1</sup> <!-- GEN:chromium-version -->147.0.7727.49<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->26.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->149.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless and headed execution on all platforms. <sup>1</sup> Uses Chrome for Testing by default.
Other Languages
Playwright is also available for Python, .NET, and Java.
Resources
* Documentation
* API reference
* MCP server
* CLI for coding agents
* VS Code extension
* Contribution guide
* Changelog
* Discord