mcpField
P
playwright

playwright

github.com/dashedTesting & quality2541 installsUpdated 1w ago
Repository

About playwright

playwright is a browser automation skill for web testing and routine page operations, using Python scripts run with uv. It provides command-line scripts for navigation, screenshots, content extraction, form submission, and JavaScript evaluation.

Key features

  1. 01Browser navigation and screenshots
  2. 02Page text and link extraction
  3. 03Form filling and submission
  4. 04JavaScript evaluation
  5. 05Trace capture for debugging

Use cases

  1. 01Capturing web page screenshots
  2. 02Extracting page content and links
  3. 03Automating login or other forms
  4. 04Debugging browser automation with traces

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/dashed/claude-marketplace --skill playwright

After installing, type/playwrightin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
api-reference.md
custom-scripts.md
selectors.md
troubleshooting.md

Details

From the project README

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 protected]" \
  --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("[email protected]")

            # 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("[email protected]")
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

OperationCode
Navigatepage.goto("https://url")
Clickpage.get_by_role("button", name="X").click()
Fill inputpage.get_by_label("Email").fill("value")
Get textpage.get_by_role("heading").text_content()
Screenshotpage.screenshot(path="/tmp/shot.png")
Waitpage.get_by_text("Loaded").wait_for()
Evaluate JSpage.evaluate("document.title")

Environment Variables

VariableDescriptionDefault
HEADLESSRun browser headless0 (headed)
SLOW_MOSlow down actions (ms)0
VIEWPORTBrowser viewport1280x720
TRACEEnable tracing0 (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:

Comments

Markdown supported