Playwright Browser Automation
Overview
Playwright enables browser automation for web testing, screenshots, form filling, and scraping. This skill uses Python with uv for self-contained scripts that require no global installation.
Prerequisites
-
Python 3.10+
-
uv package manager
-
Playwright browser binaries (one-time setup)
Setup (First Time Only)
Claude: Do not run browser installation commands directly. Suggest these commands to the user and let them run manually. This is a one-time setup that downloads ~200MB of browser binaries.
Suggest the user run:
Install Chromium (recommended, ~200MB)
uv run --with playwright playwright install chromium
Or install all browsers
uv run --with playwright playwright install
To verify installation:
uv run /path/to/plugins/playwright/scripts/check_setup.py
Quick Start
Take a screenshot of any URL:
uv run /path/to/plugins/playwright/scripts/screenshot.py https://example.com
Output: /tmp/screenshot-{timestamp}.png
Common Patterns
Take a Screenshot
Default (visible browser)
uv run scripts/screenshot.py https://example.com
Full page, headless
uv run scripts/screenshot.py https://example.com --full-page --headless
Custom output path
uv run scripts/screenshot.py https://example.com -o /tmp/my-shot.png
Navigate and Extract Content
Get page title and URL
uv run scripts/navigate.py https://example.com
Extract all links as JSON
uv run scripts/navigate.py https://example.com --links
Get page text content
uv run scripts/navigate.py https://example.com --text
Fill and Submit Forms
uv run scripts/fill_form.py https://example.com/login
--field "email=test@example.com"
--field "password=secret123"
--submit
Execute JavaScript
uv run scripts/evaluate.py https://example.com "document.title" uv run scripts/evaluate.py https://example.com "document.querySelectorAll('a').length"
Writing Custom Scripts
Save this template to /tmp/my-automation.py :
#!/usr/bin/env -S uv run --script
/// script
requires-python = ">=3.10"
dependencies = ["playwright==1.56.0"]
///
"""Custom Playwright automation script."""
import os import sys from playwright.sync_api import sync_playwright
HEADLESS = os.getenv("HEADLESS", "0").lower() in ("1", "true", "yes")
def main(): with sync_playwright() as p: browser = p.chromium.launch(headless=HEADLESS) page = browser.new_page()
try:
page.goto("https://example.com")
print(f"Title: {page.title()}")
# Use semantic locators (preferred)
page.get_by_role("button", name="Submit").click()
page.get_by_label("Email").fill("test@example.com")
# Screenshot
page.screenshot(path="/tmp/result.png")
except Exception as e:
page.screenshot(path="/tmp/error.png")
print(f"Error: {e}", file=sys.stderr)
return 1
finally:
browser.close()
return 0
if name == "main": sys.exit(main())
Run with:
uv run /tmp/my-automation.py
Modern Locator API
Prefer semantic locators over CSS selectors:
PREFERRED: Semantic locators (accessible, stable)
page.get_by_role("button", name="Submit").click() page.get_by_label("Email").fill("user@example.com") page.get_by_placeholder("Search...").fill("query") page.get_by_text("Welcome back").wait_for() page.get_by_test_id("submit-btn").click()
AVOID: Raw CSS selectors (fragile)
page.locator("button.btn-primary").click() # Don't use
Combine locators:
OR: Match either
page.get_by_role("button", name="New").or_( page.get_by_text("Create") ).click()
Filter: Narrow down
page.locator("tr").filter(has_text="Active").first.click()
Quick Reference
Operation Code
Navigate page.goto("https://url")
Click page.get_by_role("button", name="X").click()
Fill input page.get_by_label("Email").fill("value")
Get text page.get_by_role("heading").text_content()
Screenshot page.screenshot(path="/tmp/shot.png")
Wait page.get_by_text("Loaded").wait_for()
Evaluate JS page.evaluate("document.title")
Environment Variables
Variable Description Default
HEADLESS
Run browser headless 0 (headed)
SLOW_MO
Slow down actions (ms) 0
VIEWPORT
Browser viewport 1280x720
TRACE
Enable tracing 0 (off)
Example:
HEADLESS=1 SLOW_MO=250 uv run scripts/screenshot.py https://example.com
Tracing for Debugging
Enable tracing to debug complex automations:
context.tracing.start(screenshots=True, snapshots=True, sources=True)
... your automation ...
context.tracing.stop(path="/tmp/trace.zip")
View the trace:
uv run --with playwright playwright show-trace /tmp/trace.zip
Troubleshooting
"Browser not found"
Suggest the user install browser binaries (do not run directly):
uv run --with playwright playwright install chromium
"Timeout waiting for element"
Use proper waiting strategies:
Wait for element to be visible
page.get_by_text("Loaded").wait_for(state="visible")
Wait for network idle
page.goto(url, wait_until="networkidle")
"Element not interactable"
Ensure element is visible and scroll into view:
element = page.get_by_role("button", name="Submit") element.scroll_into_view_if_needed() element.click()
Headless mode issues
Debug with headed mode:
HEADLESS=0 uv run scripts/screenshot.py https://example.com
Container/CI Issues
Use these Chromium flags:
browser = p.chromium.launch( headless=True, args=["--disable-dev-shm-usage", "--no-sandbox"] )
Advanced Usage
For comprehensive documentation, see:
-
references/api-reference.md - Full API reference
-
references/selectors.md - Selector patterns
-
references/custom-scripts.md - Script templates
-
references/troubleshooting.md - Common issues