even-better-playwright-mcp

even-better-playwright-mcp

An advanced Playwright MCP server that enables efficient browser automation through compressed accessibility snapshots, sandboxed code execution, and visual element labeling. It features 90% DOM compression and integrated DevTools for deep web inspection and interaction.

Category
Visit Server

README

even-better-playwright-mcp

The best of all worlds Playwright MCP server - combining intelligent DOM compression, code execution, visual labels, and advanced DevTools capabilities.

Features

  • šŸŽ­ Full Playwright API - Execute any Playwright code via the execute tool
  • šŸ—ļø 90%+ DOM Compression - SimHash-based list folding and wrapper removal
  • šŸ“ Ref-Based Elements - Stable [ref=e1] identifiers with aria-ref selectors
  • šŸ” Regex Search - Find content in snapshots without re-fetching
  • šŸŽÆ Visual Labels - Vimium-style overlays for screenshot-based interaction
  • šŸ”§ Advanced DevTools - Debugger, live editor, styles inspection, React source finding
  • šŸ”’ Sandboxed Execution - Safe VM with scoped file system and module allowlist

Installation

npm install -g even-better-playwright-mcp

Or use directly with npx:

npx even-better-playwright-mcp

Configuration

Add to your MCP client settings (e.g., Claude Desktop's claude_desktop_config.json):

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["even-better-playwright-mcp"]
    }
  }
}

CLI Options

Usage: even-better-playwright-mcp [options]

Options:
  --browser <browser>       Browser to use: chromium, firefox, webkit (default: chromium)
  --headless               Run browser in headless mode (default: false)
  --cdp-endpoint <url>     Connect to existing browser via CDP endpoint
  --user-data-dir <path>   Use persistent browser profile directory
  -h, --help               Show help message

Examples

# Basic usage (launches Chromium in headed mode)
even-better-playwright-mcp

# Use Firefox in headless mode
even-better-playwright-mcp --browser firefox --headless

# Connect to existing Chrome instance
even-better-playwright-mcp --cdp-endpoint ws://localhost:9222

# Use persistent profile
even-better-playwright-mcp --user-data-dir ./browser-profile

Tools

1. snapshot - Get Page Structure

Get compressed accessibility snapshot with ref IDs for element targeting.

Returns: DOM tree with [ref=e1], [ref=e2] etc.
Use refs with execute tool: await $('e1').click()
Call again after navigation (refs become stale).

Options:

  • compress (boolean, default: true) - Enable smart compression (~90% token reduction)

Example output:

### Page Info
- URL: https://example.com
- Title: Example Domain

### Accessibility Snapshot
- document [ref=e1]
  - heading "Example Domain" [level=1] [ref=e2]
  - paragraph [ref=e3]: This domain is for use in illustrative examples...
  - link "More information..." [ref=e4]

2. browser_execute - Run Playwright Code

Execute any Playwright code with full API access. This is the main tool for browser automation.

Scope variables:

  • page - Current Playwright page
  • context - Browser context
  • state - Persistent object across calls
  • $('e5') - Shorthand for page.locator('aria-ref=e5')
  • accessibilitySnapshot() - Get current page snapshot

Common patterns:

// Navigate
await page.goto('https://example.com')

// Click by ref (from snapshot)
await $('e5').click()

// Fill input
await $('e12').fill('search query')

// Get text
const text = await $('e3').textContent()

// Wait for network
await page.waitForLoadState('networkidle')

// Screenshot
await page.screenshot({ path: 'screenshot.png' })

Advanced - DevTools access:

// Get CDP session for debugging
const cdp = await getCDPSession({ page })
const dbg = createDebugger({ cdp })

// Set breakpoint
await dbg.setBreakpoint({ file: 'app.js', line: 42 })

// Inspect styles
const styles = await getStylesForLocator({ locator: $('e5') })

// Find React component source
const source = await getReactSource({ locator: $('e5') })
// => { fileName: 'Button.tsx', lineNumber: 42 }

Safe modules via require(): path, url, crypto, buffer, util, assert, os, fs (sandboxed)

3. screenshot - Capture Page Image

Capture screenshots with optional visual ref labels.

Options:

  • ref (string) - Screenshot specific element by ref
  • fullPage (boolean) - Capture entire scrollable area
  • withLabels (boolean) - Show Vimium-style ref labels

Label colors by role:

Color Role
Yellow links
Orange buttons
Coral text inputs
Pink checkboxes, radios
Blue images, videos

4. browser_search_snapshot - Search Content

Search the last captured snapshot using regex patterns.

Options:

  • pattern (string) - Regex pattern to search for
  • ignoreCase (boolean, default: false) - Case-insensitive matching
  • lineLimit (number, default: 100) - Maximum lines to return

Example:

Pattern: "button|link"
Result: 
- link "Contact Us" [ref=e15]
- button "Submit" [ref=e23]
- link "Privacy Policy" [ref=e31]

Workflow

Basic Automation

  1. Get page structure

    Use: snapshot tool
    → See all interactive elements with refs
    
  2. Interact with elements

    Use: execute tool
    Code: await $('e5').click()
    
  3. After navigation, refresh refs

    Use: snapshot tool again
    → Refs are stale after navigation
    

Visual Automation

  1. Take labeled screenshot

    Use: screenshot tool with withLabels: true
    → See visual labels overlaid on elements
    
  2. Identify element from image

    Label shows: "e5" on a button
    
  3. Click using ref

    Use: execute tool
    Code: await $('e5').click()
    

Architecture

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                     even-better-playwright-mcp                  │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  CORE                                                           │
│  ā”œā”€ā”€ aria-ref selector system ([ref=e1], [ref=e2], etc.)       │
│  ā”œā”€ā”€ page._snapshotForAI() for accessibility snapshots         │
│  └── Standard Playwright browser automation                     │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  ENHANCED SNAPSHOT                                              │
│  ā”œā”€ā”€ SimHash-based list folding (compress 48 items → 2 lines)  │
│  ā”œā”€ā”€ Useless wrapper removal                                    │
│  └── Regex-powered content search                               │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  CODE EXECUTION                                                 │
│  ā”œā”€ā”€ browser_execute tool (run Playwright code in VM sandbox)  │
│  ā”œā”€ā”€ Sandboxed require (safe module allowlist)                  │
│  ā”œā”€ā”€ Scoped file system (cwd, /tmp only)                       │
│  └── Console log capture and forwarding                         │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  ADVANCED DEVTOOLS                                              │
│  ā”œā”€ā”€ Debugger class (breakpoints, step, inspect variables)     │
│  ā”œā”€ā”€ Editor class (live code editing without reload)           │
│  ā”œā”€ā”€ Styles inspection (CSS like DevTools panel)               │
│  └── React source finding (component file/line locations)      │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│  VISUAL OVERLAYS                                                │
│  ā”œā”€ā”€ Vimium-style labels on interactive elements               │
│  ā”œā”€ā”€ Color-coded by role (links=yellow, buttons=orange, etc.)  │
│  └── Screenshot with visible ref labels                         │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Ref System

All projects use the same ref system built into Playwright:

  • Snapshots generate refs like [ref=e1]
  • Selectors use page.locator('aria-ref=e1')
  • Shorthand $('e1') in execute tool

Important: Refs become stale after navigation. Always call snapshot again after page.goto() or clicking links that navigate.

Compression Algorithm

The snapshot compression achieves ~90% token reduction:

Original DOM (5000+ lines)
    ↓ removeUselessWrappers()
    ↓ truncateText(50 chars)
    ↓ detectSimilarPatterns(SimHash)
    ↓ foldLists()
Compressed (<500 lines)

Example:

Before:
- listitem [ref=e234]: Product 1 - Description...
- listitem [ref=e235]: Product 2 - Description...
- listitem [ref=e236]: Product 3 - Description...
... (48 items)

After:
- listitem [ref=e234]: Product 1 - Description...
- listitem (... and 47 more similar) [refs: e235, e236, ...]

Error Handling

The execute tool provides contextual hints:

  • Stale ref: "Page may have navigated. Refs are stale after navigation. Call snapshot tool to get fresh refs."
  • Timeout: "Operation timed out. Try increasing timeout or check if element exists/is visible."
  • Hidden element: "Element may be hidden or covered by another element. Try scrolling or closing overlays."
  • Connection lost: "Browser connection lost. The browser may have been closed - try again to relaunch."

Development

Building from Source

git clone https://github.com/your-repo/even-better-playwright-mcp
cd even-better-playwright-mcp
npm install
npm run build

Project Structure

even-better-playwright-mcp/
ā”œā”€ā”€ bin/
│   └── cli.ts              # CLI entry point with arg parsing
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ index.ts            # MCP server setup
│   ā”œā”€ā”€ browser.ts          # Browser/context management
│   ā”œā”€ā”€ vm-context.ts       # VM sandbox setup
│   ā”œā”€ā”€ tools/
│   │   ā”œā”€ā”€ snapshot.ts     # Snapshot tool (compressed)
│   │   ā”œā”€ā”€ execute.ts      # Execute tool (main)
│   │   ā”œā”€ā”€ screenshot.ts   # Screenshot tool (with labels)
│   │   └── search.ts       # Search tool
│   ā”œā”€ā”€ utils/
│   │   ā”œā”€ā”€ smart-outline.ts    # DOM compression
│   │   ā”œā”€ā”€ list-detector.ts    # Pattern detection
│   │   ā”œā”€ā”€ dom-simhash.ts      # SimHash implementation
│   │   ā”œā”€ā”€ scoped-fs.ts        # Sandboxed file system
│   │   └── search.ts           # Regex search
│   ā”œā”€ā”€ devtools/
│   │   ā”œā”€ā”€ cdp-session.ts      # CDP connection
│   │   ā”œā”€ā”€ debugger.ts         # Debugger class
│   │   ā”œā”€ā”€ editor.ts           # Live editor
│   │   ā”œā”€ā”€ styles.ts           # CSS inspection
│   │   └── react-source.ts     # React locations
│   └── visual/
│       └── aria-labels.ts      # Vimium-style overlays
ā”œā”€ā”€ package.json
ā”œā”€ā”€ tsconfig.json
└── README.md

Acknowledgments

This project combines the best ideas from:

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured