Playwright
Overview
Playwright is a browser automation framework for Node.js and Python supporting Chromium, Firefox, and WebKit with a single API. It provides auto-waiting, web-first assertions, and full test isolation for reliable end-to-end testing.
When to use: Browser automation, web scraping, screenshot/PDF generation, API testing, configuring Playwright Test, troubleshooting Playwright errors, stealth mode and anti-bot bypass.
When NOT to use: Simple HTTP requests (use fetch), unit testing (use Vitest/Jest), serverless scraping at scale (consider Cloudflare Browser Rendering). For E2E test architecture (Page Object Models, CI sharding, test organization, authentication patterns), use the e2e-testing skill.
Quick Reference
| Pattern |
API / Config |
Key Points |
| Basic test |
test('name', async ({ page }) => {}) |
Auto-wait, web-first assertions, test isolation |
| Locator |
page.getByRole() / page.locator() |
Prefer role/label/text selectors over CSS |
| Assertion |
expect(locator).toBeVisible() |
Auto-retrying, configurable timeout |
| API testing |
request fixture / apiRequestContext |
Send HTTP requests, validate responses |
| Aria snapshot |
expect(locator).toMatchAriaSnapshot() |
Validate accessibility tree structure via YAML |
| Class assertion |
expect(locator).toContainClass('active') |
Match individual CSS class names (v1.52+) |
| Visible filter |
locator.filter({ visible: true }) |
Match only visible elements (v1.51+) |
| Test step |
test.step('name', async (step) => {}) |
Timeout, skip, and attachments (v1.50+) |
| Stealth mode |
playwright-extra + stealth plugin |
Patches 20+ detection vectors |
| Authenticated session |
context.cookies() + addCookies() |
Save/restore cookies and IndexedDB for persistence |
| Screenshot |
page.screenshot({ fullPage: true }) |
Wait for key elements to load first |
| PDF generation |
page.pdf({ format: 'A4' }) |
Chromium only, set printBackground: true |
| Clock API |
page.clock |
Freeze, fast-forward, or simulate time in tests |
| A11y assertions |
toHaveAccessibleName, toHaveRole |
Native assertions without axe-core dependency |
| Viewport assertion |
expect(locator).toBeInViewport() |
Assert element is within the visible viewport |
| Changed tests only |
--only-changed=$GITHUB_BASE_REF |
Run only test files changed since base branch |
| Docker |
mcr.microsoft.com/playwright:v1.58.2-noble |
Use --init --ipc=host flags |
| Debug methods |
page.consoleMessages() / page.requests() (v1.56+) |
No event listeners needed |
| Speedboard |
HTML reporter (v1.57+) |
Identifies slow tests and bottlenecks |
| Playwright Agents |
npx playwright init-agents |
Planner, generator, healer for LLM-driven testing |
| Flaky test detection |
--fail-on-flaky-tests (v1.50+) |
Exit code 1 on flaky tests in CI |
| Modify live responses |
route.fetch() + route.fulfill() |
Intercept real response, tweak JSON, return it |
| Soft assertions |
expect.soft(locator) |
Don't stop test on failure, report all at end |
| Retry block |
expect(async () => {}).toPass() |
Default timeout is 0 (forever) — always set one |
| Custom matchers |
expect.extend() / mergeExpects() |
Define or combine custom assertion methods |
| Actionability matrix |
Per-action auto-wait checks |
click: all 5 checks, fill: 3, focus/blur: none |
| Test modifiers |
test.fixme() / test.fail() / test.slow() |
fixme=skip+track, fail=assert failure, slow=3x |
| Parallel modes |
test.describe.configure({ mode: 'serial' }) |
serial, parallel, or default per-describe block |
| Teardown projects |
teardown option on setup projects |
Auto-cleanup after all dependents finish |
Common Mistakes
| Mistake |
Correct Pattern |
| Using CSS selectors over role selectors |
Prefer getByRole, getByLabel, getByText for resilience |
| Not closing browser |
Always await browser.close() in finally block |
Using setTimeout for waits |
Use locator auto-wait or waitForLoadState |
page.pause() left in CI code |
Guard with if (!process.env.CI) — hangs CI indefinitely |
| Clicking without waiting |
Use locator().click() with built-in auto-wait |
| Shared state between tests |
Each test gets fresh context via fixtures |
| Testing implementation details |
Assert user-visible behavior, not DOM structure |
| Hardcoded waits for dynamic content |
Wait for selector appearance or content stabilization |
Missing await on assertions |
All expect() assertions return promises — must be awaited |
| Same user agent for all scraping |
Rotate user agents for high-volume scraping |
Using setTimeout for time-dependent tests |
Use page.clock API to freeze/fast-forward time |
| Installing axe-core for simple a11y checks |
Use native toHaveAccessibleName/toHaveRole assertions |
Using toPass() without explicit timeout |
Always pass { timeout: 10_000 } — default is 0 (forever) |
Service worker silently blocking page.route() |
Set serviceWorkers: 'block' in context config when using MSW |
Using fill() for autocomplete/debounce inputs |
Use pressSequentially() with optional delay for per-keystroke handling |
storageState losing sessionStorage |
storageState only saves cookies + localStorage — inject sessionStorage via addInitScript() |
Delegation
- Selector troubleshooting: Use
Explore agent
- Test pattern review: Use
Task agent
- Code review: Delegate to
code-reviewer agent
For E2E test architecture, Page Object Model patterns, CI sharding strategies, authentication flows, visual regression workflows, or test organization, use the e2e-testing skill.
References
- Quick start and installation
- E2E testing patterns and assertions
- Selector strategies and best practices
- Configuration and Docker deployment
- Docker and CI
- Debug methods and performance analysis
- Common automation patterns
- Stealth mode and anti-bot bypass
- Known issues and solutions
- Site-specific blocking and bypasses
- Troubleshooting common problems
- Network testing, mocking, and API patterns
- Input patterns, actionability, and test modifiers
- Advanced assertions, polling, custom matchers, and annotations
- Advanced topics: MCP, AI agents, parallel contexts
1---
2name: playwright
3description: |
4 Playwright browser automation API, web scraping, and tooling. Covers locator strategies, assertions, API testing, stealth mode, anti-bot bypass, authenticated sessions, screenshots/PDFs, Docker deployment, configuration, debugging, and MCP integration with AI agents. Prevents documented errors including CI timeout hangs, extension testing failures, and navigation issues.
5
6 Use when automating browsers, scraping protected sites, bypassing bot detection, generating screenshots/PDFs, configuring Playwright Test, troubleshooting Playwright errors, or learning Playwright API patterns. For E2E test architecture, Page Object Models, CI sharding strategies, or test organization patterns, use the e2e-testing skill instead.
7license: MIT
8metadata:
9 author: oakoss
10 version: '1.1'
11user-invocable: false
12---
13
14# Playwright
15
16## Overview
17
18Playwright is a browser automation framework for Node.js and Python supporting Chromium, Firefox, and WebKit with a single API. It provides auto-waiting, web-first assertions, and full test isolation for reliable end-to-end testing.
19
20**When to use:** Browser automation, web scraping, screenshot/PDF generation, API testing, configuring Playwright Test, troubleshooting Playwright errors, stealth mode and anti-bot bypass.
21
22**When NOT to use:** Simple HTTP requests (use `fetch`), unit testing (use Vitest/Jest), serverless scraping at scale (consider Cloudflare Browser Rendering). For E2E test architecture (Page Object Models, CI sharding, test organization, authentication patterns), use the `e2e-testing` skill.
23
24## Quick Reference
25
26| Pattern | API / Config | Key Points |
27| --------------------- | ----------------------------------------------------- | -------------------------------------------------- |
28| Basic test | `test('name', async ({ page }) => {})` | Auto-wait, web-first assertions, test isolation |
29| Locator | `page.getByRole()` / `page.locator()` | Prefer role/label/text selectors over CSS |
30| Assertion | `expect(locator).toBeVisible()` | Auto-retrying, configurable timeout |
31| API testing | `request` fixture / `apiRequestContext` | Send HTTP requests, validate responses |
32| Aria snapshot | `expect(locator).toMatchAriaSnapshot()` | Validate accessibility tree structure via YAML |
33| Class assertion | `expect(locator).toContainClass('active')` | Match individual CSS class names (v1.52+) |
34| Visible filter | `locator.filter({ visible: true })` | Match only visible elements (v1.51+) |
35| Test step | `test.step('name', async (step) => {})` | Timeout, skip, and attachments (v1.50+) |
36| Stealth mode | `playwright-extra` + stealth plugin | Patches 20+ detection vectors |
37| Authenticated session | `context.cookies()` + `addCookies()` | Save/restore cookies and IndexedDB for persistence |
38| Screenshot | `page.screenshot({ fullPage: true })` | Wait for key elements to load first |
39| PDF generation | `page.pdf({ format: 'A4' })` | Chromium only, set `printBackground: true` |
40| Clock API | `page.clock` | Freeze, fast-forward, or simulate time in tests |
41| A11y assertions | `toHaveAccessibleName`, `toHaveRole` | Native assertions without axe-core dependency |
42| Viewport assertion | `expect(locator).toBeInViewport()` | Assert element is within the visible viewport |
43| Changed tests only | `--only-changed=$GITHUB_BASE_REF` | Run only test files changed since base branch |
44| Docker | `mcr.microsoft.com/playwright:v1.58.2-noble` | Use `--init --ipc=host` flags |
45| Debug methods | `page.consoleMessages()` / `page.requests()` (v1.56+) | No event listeners needed |
46| Speedboard | HTML reporter (v1.57+) | Identifies slow tests and bottlenecks |
47| Playwright Agents | `npx playwright init-agents` | Planner, generator, healer for LLM-driven testing |
48| Flaky test detection | `--fail-on-flaky-tests` (v1.50+) | Exit code 1 on flaky tests in CI |
49| Modify live responses | `route.fetch()` + `route.fulfill()` | Intercept real response, tweak JSON, return it |
50| Soft assertions | `expect.soft(locator)` | Don't stop test on failure, report all at end |
51| Retry block | `expect(async () => {}).toPass()` | Default timeout is 0 (forever) — always set one |
52| Custom matchers | `expect.extend()` / `mergeExpects()` | Define or combine custom assertion methods |
53| Actionability matrix | Per-action auto-wait checks | click: all 5 checks, fill: 3, focus/blur: none |
54| Test modifiers | `test.fixme()` / `test.fail()` / `test.slow()` | fixme=skip+track, fail=assert failure, slow=3x |
55| Parallel modes | `test.describe.configure({ mode: 'serial' })` | serial, parallel, or default per-describe block |
56| Teardown projects | `teardown` option on setup projects | Auto-cleanup after all dependents finish |
57
58## Common Mistakes
59
60| Mistake | Correct Pattern |
61| ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |
62| Using CSS selectors over role selectors | Prefer `getByRole`, `getByLabel`, `getByText` for resilience |
63| Not closing browser | Always `await browser.close()` in `finally` block |
64| Using `setTimeout` for waits | Use locator auto-wait or `waitForLoadState` |
65| `page.pause()` left in CI code | Guard with `if (!process.env.CI)` — hangs CI indefinitely |
66| Clicking without waiting | Use `locator().click()` with built-in auto-wait |
67| Shared state between tests | Each test gets fresh context via fixtures |
68| Testing implementation details | Assert user-visible behavior, not DOM structure |
69| Hardcoded waits for dynamic content | Wait for selector appearance or content stabilization |
70| Missing `await` on assertions | All `expect()` assertions return promises — must be awaited |
71| Same user agent for all scraping | Rotate user agents for high-volume scraping |
72| Using `setTimeout` for time-dependent tests | Use `page.clock` API to freeze/fast-forward time |
73| Installing axe-core for simple a11y checks | Use native `toHaveAccessibleName`/`toHaveRole` assertions |
74| Using `toPass()` without explicit timeout | Always pass `{ timeout: 10_000 }` — default is 0 (forever) |
75| Service worker silently blocking `page.route()` | Set `serviceWorkers: 'block'` in context config when using MSW |
76| Using `fill()` for autocomplete/debounce inputs | Use `pressSequentially()` with optional delay for per-keystroke handling |
77| `storageState` losing sessionStorage | `storageState` only saves cookies + localStorage — inject sessionStorage via `addInitScript()` |
78
79## Delegation
80
81- **Selector troubleshooting**: Use `Explore` agent
82- **Test pattern review**: Use `Task` agent
83- **Code review**: Delegate to `code-reviewer` agent
84
85> For E2E test architecture, Page Object Model patterns, CI sharding strategies, authentication flows, visual regression workflows, or test organization, use the `e2e-testing` skill.
86
87## References
88
89- [Quick start and installation](references/quick-start.md)
90- [E2E testing patterns and assertions](references/testing-patterns.md)
91- [Selector strategies and best practices](references/selector-strategies.md)
92- [Configuration and Docker deployment](references/configuration.md)
93- [Docker and CI](references/docker-and-ci.md)
94- [Debug methods and performance analysis](references/debug-and-performance.md)
95- [Common automation patterns](references/common-patterns.md)
96- [Stealth mode and anti-bot bypass](references/stealth-mode.md)
97- [Known issues and solutions](references/known-issues.md)
98- [Site-specific blocking and bypasses](references/blocking-and-bypasses.md)
99- [Troubleshooting common problems](references/troubleshooting.md)
100- [Network testing, mocking, and API patterns](references/network-testing.md)
101- [Input patterns, actionability, and test modifiers](references/input-and-actions.md)
102- [Advanced assertions, polling, custom matchers, and annotations](references/advanced-assertions.md)
103- [Advanced topics: MCP, AI agents, parallel contexts](references/advanced-topics.md)