Playwright MCP Skill
Workflow guidance for Microsoft Playwright MCP server. Tool parameters are delivered by MCP tools/list handshake - this skill provides procedures, gotchas, and decision logic.
References (loaded on demand):
- PLAYWRIGHT_TOOLS.md - Complete tool catalog (21 core + 40 opt-in)
- PLAYWRIGHT_CONFIG.md - All CLI flags, env vars, JSON config
- PLAYWRIGHT_AUTHENTICATION.md - Extension mode, persistent profiles
- PLAYWRIGHT_TROUBLESHOOTING.md - Common issues with fixes
- SETUP.md - Installation
- UNINSTALL.md - Uninstallation
MUST-NOT-FORGET
- Use
browser_snapshot(accessibility tree) for element discovery, not screenshots - Element refs are ephemeral - ALWAYS re-snapshot before clicking after any navigation or page change
- Reference elements via
reffrom snapshot (e.g.,ref: "e5") orselector(e.g.,[data-testid="submit"]) - Use
type: "jpeg"for all screenshots (default PNG produces unnecessarily large files) - NEVER auto-close browser - only user may close. Sessions preserve authentication state
browser_fill_formtakesfieldsarray (NOTbrowser_fill).browser_take_screenshot(NOTbrowser_screenshot)- Opt-in tools need
--capsflag. Cookie read needs--caps=storage. Route mocking needs--caps=network browser_evaluateruns in browser (no Node.js APIs).browser_run_coderuns server-side with Playwrightpageobject- Downloads go to
--output-dirpath. Default:.playwright-mcp/under the IDE installation folder (e.g.,[LOCALAPPDATA]\Programs\Devin\.playwright-mcp\). NOT the system Downloads folder. File names are typically UUIDs (e.g.,765984ac-5fcb-4bad-9aa3-e4163a93fa5d) or descriptive names from the server. UseGet-ChildItem "[LOCALAPPDATA]\Programs\Devin\.playwright-mcp" -File | Sort-Object LastWriteTime -Descending | Select-Object -First 10 FullName, Length, LastWriteTimeto find recent downloads. For PDFs, extract text with poppler:& "[TOOLS]\poppler\Library\bin\pdftotext.exe" "<path>" - - Extension mode: Chrome/Edge only, uses Chrome Web Store extension, NOT
--remote-debugging-port fullPage: true+type: "jpeg"is MANDATORY for research, archival, or source-validation screenshots. Viewport-only (fullPage: false) captures ~900px of a 5,000-20,000px page - missing 80-95% of content. PNG produces 3-5x larger files than JPEG with no benefit for text pages. Only use viewport for UI debugging or above-the-fold checks. (GLOB-FL-0042)
Intent Lookup
User wants to...
- Read a webpage / research a topic → Navigate, snapshot, dismiss cookie popup, scroll for lazy content
- Fill out a form → Snapshot to get refs,
browser_fill_formwith fields array, click submit - Take a screenshot →
browser_take_screenshot(type: "jpeg"), orfullPage: truefor complete page - Log into a site → Fill credentials + submit, or use persistent profile. See PLAYWRIGHT_AUTHENTICATION.md
- Use an already logged-in browser → Extension mode (
--extension). See PLAYWRIGHT_AUTHENTICATION.md - Scrape data →
browser_evaluatewith JS to extract DOM content, orbrowser_snapshotfor structured text - Test a web UI → Navigate, snapshot, assert elements present, use
--caps=testingfor verification tools - Download a file → Find link with snapshot, click to download, check output dir
- Interact with a map / canvas / custom widget → Need
--caps=visionfor coordinate-based click/drag - Mock API responses → Need
--caps=network, usebrowser_routewith URL pattern - Handle cookie/General Data Protection Regulation (GDPR) popups → Snapshot, find accept/reject button, click it. See Dismiss Cookie Popup
- Debug browser issues → See PLAYWRIGHT_TROUBLESHOOTING.md
Core Procedures
1. Navigate and Interact
1. browser_navigate(url: "https://example.com")
2. browser_snapshot() # Get element refs
3. # If cookie popup visible: find accept button, click it, re-snapshot
4. browser_click(ref: "e12", element: "Target button")
5. browser_snapshot() # Verify result, get new refs
After EVERY navigation or click that changes the page: re-snapshot. Refs from previous snapshot are invalid.
2. Fill a Form
1. browser_snapshot() # Find form fields
2. browser_fill_form(fields: [
{ref: "e3", name: "Email", type: "textbox", value: "user@example.com"},
{ref: "e5", name: "Password", type: "textbox", value: "password123"}
])
3. browser_click(ref: "e8", element: "Submit button")
4. browser_snapshot() # Verify submission result
Field types: textbox, checkbox (value: "true"/"false"), radio, combobox (value: option text), slider.
3. Full Page Screenshot
1. browser_navigate(url: "https://example.com")
2. browser_snapshot() # Check for cookie popups
3. # Dismiss cookie popup if present
4. # Scroll down to trigger lazy-loaded content:
browser_press_key(key: "End")
browser_wait_for(time: 2)
browser_press_key(key: "Home")
5. browser_take_screenshot(fullPage: true, type: "jpeg")
4. Extract Data with JavaScript
1. browser_navigate(url: "https://example.com")
2. browser_evaluate(function: "document.querySelectorAll('h2').length")
3. browser_evaluate(function: "JSON.stringify([...document.querySelectorAll('tr')].map(r => r.textContent))")
browser_evaluate runs in browser context. No Node.js APIs. Return values must be serializable.
For Playwright API access (e.g., page.locator()), use browser_run_code instead.
5. Dismiss Cookie/GDPR Popup
1. browser_snapshot()
2. # Look for buttons with text: Accept, Agree, OK, Got it, Allow, Consent
3. browser_click(ref: "<popup-button-ref>", element: "Accept cookies")
4. browser_snapshot() # Verify popup dismissed
If popup uses iframe: snapshot may show it nested. Try clicking by text selector: selector: "text=Accept".
6. Scroll and Load Lazy Content
1. browser_press_key(key: "End") # Scroll to bottom
2. browser_wait_for(time: 2) # Wait for lazy load
3. browser_snapshot() # Check if new content appeared
4. # Repeat if more content expected
For infinite scroll: repeat scroll+wait+snapshot in a loop until content stops changing.
Element Targeting
Two methods (v0.0.69+):
reffrom snapshot (preferred) -ref: "e5"from latestbrowser_snapshotselector(when refs unavailable) - priority order:[data-testid="submit"]- Test IDs (most stable)role=button[name="Save"]- Semantic rolestext=Sign in- Visible textinput[name="email"]- HTML attributes
All interaction tools (browser_click, browser_type, browser_hover, etc.) accept both ref and selector.
Capabilities Quick Reference
Core 21 tools always available. Opt-in categories enabled via --caps:
- network - Route mocking, offline toggle
- storage - Cookie/localStorage/sessionStorage Create/Read/Update/Delete (CRUD)
- devtools - Tracing, video recording, debugger
- vision - Coordinate-based mouse (for canvas/maps)
- pdf - Save page as PDF
- testing - Element/text/value verification, locator generation
- config - Read resolved server configuration
Enable all: --caps vision,pdf,devtools,network,storage,testing,config. Tool details: PLAYWRIGHT_TOOLS.md
Gotchas
- Refs invalidated by any page change - navigation, DOM mutation, dynamic content. Always re-snapshot before interacting
browser_fill_formnotbrowser_fill- Old name deprecated. New API takesfieldsarray, not single fieldbrowser_take_screenshotnotbrowser_screenshot- Old name deprecatedbrowser_evaluateruns in BROWSER - No Node.js. Usebrowser_run_codefor server-side Playwright API- Cookie read needs
--caps=storage- Even basicbrowser_cookie_listis gated browser_network_requestsis core - Read-only request listing. Route mocking needs--caps=network- Extension mode is Chrome/Edge only - Firefox/WebKit not supported
--no-sandboxwarning is cosmetic - Browser works correctly. Required in Docker/WSL2- Default screenshot format is PNG - Always specify
type: "jpeg"for smaller files - Profile lock error - Previous Chrome didn't shut down cleanly. Close Chrome instances or delete lock file
Quick Config
Basic (persistent profile, default):
{"mcpServers": {"playwright": {"command": "npx", "args": ["@playwright/mcp@latest"]}}}
Persistent profile with all capabilities:
{"mcpServers": {"playwright": {"command": "npx", "args": ["@playwright/mcp@latest", "--caps", "vision,pdf,devtools,network,storage,testing,config"]}}}
Extension mode (existing browser):
{"mcpServers": {"playwright": {"command": "npx", "args": ["@playwright/mcp@latest", "--extension"]}}}
Full config reference: PLAYWRIGHT_CONFIG.md