Skip to main content

Playwright MCP

Introduction​

The Playwright MCP server provides browser automation capabilities through the Model Context Protocol, enabling LLMs to interact with web pages using structured accessibility snapshots. It works with VS Code, Cursor, Windsurf, Claude Desktop, and any other MCP client — no vision models required.

Prerequisites​

Before you begin, make sure you have the following installed:

  • Node.js 20 or newer
  • An MCP client: VS Code, Cursor, Windsurf, Claude Code, Claude Desktop, or similar

Getting Started​

Installation​

Add the Playwright MCP server to your client using the standard configuration:

{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest"
]
}
}
}

VS Code​

Click one of the buttons below to install directly:

Install in VS Code Install in VS Code Insiders

Or install via the VS Code CLI:

code --add-mcp '{"name":"playwright","command":"npx","args":["@playwright/mcp@latest"]}'

Cursor​

Install in Cursor

Or go to Cursor Settings → MCP → Add new MCP Server and use command type with npx @playwright/mcp@latest.

Claude Code​

claude mcp add playwright npx @playwright/mcp@latest

Claude Desktop​

Follow the MCP install guide and use the standard config above.

Other clients​

The standard configuration works with most MCP clients, including Windsurf, Cline, Goose, Kiro, Codex, Copilot CLI, and others. Consult your client's MCP documentation for where to place the config.

First interaction​

Once the server is connected, ask your AI assistant to interact with a web page:

Navigate to https://demo.playwright.dev/todomvc and add a few todo items.

The assistant will use Playwright MCP tools to open the browser, navigate to the page, and interact with elements — all through structured accessibility snapshots rather than screenshots.

Core Features​

Accessibility snapshots​

Playwright MCP operates on the page's accessibility tree, not pixels. When a tool runs, it returns a structured snapshot showing the page elements, their roles, and text content. The LLM uses element references from these snapshots to interact with the page:

- heading "todos" [level=1]
- textbox "What needs to be done?" [ref=e5]
- listitem:
- checkbox "Toggle Todo" [ref=e10]
- text: "Buy groceries"

The LLM reads this snapshot and uses ref=e5 to type into the textbox or ref=e10 to check the checkbox.

Interacting with pages​

Playwright MCP provides tools for all common browser interactions:

  • Navigation: Open URLs, go back/forward, reload pages.
  • Clicking and typing: Click elements, type text, fill forms, select dropdowns.
  • Screenshots: Capture the current page or specific elements for visual verification.
  • Keyboard and mouse: Press keys, hover, drag and drop.
  • Dialogs: Accept or dismiss browser dialogs.
  • Tabs: Create, close, and switch between browser tabs.

Running Playwright code​

For complex interactions that go beyond individual tool calls, use the browser_run_code_unsafe tool to execute Playwright scripts directly. This tool runs arbitrary JavaScript in the Playwright server process and is RCE-equivalent — only enable it for trusted MCP clients:

Run this Playwright code to verify the todo count:
async (page) => {
const count = await page.getByTestId('todo-count').textContent();
return count;
}

Network monitoring and mocking​

Inspect network traffic and mock API responses:

  • View network requests: List all requests made since page load.
  • Mock routes: Set up URL pattern matching to return custom responses.
  • Console messages: Access browser console output for debugging.

Storage state​

Save and restore browser state including cookies and localStorage:

  • Save state: Persist authentication and session data to a file.
  • Restore state: Load previously saved state into a new session.
  • Cookie management: List, get, set, and delete individual cookies.

WebMCP tools​

Pages can register their own tools for agents through the experimental WebMCP API. The tools of the current tab are offered as MCP tools named webmcp_<tool>.

Tool names, descriptions, schemas and results are provided by the page, so treat them as untrusted input.

Configuration​

Headed mode​

By default, Playwright MCP runs the browser in headed mode so you can see what's happening. To run headless:

{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest",
"--headless"
]
}
}
}

Browser selection​

Choose which browser to use:

{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest",
"--browser=firefox"
]
}
}
}

Supported values: chrome, firefox, webkit, msedge.

User profile​

Playwright MCP supports three profile modes:

  • Persistent (default): Login state and cookies are preserved between sessions. The profile is stored in ms-playwright/mcp-{channel}-{workspace-hash} in your platform's cache directory, so different projects get separate profiles automatically. Override with --user-data-dir.
  • Isolated: Each session starts fresh. Pass --isolated to enable. You can load initial state with --storage-state.
  • Browser extension: Connect to your existing browser tabs with the Playwright Extension. Pass --extension to enable.

Idle timeout​

A page that keeps animating or rendering costs CPU for as long as the browser is open, and an agent session can last hours. A headless browser launched by the server is therefore closed after an hour without tool calls. Headed browsers, and browsers attached over --cdp-endpoint or --extension, are never closed automatically. Pass --idle-timeout to set the timeout in milliseconds for any mode, or 0 to disable it:

{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@playwright/mcp@latest",
"--idle-timeout=300000"
]
}
}
}

When no tool call has completed for that long, the browser is closed, headed or not, the same way as if you had closed it by hand. The next tool call launches a new browser, so the agent navigates again. The timer never fires while a tool call is running.

  • With --isolated, cookies and storage kept in memory are lost on an idle close. Use the persistent profile or --storage-state to keep them.
  • With --cdp-endpoint or --extension, the browser is not owned by the server, so there is no default timeout, and an explicit one only disconnects from it, leaving its pages open. With --extension, the next tool call goes through the connect flow again.
  • With --shared-browser-context, the timer spans all clients: a client that is idle while others keep working keeps its tabs and state, and the shared browser is closed only once every client has been idle for the timeout.

Configuration file​

For advanced configuration, use a JSON config file:

npx @playwright/mcp@latest --config path/to/config.json

The config file supports browser options, context options, network rules, timeouts, and more. See the Playwright MCP repository for the full schema.

Standalone server​

When running a headed browser on a system without a display or from IDE worker processes, start the MCP server separately with HTTP transport:

npx @playwright/mcp@latest --port 8931

HTTP sessions use a five-second heartbeat timeout. If your MCP client or proxy does not answer server-initiated pings, set PLAYWRIGHT_MCP_PING_TIMEOUT_MS to a longer timeout in milliseconds. Set it to 0 to disable the heartbeat.

Then point your MCP client to the HTTP endpoint:

{
"mcpServers": {
"playwright": {
"url": "http://localhost:8931/mcp"
}
}
}

Quick Reference​

ActionHow to do it
Install serverAdd standard config to your MCP client
Navigate to a pageAsk: "Go to https://example.com"
Click an elementAsk: "Click the Submit button"
Fill a formAsk: "Fill in the email field with [email protected]"
Take a screenshotAsk: "Take a screenshot of the page"
Run Playwright codeAsk: "Run this Playwright code: ..."
Mock an APIAsk: "Mock the /api/users endpoint to return ..."
Use headed modeDefault. Pass --headless to disable
Choose a browserPass --browser=firefox in args

What's Next​