Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    leegonzales

    playwright-browser-automation

    leegonzales/playwright-browser-automation
    DevOps
    16
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Complete browser automation with Playwright. Auto-detects dev servers, writes clean test scripts to /tmp.

    SKILL.md

    IMPORTANT - Path Resolution: This skill can be installed in different locations (plugin system, manual installation, global, or project-specific). Before executing any commands, determine the skill directory based on where you loaded this SKILL.md file, and use that path in all commands below. Replace $SKILL_DIR with the actual discovered path.

    Common installation paths:

    • Plugin system: ~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill
    • Manual global: ~/.claude/skills/playwright-skill
    • Project-specific: <project>/.claude/skills/playwright-skill

    Playwright Browser Automation

    General-purpose browser automation skill. I'll write custom Playwright code for any automation task you request and execute it via the universal executor.

    CRITICAL WORKFLOW - Follow these steps in order:

    1. Auto-detect dev servers - For localhost testing, ALWAYS run server detection FIRST:

      cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
      
      • If 1 server found: Use it automatically, inform user
      • If multiple servers found: Ask user which one to test
      • If no servers found: Ask for URL or offer to help start dev server
    2. Write scripts to /tmp - NEVER write test files to skill directory; always use /tmp/playwright-test-*.js

    3. Use visible browser by default - Always use headless: false unless user specifically requests headless mode

    4. Parameterize URLs - Always make URLs configurable via environment variable or constant at top of script

    How It Works

    1. You describe what you want to test/automate
    2. I auto-detect running dev servers (or ask for URL if testing external site)
    3. I write custom Playwright code in /tmp/playwright-test-*.js (won't clutter your project)
    4. I execute it via: cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js
    5. Results displayed in real-time, browser window visible for debugging
    6. Test files auto-cleaned from /tmp by your OS

    Setup (First Time)

    cd $SKILL_DIR
    npm run setup
    

    This installs Playwright and Chromium browser. Only needed once.

    Execution Pattern

    Step 1: Detect dev servers (for localhost testing)

    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
    

    Step 2: Write test script to /tmp with URL parameter

    // /tmp/playwright-test-page.js
    const { chromium } = require('playwright');
    
    // Parameterized URL (detected or user-provided)
    const TARGET_URL = 'http://localhost:3001'; // <-- Auto-detected or from user
    
    (async () => {
      const browser = await chromium.launch({ headless: false });
      const page = await browser.newPage();
    
      await page.goto(TARGET_URL);
      console.log('Page loaded:', await page.title());
    
      await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
      console.log('📸 Screenshot saved to /tmp/screenshot.png');
    
      await browser.close();
    })();
    

    Step 3: Execute from skill directory

    cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js
    

    Common Patterns

    Test a Page (Multiple Viewports)

    // /tmp/playwright-test-responsive.js
    const { chromium } = require('playwright');
    
    const TARGET_URL = 'http://localhost:3001'; // Auto-detected
    
    (async () => {
      const browser = await chromium.launch({ headless: false, slowMo: 100 });
      const page = await browser.newPage();
    
      // Desktop test
      await page.setViewportSize({ width: 1920, height: 1080 });
      await page.goto(TARGET_URL);
      console.log('Desktop - Title:', await page.title());
      await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });
    
      // Mobile test
      await page.setViewportSize({ width: 375, height: 667 });
      await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });
    
      await browser.close();
    })();
    

    Test Login Flow

    // /tmp/playwright-test-login.js
    const { chromium } = require('playwright');
    
    const TARGET_URL = 'http://localhost:3001'; // Auto-detected
    
    (async () => {
      const browser = await chromium.launch({ headless: false });
      const page = await browser.newPage();
    
      await page.goto(`${TARGET_URL}/login`);
    
      await page.fill('input[name="email"]', 'test@example.com');
      await page.fill('input[name="password"]', 'password123');
      await page.click('button[type="submit"]');
    
      // Wait for redirect
      await page.waitForURL('**/dashboard');
      console.log('✅ Login successful, redirected to dashboard');
    
      await browser.close();
    })();
    

    Fill and Submit Form

    // /tmp/playwright-test-form.js
    const { chromium } = require('playwright');
    
    const TARGET_URL = 'http://localhost:3001'; // Auto-detected
    
    (async () => {
      const browser = await chromium.launch({ headless: false, slowMo: 50 });
      const page = await browser.newPage();
    
      await page.goto(`${TARGET_URL}/contact`);
    
      await page.fill('input[name="name"]', 'John Doe');
      await page.fill('input[name="email"]', 'john@example.com');
      await page.fill('textarea[name="message"]', 'Test message');
      await page.click('button[type="submit"]');
    
      // Verify submission
      await page.waitForSelector('.success-message');
      console.log('✅ Form submitted successfully');
    
      await browser.close();
    })();
    

    Check for Broken Links

    const { chromium } = require('playwright');
    
    (async () => {
      const browser = await chromium.launch({ headless: false });
      const page = await browser.newPage();
    
      await page.goto('http://localhost:3000');
    
      const links = await page.locator('a[href^="http"]').all();
      const results = { working: 0, broken: [] };
    
      for (const link of links) {
        const href = await link.getAttribute('href');
        try {
          const response = await page.request.head(href);
          if (response.ok()) {
            results.working++;
          } else {
            results.broken.push({ url: href, status: response.status() });
          }
        } catch (e) {
          results.broken.push({ url: href, error: e.message });
        }
      }
    
      console.log(`✅ Working links: ${results.working}`);
      console.log(`❌ Broken links:`, results.broken);
    
      await browser.close();
    })();
    

    Take Screenshot with Error Handling

    const { chromium } = require('playwright');
    
    (async () => {
      const browser = await chromium.launch({ headless: false });
      const page = await browser.newPage();
    
      try {
        await page.goto('http://localhost:3000', {
          waitUntil: 'networkidle',
          timeout: 10000
        });
    
        await page.screenshot({
          path: '/tmp/screenshot.png',
          fullPage: true
        });
    
        console.log('📸 Screenshot saved to /tmp/screenshot.png');
      } catch (error) {
        console.error('❌ Error:', error.message);
      } finally {
        await browser.close();
      }
    })();
    

    Test Responsive Design

    // /tmp/playwright-test-responsive-full.js
    const { chromium } = require('playwright');
    
    const TARGET_URL = 'http://localhost:3001'; // Auto-detected
    
    (async () => {
      const browser = await chromium.launch({ headless: false });
      const page = await browser.newPage();
    
      const viewports = [
        { name: 'Desktop', width: 1920, height: 1080 },
        { name: 'Tablet', width: 768, height: 1024 },
        { name: 'Mobile', width: 375, height: 667 }
      ];
    
      for (const viewport of viewports) {
        console.log(`Testing ${viewport.name} (${viewport.width}x${viewport.height})`);
    
        await page.setViewportSize({
          width: viewport.width,
          height: viewport.height
        });
    
        await page.goto(TARGET_URL);
        await page.waitForTimeout(1000);
    
        await page.screenshot({
          path: `/tmp/${viewport.name.toLowerCase()}.png`,
          fullPage: true
        });
      }
    
      console.log('✅ All viewports tested');
      await browser.close();
    })();
    

    Inline Execution (Simple Tasks)

    For quick one-off tasks, you can execute code inline without creating files:

    # Take a quick screenshot
    cd $SKILL_DIR && node run.js "
    const browser = await chromium.launch({ headless: false });
    const page = await browser.newPage();
    await page.goto('http://localhost:3001');
    await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true });
    console.log('Screenshot saved');
    await browser.close();
    "
    

    When to use inline vs files:

    • Inline: Quick one-off tasks (screenshot, check if element exists, get page title)
    • Files: Complex tests, responsive design checks, anything user might want to re-run

    Available Helpers

    Optional utility functions in lib/helpers.js:

    const helpers = require('./lib/helpers');
    
    // Detect running dev servers (CRITICAL - use this first!)
    const servers = await helpers.detectDevServers();
    console.log('Found servers:', servers);
    
    // Safe click with retry
    await helpers.safeClick(page, 'button.submit', { retries: 3 });
    
    // Safe type with clear
    await helpers.safeType(page, '#username', 'testuser');
    
    // Take timestamped screenshot
    await helpers.takeScreenshot(page, 'test-result');
    
    // Handle cookie banners
    await helpers.handleCookieBanner(page);
    
    // Extract table data
    const data = await helpers.extractTableData(page, 'table.results');
    

    See lib/helpers.js for full list.

    Advanced Usage

    For comprehensive Playwright API documentation, see API_REFERENCE.md:

    • Selectors & Locators best practices
    • Network interception & API mocking
    • Authentication & session management
    • Visual regression testing
    • Mobile device emulation
    • Performance testing
    • Debugging techniques
    • CI/CD integration

    Tips

    • CRITICAL: Detect servers FIRST - Always run detectDevServers() before writing test code for localhost testing
    • Use /tmp for test files - Write to /tmp/playwright-test-*.js, never to skill directory or user's project
    • Parameterize URLs - Put detected/provided URL in a TARGET_URL constant at the top of every script
    • DEFAULT: Visible browser - Always use headless: false unless user explicitly asks for headless mode
    • Headless mode - Only use headless: true when user specifically requests "headless" or "background" execution
    • Slow down: Use slowMo: 100 to make actions visible and easier to follow
    • Wait strategies: Use waitForURL, waitForSelector, waitForLoadState instead of fixed timeouts
    • Error handling: Always use try-catch for robust automation
    • Console output: Use console.log() to track progress and show what's happening

    Troubleshooting

    Playwright not installed:

    cd $SKILL_DIR && npm run setup
    

    Module not found: Ensure running from skill directory via run.js wrapper

    Browser doesn't open: Check headless: false and ensure display available

    Element not found: Add wait: await page.waitForSelector('.element', { timeout: 10000 })

    Example Usage

    User: "Test if the marketing page looks good"
    
    Claude: I'll test the marketing page across multiple viewports. Let me first detect running servers...
    [Runs: detectDevServers()]
    [Output: Found server on port 3001]
    I found your dev server running on http://localhost:3001
    
    [Writes custom automation script to /tmp/playwright-test-marketing.js with URL parameterized]
    [Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-marketing.js]
    [Shows results with screenshots from /tmp/]
    
    User: "Check if login redirects correctly"
    
    Claude: I'll test the login flow. First, let me check for running servers...
    [Runs: detectDevServers()]
    [Output: Found servers on ports 3000 and 3001]
    I found 2 dev servers. Which one should I test?
    - http://localhost:3000
    - http://localhost:3001
    
    User: "Use 3001"
    
    [Writes login automation to /tmp/playwright-test-login.js]
    [Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-login.js]
    [Reports: ✅ Login successful, redirected to /dashboard]
    

    Notes

    • Each automation is custom-written for your specific request
    • Not limited to pre-built scripts - any browser task possible
    • Auto-detects running dev servers to eliminate hardcoded URLs
    • Test scripts written to /tmp for automatic cleanup (no clutter)
    • Code executes reliably with proper module resolution via run.js
    • Progressive disclosure - API_REFERENCE.md loaded only when advanced features needed
    Recommended Servers
    Apify
    Apify
    Browserbase
    Browserbase
    ScrapeGraph AI Integration Server
    ScrapeGraph AI Integration Server
    Repository
    leegonzales/aiskills
    Files