Like Playwright MCP but via extension. 90% less context window. 10x more capable (full playwright API)
Install Extension from Chrome Web Store
-
Install the Chrome Extension
Install Extension - Install the Playwriter MCP Extension from the Chrome Web Store (or load it unpacked during development). Pin the extension to your Chrome toolbar for easy access.
-
Connect to a Tab
Click the Playwriter MCP extension icon on any tab you want to control. The icon will turn green when successfully connected.
Icon states:
- Gray: Not connected
- Green: Connected and ready
- Orange badge (...): Connecting
- Red badge (!): Error
-
Add MCP to Your Agent
Add the following configuration to your MCP client settings (e.g., Claude Desktop's
claude_desktop_config.json):{ "mcpServers": { "playwriter": { "command": "npx", "args": [ "playwriter@latest" ] } } }Restart your MCP client and you're ready to go! Your AI assistant can now control the browser through the extension.
Important: Before using the MCP, you must install and enable the extension on at least one tab:
- Pin the Playwriter extension to your Chrome toolbar (click the puzzle icon)
- Navigate to a tab you want to control
- Click the extension icon - it will turn green when connected
Once enabled on one or more tabs, your AI assistant can:
- Control all enabled tabs through the
executetool - Switch between tabs using playwright's context and page APIs
- Create new tabs programmatically
- Run any Playwright code against your browser tabs
The MCP will automatically start a relay server and connect to your enabled browser tabs.
You can use playwriter programmatically with playwright-core:
import { chromium } from 'playwright-core'
import { startPlayWriterCDPRelayServer, getCdpUrl } from 'playwriter'
const server = await startPlayWriterCDPRelayServer()
const browser = await chromium.connectOverCDP(getCdpUrl())
const context = browser.contexts()[0]
const page = context.pages()[0]
await page.goto('https://example.com')
await page.screenshot({ path: 'screenshot.png' })
await browser.close()
server.close()Playwriter includes Vimium-style visual labels that overlay interactive elements, making it easy for AI agents to identify and click elements from screenshots. These functions are available in the MCP context.
// Show labels on all visible interactive elements
const { snapshot, labelCount } = await showAriaRefLabels({ page })
console.log(`Showing ${labelCount} labels`)
// Take a screenshot with labels visible
await page.screenshot({ path: '/tmp/labeled-page.png' })
// Use the snapshot to find elements, then interact using aria-ref selector
await page.locator('aria-ref=e5').click()
// Labels auto-hide after 30 seconds, or remove manually:
await hideAriaRefLabels({ page })Important: Labels auto-hide after 30 seconds to prevent stale labels. If the page HTML changes (navigation, dynamic content), call showAriaRefLabels() again to get fresh labels matching the current DOM.
Features:
- Role filtering - Only shows labels for interactive elements (buttons, links, inputs, etc.)
- Visibility detection - Skips elements covered by modals or overlays
- Overlap prevention - Skips labels that would overlap with already-placed ones
- Color-coded by type - Warm color scheme helps distinguish element types
- Auto-hide - Labels disappear after 30 seconds to prevent stale overlays
Color legend:
| Color | Element Types |
|---|---|
| Yellow | Links |
| Orange | Buttons |
| Coral | Text inputs (textbox, combobox, searchbox) |
| Pink | Checkboxes, radios, switches |
| Peach | Sliders |
| Salmon | Menu items |
| Amber | Tabs, options |
When set, the MCP will automatically create an initial tab when a Playwright client connects and no tabs are currently enabled. This is useful for fully automated workflows where you don't want to manually click the extension icon.
{
"mcpServers": {
"playwriter": {
"command": "npx",
"args": ["playwriter@latest"],
"env": {
"PLAYWRITER_AUTO_ENABLE": "1"
}
}
}
}With this setting, when your AI agent starts, it will immediately have a page to work with without requiring manual extension activation.
Note: The auto-created tab starts at about:blank. Your agent can then navigate it to any URL.
Playwriter uses a Chrome extension instead of launching a full new Chrome window. This approach has several benefits:
- Collaborate with your agent - Work alongside the AI in the same browser, helping it when stuck on captchas or complex interactions
- Start on existing pages - Launch the MCP on a page in your existing browser to replicate bugs exactly as they occur
- Reuse your extensions - Keep using ad blockers, password managers, and other extensions you already have installed
- Bypass automation detection - Disable CDP/automation temporarily by disconnecting the extension to bypass detection systems like Google login, then reconnect to continue automation. With Playwright's headless Chrome, automation is always detected and blocks your workflow
- Less resource usage - No need to spawn a separate Chrome instance, saving memory and CPU
- Single browser workflow - Everything happens in your main Chrome browser, no switching between windows
Playwriter has access to the full playwright API available, it can send any CDP command via the playwright methods. It only uses 1 tool execute to send playwright code snippets. This means that the LLM can reuse its knowledge about playwright and less context window is used to expose browser automations tools.
Playwriter is also more capable because it exposes the full playwright API instead of only a few tools.
For comparison here are the tools supported by BrowserMCP:
Navigation:
browsermcp_browser_navigate- Navigate to a URLbrowsermcp_browser_go_back- Go back to the previous pagebrowsermcp_browser_go_forward- Go forward to the next page Page Inspection:browsermcp_browser_snapshot- Capture accessibility snapshot of the current page (use this to get references to elements)browsermcp_browser_screenshot- Take a screenshot of the current pagebrowsermcp_browser_get_console_logs- Get console logs from the browser Interactions:browsermcp_browser_click- Click on an element (requires element reference from snapshot)browsermcp_browser_hover- Hover over an elementbrowsermcp_browser_type- Type text into an editable element (with optional submit)browsermcp_browser_select_option- Select an option in a dropdownbrowsermcp_browser_press_key- Press a key on the keyboard Utilities:browsermcp_browser_wait- Wait for a specified time in seconds
Antigravity's browser integration suffers from the same fundamental problem as BrowserMCP: it creates a separate tool for every browser action instead of using the Playwright API that LLMs already understand.
The Context Window Problem:
Jetski exposes 17+ browser tools (capture_browser_screenshot, browser_click_element, browser_input, browser_scroll, wait_5_seconds, etc.). Each tool definition consumes context window space with parameter schemas, descriptions, and examples. This bloated schema forces Antigravity to spawn a subagent every time you want to use the browser, adding significant latency and indirection to every browser interaction.
Playwriter's Approach:
- 1 tool instead of 17+ - Only the
executetool is needed - No subagent spawning - Browser operations happen directly without extra layers
- Lower latency - No need to spawn/teardown agents for each browser task
- Leverages existing knowledge - LLMs already know Playwright's API from their training data
- More capable - Full Playwright API access vs a limited set of predefined actions
The irony is that by trying to make browser control "simpler" with dedicated tools, these integrations make it slower, less capable, and waste context window that could be used for actual work.
Claude Code has a built-in Chrome extension ("Claude in Chrome") that uses Native Messaging API with a hybrid approach: screenshots for visual understanding and DOM/JavaScript for interactions.
Works Everywhere Claude's Extension Doesn't:
- Windows WSL support - Claude's extension doesn't work in WSL because Native Messaging requires Windows-native Chrome. Playwriter uses WebSocket on localhost:19988, so agents running in WSL can control Chrome on your Windows host
- Any MCP-compatible agent - Not locked to Claude. Works with GPT, Gemini, local models, or any CLI tool that supports MCP
- Devcontainers & VMs - Run your agent in an isolated environment while controlling Chrome on your host machine
Context Efficiency:
Claude's extension sends screenshots to the LLM for visual understanding, then uses DOM inspection for interactions. Playwriter uses accessibility snapshots instead - structured text describing interactive elements with their roles, names, and states:
| Approach | What's sent to LLM | Typical size |
|---|---|---|
| Claude's extension | Screenshots | 100KB-1MB+ per image |
| Playwriter | Accessibility snapshots | 5-20KB text |
Full Playwright API vs Step-by-Step Navigation:
Claude's extension navigates pages step-by-step with screenshots. Playwriter exposes the complete Playwright API through a single execute tool - LLMs already know Playwright from training data:
// Complex interactions in one call
await page.locator('tr').filter({ hasText: 'John' }).locator('button').click();
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('button.export')
]);
await download.saveAs('/tmp/report.pdf');Advanced DevTools Features:
Playwriter provides capabilities Claude's extension doesn't have:
// Set breakpoints and inspect variables at runtime
const dbg = createDebugger({ cdp });
await dbg.setBreakpoint({ file: 'app.js', line: 42 });
// when paused: await dbg.inspectLocalVariables()
// Live-edit page scripts without reload
const editor = createEditor({ cdp });
await editor.edit({ url: 'app.js', oldString: 'DEBUG=false', newString: 'DEBUG=true' });
// Inspect CSS like DevTools Styles panel
const styles = await getStylesForLocator({ locator: page.locator('.btn'), cdp });
// Intercept network requests for API reverse-engineering
page.on('response', async res => {
if (res.url().includes('/api/')) state.responses.push(await res.json());
});
// Find React component source locations
const source = await getReactSource({ locator: page.locator('aria-ref=e5') });
// => { fileName: 'Button.tsx', lineNumber: 42 }User Collaboration Features:
- Right-click → "Copy Playwriter Element Reference" - Pin any element and reference it as
globalThis.playwriterPinnedElem1in your automation code - Vimium-style visual labels -
showAriaRefLabels()overlays clickable labels on all interactive elements - Tab group organization - Connected tabs are grouped together with a green "playwriter" label
- Bypass automation detection - Disconnect the extension temporarily to pass bot detection (e.g., Google login), then reconnect
Summary:
| Feature | Claude's Extension | Playwriter |
|---|---|---|
| Windows WSL | No | Yes |
| Works with any agent | No (Claude only) | Yes (any MCP client) |
| Context method | Screenshots | A11y snapshots (90% smaller) |
| Full Playwright API | No | Yes |
| Debugger (breakpoints) | No | Yes |
| Live code editing | No | Yes |
| CSS inspection | No | Yes |
| Network interception | Limited | Full |
| React source finding | No | Yes |
| Right-click pin element | No | Yes |
| Raw CDP access | No | Yes |
+---------------------+ +-------------------+ +-----------------+
| BROWSER | | LOCALHOST | | MCP CLIENT |
| | | | | |
| +---------------+ | | WebSocket Server | | +-----------+ |
| | Extension |<---------> :19988 | | | AI Agent | |
| | (bg script) | | WS | | | | (Claude) | |
| +-------+-------+ | | /extension | | +-----------+ |
| | | | ^ | | | |
| | chrome | | | | | v |
| | .debug | | v | | +-----------+ |
| v | | /cdp/:id <--------------> | execute | |
| +---------------+ | | | WS | | tool | |
| | Tab 1 (green) | | | Routes: | | +-----------+ |
| +---------------+ | | - CDP commands | | | |
| +---------------+ | | - CDP events | | v |
| | Tab 2 (green) | | | - attach/detach | | +-----------+ |
| +---------------+ | | Target events | | | Playwright| |
| +---------------+ | +-------------------+ | | API | |
| | Tab 3 (gray) | | | +-----------+ |
| +---------------+ | Tab 3 not controlled +-----------------+
| | (user didn't click icon)
+---------------------+
Run agents in isolated environments (devcontainers, VMs, SSH) while controlling Chrome on your host.
On host (where Chrome runs):
npx playwriter serve --token <secret>
# or use environment variable:
PLAYWRITER_TOKEN=<secret> npx playwriter serveIn container/VM (where agent runs):
Configure your MCP client with the host and token. You can pass them as CLI arguments:
{
"mcpServers": {
"playwriter": {
"command": "npx",
"args": [
"playwriter@latest",
"--host", "host.docker.internal",
"--token", "<secret>"
]
}
}
}Or use environment variables (useful if you want to set them globally in your process or MCP client):
{
"mcpServers": {
"playwriter": {
"command": "npx",
"args": ["playwriter@latest"],
"env": {
"PLAYWRITER_HOST": "host.docker.internal",
"PLAYWRITER_TOKEN": "<secret>"
}
}
}
}Use host.docker.internal for devcontainers, or your host's IP for VMs/SSH.
- If all pages urls return
about:blankin every MCP session restart your Chrome browser. This seems to be a Chrome bug that sometimes happen. It is some hidden state inchrome.debuggerExtensions API. Restarting the extension worker does not fix it. - When connecting the MCP to a page, the browser may switch to light mode. This happens because Playwright, via CDP, automatically sends an "emulate media" command on start. If you'd like to see this behavior changed, you can upvote the related issue here.
Playwriter is designed with security in mind, ensuring that only you can control your browser.
- Local WebSocket Server: When the MCP starts, it launches a singleton WebSocket server on
localhost:19988 - Dual Connection: Both the Chrome extension and MCP client connect to this local server
- User-Controlled Access: The extension can only control tabs where you explicitly clicked the extension icon (green icon indicates connected tabs)
- Localhost-Only: The WebSocket server does not send CORS headers, preventing any web pages or remote servers from connecting to it - only processes running on your local machine can establish a connection
- Explicit Consent: Chrome displays an "automation banner" on controlled tabs, making it obvious when a tab is being automated
- Only enabled tabs: Tabs you explicitly connected by clicking the extension icon
- New tabs created by automation: Tabs created programmatically through Playwright commands
- Nothing else: Other browser tabs, your browsing history, or any tabs you haven't explicitly connected remain inaccessible
- No remote access: External websites or servers cannot connect to the WebSocket (localhost-only)
- No passive monitoring: The extension cannot read or monitor tabs you haven't connected
- No automatic spreading: The debugger won't automatically attach to new tabs you open manually
This architecture ensures that browser automation only happens with your explicit permission on tabs you choose.