diff --git a/README.md b/README.md
index 77ea238..0e50797 100644
--- a/README.md
+++ b/README.md
@@ -1,313 +1,474 @@
-# playwright-cli
+## Playwright MCP
-Playwright CLI with SKILLS
+A Model Context Protocol (MCP) server that provides browser automation capabilities using [Playwright](https://playwright.dev). This server enables LLMs to interact with web pages through structured accessibility snapshots, bypassing the need for screenshots or visually-tuned models.
-### Playwright CLI vs Playwright MCP
+### Playwright MCP vs Playwright CLI
-This package provides CLI interface into Playwright. If you are using **coding agents**, that is the best fit.
+This package provides MCP interface into Playwright. If you are using a **coding agent**, you might benefit from using the [CLI+SKILLS](https://github.com/microsoft/playwright-cli) instead.
-- **CLI**: Modern **coding agents** increasingly favor CLI–based workflows exposed as SKILLs over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context, allowing agents to act through concise, purpose-built commands. This makes CLI + SKILLs better suited for high-throughput coding agents that must balance browser automation with large codebases, tests, and reasoning within limited context windows.
+- **CLI**: Modern **coding agents** increasingly favor CLI–based workflows exposed as SKILLs over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context, allowing agents to act through concise, purpose-built commands. This makes CLI + SKILLs better suited for high-throughput coding agents that must balance browser automation with large codebases, tests, and reasoning within limited context windows.
**Learn more about [Playwright CLI with SKILLS](https://github.com/microsoft/playwright-cli)**.
-- **MCP**: MCP remains relevant for specialized agentic loops that benefit from persistent state, rich introspection, and iterative reasoning over page structure, such as exploratory automation, self-healing tests, or long-running autonomous workflows where maintaining continuous browser context outweighs token cost concerns. Learn more about [Playwright MCP](https://github.com/microsoft/playwright-mcp).
+- **MCP**: MCP remains relevant for specialized agentic loops that benefit from persistent state, rich introspection, and iterative reasoning over page structure, such as exploratory automation, self-healing tests, or long-running autonomous workflows where maintaining continuous browser context outweighs token cost concerns.
### Key Features
-- **Token-efficient**. Does not force page data into LLM.
+- **Fast and lightweight**. Uses Playwright's accessibility tree, not pixel-based input.
+- **LLM-friendly**. No vision models needed, operates purely on structured data.
+- **Deterministic tool application**. Avoids ambiguity common with screenshot-based approaches.
### Requirements
- Node.js 18 or newer
-- Claude Code, GitHub Copilot, or any other coding agent.
+- VS Code, Cursor, Windsurf, Claude Desktop, Goose or any other MCP client
-## Getting Started
+
-## Installation
+### Getting started
+
+First, install the Playwright MCP server with your client.
+
+**Standard config** works in most of the tools:
+
+```js
+{
+ "mcpServers": {
+ "playwright": {
+ "command": "npx",
+ "args": [
+ "@playwright/mcp@latest"
+ ]
+ }
+ }
+}
+```
+
+[
](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [
](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D)
+
+
+Amp
+
+Add via the Amp VS Code extension settings screen or by updating your settings.json file:
+
+```json
+"amp.mcpServers": {
+ "playwright": {
+ "command": "npx",
+ "args": [
+ "@playwright/mcp@latest"
+ ]
+ }
+}
+```
+
+**Amp CLI Setup:**
+
+Add via the `amp mcp add`command below
```bash
-npm install -g @playwright/cli@latest
-playwright-cli --help
+amp mcp add playwright -- npx @playwright/mcp@latest
```
-### Installing skills
+
-Claude Code, GitHub # playwright-cli
+
+Claude Code
-Playwright CLI with SKILLS
-
-### Playwright CLI vs Playwright MCP
-
-This package provides CLI interface into Playwright. If you are using **coding agents**, that is the best fit.
-
-- **CLI**: Modern **coding agents** increasingly favor CLI–based workflows exposed as SKILLs over MCP because CLI invocations are more token-efficient: they avoid loading large tool schemas and verbose accessibility trees into the model context, allowing agents to act through concise, purpose-built commands. This makes CLI + SKILLs better suited for high-throughput coding agents that must balance browser automation with large codebases, tests, and reasoning within limited context windows.
-
-- **MCP**: MCP remains relevant for specialized agentic loops that benefit from persistent state, rich introspection, and iterative reasoning over page structure, such as exploratory automation, self-healing tests, or long-running autonomous workflows where maintaining continuous browser context outweighs token cost concerns. Learn more about [Playwright MCP](https://github.com/microsoft/playwright-mcp).
-
-### Key Features
-
-- **Token-efficient**. Does not force page data into LLM.
-
-### Requirements
-- Node.js 18 or newer
-- Claude Code, GitHub Copilot, or any other coding agent.
-
-## Getting Started
-
-## Installation
+Use the Claude Code CLI to add the Playwright MCP server:
```bash
-npm install -g @playwright/cli@latest
-playwright-cli --help
+claude mcp add playwright npx @playwright/mcp@latest
+```
+
+
+
+Claude Desktop
+
+Follow the MCP install [guide](https://modelcontextprotocol.io/quickstart/user), use the standard config above.
+
+
+
+
+Cline
+
+Follow the instruction in the section [Configuring MCP Servers](https://docs.cline.bot/mcp/configuring-mcp-servers)
+
+**Example: Local Setup**
+
+Add the following to your [`cline_mcp_settings.json`](https://docs.cline.bot/mcp/configuring-mcp-servers#editing-mcp-settings-files) file:
+
+```json
+{
+ "mcpServers": {
+ "playwright": {
+ "type": "stdio",
+ "command": "npx",
+ "timeout": 30,
+ "args": [
+ "-y",
+ "@playwright/mcp@latest"
+ ],
+ "disabled": false
+ }
+ }
+}
```
-### Installing skills
+
-Claude Code, GitHub Copilot and others will use the locally installed skills.
+
+Codex
+
+Use the Codex CLI to add the Playwright MCP server:
```bash
-playwright-cli install-skills
+codex mcp add playwright npx "@playwright/mcp@latest"
```
-### Skills-less operation
+Alternatively, create or edit the configuration file `~/.codex/config.toml` and add:
-Point your agent at the CLI and let it cook. It'll read the skill off `playwright-cli --help` on its own:
-
-```
-Test the "add todo" flow on https://demo.playwright.dev/todomvc using playwright-cli.
-Check playwright-cli --help for available commands.
+```toml
+[mcp_servers.playwright]
+command = "npx"
+args = ["@playwright/mcp@latest"]
```
-## Demo
+For more information, see the [Codex MCP documentation](https://github.com/openai/codex/blob/main/codex-rs/config.md#mcp_servers).
-```
-> Use playwright skills to test https://demo.playwright.dev/todomvc/.
- Take screenshots for all successful and failing scenarios.
-```
+
-Your agent will be running commands, but it does not mean you can't play with it manually:
+
+Copilot
-```
-playwright-cli open https://demo.playwright.dev/todomvc/ --headed
-playwright-cli type "Buy groceries"
-playwright-cli press Enter
-playwright-cli type "Water flowers"
-playwright-cli press Enter
-playwright-cli check e21
-playwright-cli check e35
-playwright-cli screenshot
-```
-
-## Headed operation
-
-Playwright CLI is headless by default. If you'd like to see the browser, pass `--headed` to `open`:
+Use the Copilot CLI to interactively add the Playwright MCP server:
```bash
-playwright-cli open https://playwright.dev --headed
+/mcp add
```
-## Sessions
+Alternatively, create or edit the configuration file `~/.copilot/mcp-config.json` and add:
-Playwright CLI will use a dedicated persistent profile by default. It means that
-your cookies and other storage state will be preserved between the calls. You can use different
-instances of the browser for different projects with sessions.
+```json
+{
+ "mcpServers": {
+ "playwright": {
+ "type": "local",
+ "command": "npx",
+ "tools": [
+ "*"
+ ],
+ "args": [
+ "@playwright/mcp@latest"
+ ]
+ }
+ }
+}
+```
-Following will result in two browsers with separate profiles being available. Pass `--session` to
-the invocation to talk to a specific browser.
+For more information, see the [Copilot CLI documentation](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli).
+
+
+
+
+Cursor
+
+#### Click the button to install:
+
+[
](https://cursor.com/en/install-mcp?name=Playwright&config=eyJjb21tYW5kIjoibnB4IEBwbGF5d3JpZ2h0L21jcEBsYXRlc3QifQ%3D%3D)
+
+#### Or install manually:
+
+Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server`. Name to your liking, use `command` type with the command `npx @playwright/mcp@latest`. You can also verify config or add command like arguments via clicking `Edit`.
+
+
+
+
+Factory
+
+Use the Factory CLI to add the Playwright MCP server:
```bash
-playwright-cli open https://playwright.dev
-playwright-cli --session=example open https://example.com
-playwright-cli session-list
+droid mcp add playwright "npx @playwright/mcp@latest"
```
-You can run your coding agent with the `PLAYWRIGHT_CLI_SESSION` environment variable:
+Alternatively, type `/mcp` within Factory droid to open an interactive UI for managing MCP servers.
+
+For more information, see the [Factory MCP documentation](https://docs.factory.ai/cli/configuration/mcp).
+
+
+
+
+Gemini CLI
+
+Follow the MCP install [guide](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md#configure-the-mcp-server-in-settingsjson), use the standard config above.
+
+
+
+
+Goose
+
+#### Click the button to install:
+
+[](https://block.github.io/goose/extension?cmd=npx&arg=%40playwright%2Fmcp%40latest&id=playwright&name=Playwright&description=Interact%20with%20web%20pages%20through%20structured%20accessibility%20snapshots%20using%20Playwright)
+
+#### Or install manually:
+
+Go to `Advanced settings` -> `Extensions` -> `Add custom extension`. Name to your liking, use type `STDIO`, and set the `command` to `npx @playwright/mcp`. Click "Add Extension".
+
+
+
+Kiro
+
+Follow the MCP Servers [documentation](https://kiro.dev/docs/mcp/). For example in `.kiro/settings/mcp.json`:
+
+```json
+{
+ "mcpServers": {
+ "playwright": {
+ "command": "npx",
+ "args": [
+ "@playwright/mcp@latest"
+ ]
+ }
+ }
+}
+```
+
+
+
+LM Studio
+
+#### Click the button to install:
+
+[](https://lmstudio.ai/install-mcp?name=playwright&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyJAcGxheXdyaWdodC9tY3BAbGF0ZXN0Il19)
+
+#### Or install manually:
+
+Go to `Program` in the right sidebar -> `Install` -> `Edit mcp.json`. Use the standard config above.
+
+
+
+opencode
+
+Follow the MCP Servers [documentation](https://opencode.ai/docs/mcp-servers/). For example in `~/.config/opencode/opencode.json`:
+
+```json
+{
+ "$schema": "https://opencode.ai/config.json",
+ "mcp": {
+ "playwright": {
+ "type": "local",
+ "command": [
+ "npx",
+ "@playwright/mcp@latest"
+ ],
+ "enabled": true
+ }
+ }
+}
+
+```
+
+
+
+Qodo Gen
+
+Open [Qodo Gen](https://docs.qodo.ai/qodo-documentation/qodo-gen) chat panel in VSCode or IntelliJ → Connect more tools → + Add new MCP → Paste the standard config above.
+
+Click Save.
+
+
+
+VS Code
+
+#### Click the button to install:
+
+[
](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [
](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D)
+
+#### Or install manually:
+
+Follow the MCP install [guide](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server), use the standard config above. You can also install the Playwright MCP server using the VS Code CLI:
```bash
-PLAYWRIGHT_CLI_SESSION=todo-app claude .
+# For VS Code
+code --add-mcp '{"name":"playwright","command":"npx","args":["@playwright/mcp@latest"]}'
```
-Or instruct it to prepend `--session` to the calls.
+After installation, the Playwright MCP server will be available for use with your GitHub Copilot agent in VS Code.
+
-Manage your sessions as follows:
+
+Warp
-```bash
-playwright-cli session-list # list all sessions
-playwright-cli session-stop [name] # stop session
-playwright-cli session-restart [name] # restart session
-playwright-cli session-stop-all # stop all sessions
-playwright-cli session-delete [name] # delete session data along with the profiles
+Go to `Settings` -> `AI` -> `Manage MCP Servers` -> `+ Add` to [add an MCP Server](https://docs.warp.dev/knowledge-and-collaboration/mcp#adding-an-mcp-server). Use the standard config above.
+
+Alternatively, use the slash command `/add-mcp` in the Warp prompt and paste the standard config from above:
+```js
+{
+ "mcpServers": {
+ "playwright": {
+ "command": "npx",
+ "args": [
+ "@playwright/mcp@latest"
+ ]
+ }
+ }
+}
```
-
+
-## Commands
+
+Windsurf
-### Core
+Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/mcp). Use the standard config above.
-```bash
-playwright-cli open https://example.com/
-playwright-cli close
-playwright-cli type "search query"
-playwright-cli click e3
-playwright-cli dblclick e7
-playwright-cli fill e5 "user@example.com"
-playwright-cli drag e2 e8
-playwright-cli hover e4
-playwright-cli select e9 "option-value"
-playwright-cli upload ./document.pdf
-playwright-cli check e12
-playwright-cli uncheck e12
-playwright-cli snapshot
-playwright-cli snapshot --filename=after-click.yaml
-playwright-cli eval "document.title"
-playwright-cli eval "el => el.textContent" e5
-playwright-cli dialog-accept
-playwright-cli dialog-accept "confirmation text"
-playwright-cli dialog-dismiss
-playwright-cli resize 1920 1080
-```
-
-### Navigation
-
-```bash
-playwright-cli go-back
-playwright-cli go-forward
-playwright-cli reload
-```
-
-### Keyboard
-
-```bash
-playwright-cli press Enter
-playwright-cli press ArrowDown
-playwright-cli keydown Shift
-playwright-cli keyup Shift
-```
-
-### Mouse
-
-```bash
-playwright-cli mousemove 150 300
-playwright-cli mousedown
-playwright-cli mousedown right
-playwright-cli mouseup
-playwright-cli mouseup right
-playwright-cli mousewheel 0 100
-```
-
-### Save as
-
-```bash
-playwright-cli screenshot
-playwright-cli screenshot e5
-playwright-cli screenshot --filename=page.png
-playwright-cli pdf --filename=page.pdf
-```
-
-### Tabs
-
-```bash
-playwright-cli tab-list
-playwright-cli tab-new
-playwright-cli tab-new https://example.com/page
-playwright-cli tab-close
-playwright-cli tab-close 2
-playwright-cli tab-select 0
-```
-
-### Storage
-
-```bash
-playwright-cli state-save
-playwright-cli state-save auth.json
-playwright-cli state-load auth.json
-
-# Cookies
-playwright-cli cookie-list
-playwright-cli cookie-list --domain=example.com
-playwright-cli cookie-get session_id
-playwright-cli cookie-set session_id abc123
-playwright-cli cookie-set session_id abc123 --domain=example.com --httpOnly --secure
-playwright-cli cookie-delete session_id
-playwright-cli cookie-clear
-
-# LocalStorage
-playwright-cli localstorage-list
-playwright-cli localstorage-get theme
-playwright-cli localstorage-set theme dark
-playwright-cli localstorage-delete theme
-playwright-cli localstorage-clear
-
-# SessionStorage
-playwright-cli sessionstorage-list
-playwright-cli sessionstorage-get step
-playwright-cli sessionstorage-set step 3
-playwright-cli sessionstorage-delete step
-playwright-cli sessionstorage-clear
-```
-
-### Network
-
-```bash
-playwright-cli route "**/*.jpg" --status=404
-playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
-playwright-cli route-list
-playwright-cli unroute "**/*.jpg"
-playwright-cli unroute
-```
-
-### DevTools
-
-```bash
-playwright-cli console
-playwright-cli console warning
-playwright-cli network
-playwright-cli run-code "async page => await page.context().grantPermissions(['geolocation'])"
-playwright-cli tracing-start
-playwright-cli tracing-stop
-playwright-cli video-start
-playwright-cli video-stop video.webm
-```
-
-### Install
-
-```bash
-playwright-cli install-browser
-playwright-cli install-skills
-```
+
### Configuration
-```bash
-# Use specific browser when creating session
-playwright-cli open --browser=chrome
-playwright-cli open --browser=firefox
-playwright-cli open --browser=webkit
-playwright-cli open --browser=msedge
-# Connect to browser via extension
-playwright-cli open --extension
+Playwright MCP server supports following arguments. They can be provided in the JSON configuration above, as a part of the `"args"` list:
-# Configure the session
-playwright-cli config --config my-config.json
-playwright-cli config --headed --in-memory --browser=firefox
-# Configure named session
-playwright-cli --session=mysession config my-config.json
-# Start with configured session
-playwright-cli open --config=my-config.json
-```
-
+
-## Configuration file
+| Option | Description |
+|--------|-------------|
+| --allowed-hosts | comma-separated list of hosts this server is allowed to serve from. Defaults to the host the server is bound to. Pass '*' to disable the host check.
*env* `PLAYWRIGHT_MCP_ALLOWED_HOSTS` |
+| --allowed-origins | semicolon-separated list of TRUSTED origins to allow the browser to request. Default is to allow all. Important: *does not* serve as a security boundary and *does not* affect redirects.
*env* `PLAYWRIGHT_MCP_ALLOWED_ORIGINS` |
+| --allow-unrestricted-file-access | allow access to files outside of the workspace roots. Also allows unrestricted access to file:// URLs. By default access to file system is restricted to workspace root directories (or cwd if no roots are configured) only, and navigation to file:// URLs is blocked.
*env* `PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS` |
+| --blocked-origins | semicolon-separated list of origins to block the browser from requesting. Blocklist is evaluated before allowlist. If used without the allowlist, requests not matching the blocklist are still allowed. Important: *does not* serve as a security boundary and *does not* affect redirects.
*env* `PLAYWRIGHT_MCP_BLOCKED_ORIGINS` |
+| --block-service-workers | block service workers
*env* `PLAYWRIGHT_MCP_BLOCK_SERVICE_WORKERS` |
+| --browser | browser or chrome channel to use, possible values: chrome, firefox, webkit, msedge.
*env* `PLAYWRIGHT_MCP_BROWSER` |
+| --caps | comma-separated list of additional capabilities to enable, possible values: vision, pdf, devtools.
*env* `PLAYWRIGHT_MCP_CAPS` |
+| --cdp-endpoint | CDP endpoint to connect to.
*env* `PLAYWRIGHT_MCP_CDP_ENDPOINT` |
+| --cdp-header | CDP headers to send with the connect request, multiple can be specified.
*env* `PLAYWRIGHT_MCP_CDP_HEADER` |
+| --codegen | specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript".
*env* `PLAYWRIGHT_MCP_CODEGEN` |
+| --config | path to the configuration file.
*env* `PLAYWRIGHT_MCP_CONFIG` |
+| --console-level | level of console messages to return: "error", "warning", "info", "debug". Each level includes the messages of more severe levels.
*env* `PLAYWRIGHT_MCP_CONSOLE_LEVEL` |
+| --device | device to emulate, for example: "iPhone 15"
*env* `PLAYWRIGHT_MCP_DEVICE` |
+| --executable-path | path to the browser executable.
*env* `PLAYWRIGHT_MCP_EXECUTABLE_PATH` |
+| --extension | Connect to a running browser instance (Edge/Chrome only). Requires the "Playwright MCP Bridge" browser extension to be installed.
*env* `PLAYWRIGHT_MCP_EXTENSION` |
+| --grant-permissions | List of permissions to grant to the browser context, for example "geolocation", "clipboard-read", "clipboard-write".
*env* `PLAYWRIGHT_MCP_GRANT_PERMISSIONS` |
+| --headless | run browser in headless mode, headed by default
*env* `PLAYWRIGHT_MCP_HEADLESS` |
+| --host | host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.
*env* `PLAYWRIGHT_MCP_HOST` |
+| --ignore-https-errors | ignore https errors
*env* `PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS` |
+| --init-page | path to TypeScript file to evaluate on Playwright page object
*env* `PLAYWRIGHT_MCP_INIT_PAGE` |
+| --init-script | path to JavaScript file to add as an initialization script. The script will be evaluated in every page before any of the page's scripts. Can be specified multiple times.
*env* `PLAYWRIGHT_MCP_INIT_SCRIPT` |
+| --isolated | keep the browser profile in memory, do not save it to disk.
*env* `PLAYWRIGHT_MCP_ISOLATED` |
+| --image-responses | whether to send image responses to the client. Can be "allow" or "omit", Defaults to "allow".
*env* `PLAYWRIGHT_MCP_IMAGE_RESPONSES` |
+| --no-sandbox | disable the sandbox for all process types that are normally sandboxed.
*env* `PLAYWRIGHT_MCP_NO_SANDBOX` |
+| --output-dir | path to the directory for output files.
*env* `PLAYWRIGHT_MCP_OUTPUT_DIR` |
+| --output-mode | whether to save snapshots, console messages, network logs to a file or to the standard output. Can be "file" or "stdout". Default is "stdout".
*env* `PLAYWRIGHT_MCP_OUTPUT_MODE` |
+| --port | port to listen on for SSE transport.
*env* `PLAYWRIGHT_MCP_PORT` |
+| --proxy-bypass | comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"
*env* `PLAYWRIGHT_MCP_PROXY_BYPASS` |
+| --proxy-server | specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"
*env* `PLAYWRIGHT_MCP_PROXY_SERVER` |
+| --sandbox | enable the sandbox for all process types that are normally not sandboxed.
*env* `PLAYWRIGHT_MCP_SANDBOX` |
+| --save-session | Whether to save the Playwright MCP session into the output directory.
*env* `PLAYWRIGHT_MCP_SAVE_SESSION` |
+| --save-trace | Whether to save the Playwright Trace of the session into the output directory.
*env* `PLAYWRIGHT_MCP_SAVE_TRACE` |
+| --save-video | Whether to save the video of the session into the output directory. For example "--save-video=800x600"
*env* `PLAYWRIGHT_MCP_SAVE_VIDEO` |
+| --secrets | path to a file containing secrets in the dotenv format
*env* `PLAYWRIGHT_MCP_SECRETS` |
+| --shared-browser-context | reuse the same browser context between all connected HTTP clients.
*env* `PLAYWRIGHT_MCP_SHARED_BROWSER_CONTEXT` |
+| --snapshot-mode | when taking snapshots for responses, specifies the mode to use. Can be "incremental", "full", or "none". Default is incremental.
*env* `PLAYWRIGHT_MCP_SNAPSHOT_MODE` |
+| --storage-state | path to the storage state file for isolated sessions.
*env* `PLAYWRIGHT_MCP_STORAGE_STATE` |
+| --test-id-attribute | specify the attribute to use for test ids, defaults to "data-testid"
*env* `PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE` |
+| --timeout-action | specify action timeout in milliseconds, defaults to 5000ms
*env* `PLAYWRIGHT_MCP_TIMEOUT_ACTION` |
+| --timeout-navigation | specify navigation timeout in milliseconds, defaults to 60000ms
*env* `PLAYWRIGHT_MCP_TIMEOUT_NAVIGATION` |
+| --user-agent | specify user agent string
*env* `PLAYWRIGHT_MCP_USER_AGENT` |
+| --user-data-dir | path to the user data directory. If not specified, a temporary directory will be created.
*env* `PLAYWRIGHT_MCP_USER_DATA_DIR` |
+| --viewport-size | specify browser viewport size in pixels, for example "1280x720"
*env* `PLAYWRIGHT_MCP_VIEWPORT_SIZE` |
-The Playwright CLI can be configured using a JSON configuration file. You can specify the configuration file using the `--config` command line option:
+
+
+### User profile
+
+You can run Playwright MCP with persistent profile like a regular browser (default), in isolated contexts for testing sessions, or connect to your existing browser using the browser extension.
+
+**Persistent profile**
+
+All the logged in information will be stored in the persistent profile, you can delete it between sessions if you'd like to clear the offline state.
+Persistent profile is located at the following locations and you can override it with the `--user-data-dir` argument.
```bash
-playwright-cli --config path/to/config.json open example.com
+# Windows
+%USERPROFILE%\AppData\Local\ms-playwright\mcp-{channel}-profile
+
+# macOS
+- ~/Library/Caches/ms-playwright/mcp-{channel}-profile
+
+# Linux
+- ~/.cache/ms-playwright/mcp-{channel}-profile
```
-Playwright CLI will load config from `playwright-cli.json` by default so that you did not need to specify it every time.
+**Isolated**
+
+In the isolated mode, each session is started in the isolated profile. Every time you ask MCP to close the browser,
+the session is closed and all the storage state for this session is lost. You can provide initial storage state
+to the browser via the config's `contextOptions` or via the `--storage-state` argument. Learn more about the storage
+state [here](https://playwright.dev/docs/auth).
+
+```js
+{
+ "mcpServers": {
+ "playwright": {
+ "command": "npx",
+ "args": [
+ "@playwright/mcp@latest",
+ "--isolated",
+ "--storage-state={path/to/storage.json}"
+ ]
+ }
+ }
+}
+```
+
+**Browser Extension**
+
+The Playwright MCP Chrome Extension allows you to connect to existing browser tabs and leverage your logged-in sessions and browser state. See [packages/extension/README.md](packages/extension/README.md) for installation and setup instructions.
+
+### Initial state
+
+There are multiple ways to provide the initial state to the browser context or a page.
+
+For the storage state, you can either:
+- Start with a user data directory using the `--user-data-dir` argument. This will persist all browser data between the sessions.
+- Start with a storage state file using the `--storage-state` argument. This will load cookies and local storage from the file into an isolated browser context.
+
+For the page state, you can use:
+
+- `--init-page` to point to a TypeScript file that will be evaluated on the Playwright page object. This allows you to run arbitrary code to set up the page.
+
+```ts
+// init-page.ts
+export default async ({ page }) => {
+ await page.context().grantPermissions(['geolocation']);
+ await page.context().setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
+ await page.setViewportSize({ width: 1280, height: 720 });
+};
+```
+
+- `--init-script` to point to a JavaScript file that will be added as an initialization script. The script will be evaluated in every page before any of the page's scripts.
+This is useful for overriding browser APIs or setting up the environment.
+
+```js
+// init-script.js
+window.isPlaywrightMCP = true;
+```
+
+### Configuration file
+
+The Playwright MCP server can be configured using a JSON configuration file. You can specify the configuration file
+using the `--config` command line option:
+
+```bash
+npx @playwright/mcp@latest --config path/to/config.json
+```
Configuration file schema
+
+
```typescript
{
/**
@@ -377,6 +538,42 @@ Playwright CLI will load config from `playwright-cli.json` by default so that yo
initScript?: string[];
},
+ server?: {
+ /**
+ * The port to listen on for SSE or MCP transport.
+ */
+ port?: number;
+
+ /**
+ * The host to bind the server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.
+ */
+ host?: string;
+
+ /**
+ * The hosts this server is allowed to serve from. Defaults to the host server is bound to.
+ * This is not for CORS, but rather for the DNS rebinding protection.
+ */
+ allowedHosts?: string[];
+ },
+
+ /**
+ * List of enabled tool capabilities. Possible values:
+ * - 'core': Core browser automation features.
+ * - 'pdf': PDF generation and manipulation.
+ * - 'vision': Coordinate-based interactions.
+ */
+ capabilities?: ToolCapability[];
+
+ /**
+ * Whether to save the Playwright session into the output directory.
+ */
+ saveSession?: boolean;
+
+ /**
+ * Whether to save the Playwright trace of the session into the output directory.
+ */
+ saveTrace?: boolean;
+
/**
* If specified, saves the Playwright video of the session into the output directory.
*/
@@ -385,6 +582,18 @@ Playwright CLI will load config from `playwright-cli.json` by default so that yo
height: number;
};
+ /**
+ * Reuse the same browser context between all connected HTTP clients.
+ */
+ sharedBrowserContext?: boolean;
+
+ /**
+ * Secrets are used to prevent LLM from getting sensitive data while
+ * automating scenarios such as authentication.
+ * Prefer the browser.contextOptions.storageState over secrets file as a more secure alternative.
+ */
+ secrets?: Record;
+
/**
* The directory to save output files.
*/
@@ -431,6 +640,18 @@ Playwright CLI will load config from `playwright-cli.json` by default so that yo
navigation?: number;
};
+ /**
+ * Whether to send image responses to the client. Can be "allow", "omit", or "auto". Defaults to "auto", which sends images if the client can display them.
+ */
+ imageResponses?: 'allow' | 'omit';
+
+ snapshot?: {
+ /**
+ * When taking snapshots for responses, specifies the mode to use.
+ */
+ mode?: 'incremental' | 'full' | 'none';
+ };
+
/**
* Whether to allow file uploads from anywhere on the file system.
* By default (false), file uploads are restricted to paths within the MCP roots only.
@@ -444,483 +665,470 @@ Playwright CLI will load config from `playwright-cli.json` by default so that yo
}
```
+
+
-## Environment
+### Standalone MCP server
-| Environment |
-|-------------|
-| `PLAYWRIGHT_MCP_ALLOWED_HOSTS` comma-separated list of hosts this server is allowed to serve from. Defaults to the host the server is bound to. Pass '*' to disable the host check. |
-| `PLAYWRIGHT_MCP_ALLOWED_ORIGINS` semicolon-separated list of TRUSTED origins to allow the browser to request. Default is to allow all. Important: *does not* serve as a security boundary and *does not* affect redirects. |
-| `PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS` allow access to files outside of the workspace roots. Also allows unrestricted access to file:// URLs. By default access to file system is restricted to workspace root directories (or cwd if no roots are configured) only, and navigation to file:// URLs is blocked. |
-| `PLAYWRIGHT_MCP_BLOCKED_ORIGINS` semicolon-separated list of origins to block the browser from requesting. Blocklist is evaluated before allowlist. If used without the allowlist, requests not matching the blocklist are still allowed. Important: *does not* serve as a security boundary and *does not* affect redirects. |
-| `PLAYWRIGHT_MCP_BLOCK_SERVICE_WORKERS` block service workers |
-| `PLAYWRIGHT_MCP_BROWSER` browser or chrome channel to use, possible values: chrome, firefox, webkit, msedge. |
-| `PLAYWRIGHT_MCP_CAPS` comma-separated list of additional capabilities to enable, possible values: vision, pdf. |
-| `PLAYWRIGHT_MCP_CDP_ENDPOINT` CDP endpoint to connect to. |
-| `PLAYWRIGHT_MCP_CDP_HEADER` CDP headers to send with the connect request, multiple can be specified. |
-| `PLAYWRIGHT_MCP_CODEGEN` specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript". |
-| `PLAYWRIGHT_MCP_CONFIG` path to the configuration file. |
-| `PLAYWRIGHT_MCP_CONSOLE_LEVEL` level of console messages to return: "error", "warning", "info", "debug". Each level includes the messages of more severe levels. |
-| `PLAYWRIGHT_MCP_DEVICE` device to emulate, for example: "iPhone 15" |
-| `PLAYWRIGHT_MCP_EXECUTABLE_PATH` path to the browser executable. |
-| `PLAYWRIGHT_MCP_EXTENSION` Connect to a running browser instance (Edge/Chrome only). Requires the "Playwright MCP Bridge" browser extension to be installed. |
-| `PLAYWRIGHT_MCP_GRANT_PERMISSIONS` List of permissions to grant to the browser context, for example "geolocation", "clipboard-read", "clipboard-write". |
-| `PLAYWRIGHT_MCP_HEADLESS` run browser in headless mode, headed by default |
-| `PLAYWRIGHT_MCP_HOST` host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces. |
-| `PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS` ignore https errors |
-| `PLAYWRIGHT_MCP_INIT_PAGE` path to TypeScript file to evaluate on Playwright page object |
-| `PLAYWRIGHT_MCP_INIT_SCRIPT` path to JavaScript file to add as an initialization script. The script will be evaluated in every page before any of the page's scripts. Can be specified multiple times. |
-| `PLAYWRIGHT_MCP_ISOLATED` keep the browser profile in memory, do not save it to disk. |
-| `PLAYWRIGHT_MCP_IMAGE_RESPONSES` whether to send image responses to the client. Can be "allow" or "omit", Defaults to "allow". |
-| `PLAYWRIGHT_MCP_NO_SANDBOX` disable the sandbox for all process types that are normally sandboxed. |
-| `PLAYWRIGHT_MCP_OUTPUT_DIR` path to the directory for output files. |
-| `PLAYWRIGHT_MCP_OUTPUT_MODE` whether to save snapshots, console messages, network logs to a file or to the standard output. Can be "file" or "stdout". Default is "stdout". |
-| `PLAYWRIGHT_MCP_PORT` port to listen on for SSE transport. |
-| `PLAYWRIGHT_MCP_PROXY_BYPASS` comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com" |
-| `PLAYWRIGHT_MCP_PROXY_SERVER` specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080" |
-| `PLAYWRIGHT_MCP_SAVE_SESSION` Whether to save the Playwright MCP session into the output directory. |
-| `PLAYWRIGHT_MCP_SAVE_TRACE` Whether to save the Playwright Trace of the session into the output directory. |
-| `PLAYWRIGHT_MCP_SAVE_VIDEO` Whether to save the video of the session into the output directory. For example "--save-video=800x600" |
-| `PLAYWRIGHT_MCP_SECRETS` path to a file containing secrets in the dotenv format |
-| `PLAYWRIGHT_MCP_SHARED_BROWSER_CONTEXT` reuse the same browser context between all connected HTTP clients. |
-| `PLAYWRIGHT_MCP_SNAPSHOT_MODE` when taking snapshots for responses, specifies the mode to use. Can be "incremental", "full", or "none". Default is incremental. |
-| `PLAYWRIGHT_MCP_STORAGE_STATE` path to the storage state file for isolated sessions. |
-| `PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE` specify the attribute to use for test ids, defaults to "data-testid" |
-| `PLAYWRIGHT_MCP_TIMEOUT_ACTION` specify action timeout in milliseconds, defaults to 5000ms |
-| `PLAYWRIGHT_MCP_TIMEOUT_NAVIGATION` specify navigation timeout in milliseconds, defaults to 60000ms |
-| `PLAYWRIGHT_MCP_USER_AGENT` specify user agent string |
-| `PLAYWRIGHT_MCP_USER_DATA_DIR` path to the user data directory. If not specified, a temporary directory will be created. |
-| `PLAYWRIGHT_MCP_VIEWPORT_SIZE` specify browser viewport size in pixels, for example "1280x720" |
-Ccopilot and others will use the locally installed skills.
+When running headed browser on system w/o display or from worker processes of the IDEs,
+run the MCP server from environment with the DISPLAY and pass the `--port` flag to enable HTTP transport.
```bash
-playwright-cli install-skills
+npx @playwright/mcp@latest --port 8931
```
-### Skills-less operation
-
-Point your agent at the CLI and let it cook. It'll read the skill off `playwright-cli --help` on its own:
+And then in MCP client config, set the `url` to the HTTP endpoint:
+```js
+{
+ "mcpServers": {
+ "playwright": {
+ "url": "http://localhost:8931/mcp"
+ }
+ }
+}
```
-Test the "add todo" flow on https://demo.playwright.dev/todomvc using playwright-cli.
-Check playwright-cli --help for available commands.
-```
-
-## Demo
-
-```
-> Use playwright skills to test https://demo.playwright.dev/todomvc/.
- Take screenshots for all successful and failing scenarios.
-```
-
-Your agent will be running commands, but it does not mean you can't play with it manually:
-
-```
-playwright-cli open https://demo.playwright.dev/todomvc/ --headed
-playwright-cli type "Buy groceries"
-playwright-cli press Enter
-playwright-cli type "Water flowers"
-playwright-cli press Enter
-playwright-cli check e21
-playwright-cli check e35
-playwright-cli screenshot
-```
-
-## Headed operation
-
-Playwright CLI is headless by default. If you'd like to see the browser, pass `--headed` to `open`:
-
-```bash
-playwright-cli open https://playwright.dev --headed
-```
-
-## Sessions
-
-Playwright CLI will use a dedicated persistent profile by default. It means that
-your cookies and other storage state will be preserved between the calls. You can use different
-instances of the browser for different projects with sessions.
-
-Following will result in two browsers with separate profiles being available. Pass `--session` to
-the invocation to talk to a specific browser.
-
-```bash
-playwright-cli open https://playwright.dev
-playwright-cli --session=example open https://example.com
-playwright-cli session-list
-```
-
-You can run your coding agent with the `PLAYWRIGHT_CLI_SESSION` environment variable:
-
-```bash
-PLAYWRIGHT_CLI_SESSION=todo-app claude .
-```
-
-Or instruct it to prepend `--session` to the calls.
-
-Manage your sessions as follows:
-
-```bash
-playwright-cli session-list # list all sessions
-playwright-cli session-stop [name] # stop session
-playwright-cli session-restart [name] # restart session
-playwright-cli session-stop-all # stop all sessions
-playwright-cli session-delete [name] # delete session data along with the profiles
-```
-
-
-
-## Commands
-
-### Core
-
-```bash
-playwright-cli open https://example.com/
-playwright-cli close
-playwright-cli type "search query"
-playwright-cli click e3
-playwright-cli dblclick e7
-playwright-cli fill e5 "user@example.com"
-playwright-cli drag e2 e8
-playwright-cli hover e4
-playwright-cli select e9 "option-value"
-playwright-cli upload ./document.pdf
-playwright-cli check e12
-playwright-cli uncheck e12
-playwright-cli snapshot
-playwright-cli snapshot --filename=after-click.yaml
-playwright-cli eval "document.title"
-playwright-cli eval "el => el.textContent" e5
-playwright-cli dialog-accept
-playwright-cli dialog-accept "confirmation text"
-playwright-cli dialog-dismiss
-playwright-cli resize 1920 1080
-```
-
-### Navigation
-
-```bash
-playwright-cli go-back
-playwright-cli go-forward
-playwright-cli reload
-```
-
-### Keyboard
-
-```bash
-playwright-cli press Enter
-playwright-cli press ArrowDown
-playwright-cli keydown Shift
-playwright-cli keyup Shift
-```
-
-### Mouse
-
-```bash
-playwright-cli mousemove 150 300
-playwright-cli mousedown
-playwright-cli mousedown right
-playwright-cli mouseup
-playwright-cli mouseup right
-playwright-cli mousewheel 0 100
-```
-
-### Save as
-
-```bash
-playwright-cli screenshot
-playwright-cli screenshot e5
-playwright-cli screenshot --filename=page.png
-playwright-cli pdf --filename=page.pdf
-```
-
-### Tabs
-
-```bash
-playwright-cli tab-list
-playwright-cli tab-new
-playwright-cli tab-new https://example.com/page
-playwright-cli tab-close
-playwright-cli tab-close 2
-playwright-cli tab-select 0
-```
-
-### Storage
-
-```bash
-playwright-cli state-save
-playwright-cli state-save auth.json
-playwright-cli state-load auth.json
-
-# Cookies
-playwright-cli cookie-list
-playwright-cli cookie-list --domain=example.com
-playwright-cli cookie-get session_id
-playwright-cli cookie-set session_id abc123
-playwright-cli cookie-set session_id abc123 --domain=example.com --httpOnly --secure
-playwright-cli cookie-delete session_id
-playwright-cli cookie-clear
-
-# LocalStorage
-playwright-cli localstorage-list
-playwright-cli localstorage-get theme
-playwright-cli localstorage-set theme dark
-playwright-cli localstorage-delete theme
-playwright-cli localstorage-clear
-
-# SessionStorage
-playwright-cli sessionstorage-list
-playwright-cli sessionstorage-get step
-playwright-cli sessionstorage-set step 3
-playwright-cli sessionstorage-delete step
-playwright-cli sessionstorage-clear
-```
-
-### Network
-
-```bash
-playwright-cli route "**/*.jpg" --status=404
-playwright-cli route "https://api.example.com/**" --body='{"mock": true}'
-playwright-cli route-list
-playwright-cli unroute "**/*.jpg"
-playwright-cli unroute
-```
-
-### DevTools
-
-```bash
-playwright-cli console
-playwright-cli console warning
-playwright-cli network
-playwright-cli run-code "async page => await page.context().grantPermissions(['geolocation'])"
-playwright-cli tracing-start
-playwright-cli tracing-stop
-playwright-cli video-start
-playwright-cli video-stop video.webm
-```
-
-### Install
-
-```bash
-playwright-cli install-browser
-playwright-cli install-skills
-```
-
-### Configuration
-
-```bash
-# Use specific browser when creating session
-playwright-cli open --browser=chrome
-playwright-cli open --browser=firefox
-playwright-cli open --browser=webkit
-playwright-cli open --browser=msedge
-# Connect to browser via extension
-playwright-cli open --extension
-
-# Configure the session
-playwright-cli config --config my-config.json
-playwright-cli config --headed --in-memory --browser=firefox
-# Configure named session
-playwright-cli --session=mysession config my-config.json
-# Start with configured session
-playwright-cli open --config=my-config.json
-```
-
-
-## Configuration file
-
-The Playwright CLI can be configured using a JSON configuration file. You can specify the configuration file using the `--config` command line option:
-
-```bash
-playwright-cli --config path/to/config.json open example.com
-```
-
-Playwright CLI will load config from `playwright-cli.json` by default so that you did not need to specify it every time.
-Configuration file schema
+Docker
-```typescript
+**NOTE:** The Docker implementation only supports headless chromium at the moment.
+
+```js
{
- /**
- * The browser to use.
- */
- browser?: {
- /**
- * The type of browser to use.
- */
- browserName?: 'chromium' | 'firefox' | 'webkit';
-
- /**
- * Keep the browser profile in memory, do not save it to disk.
- */
- isolated?: boolean;
-
- /**
- * Path to a user data directory for browser profile persistence.
- * Temporary directory is created by default.
- */
- userDataDir?: string;
-
- /**
- * Launch options passed to
- * @see https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context
- *
- * This is useful for settings options like `channel`, `headless`, `executablePath`, etc.
- */
- launchOptions?: playwright.LaunchOptions;
-
- /**
- * Context options for the browser context.
- *
- * This is useful for settings options like `viewport`.
- */
- contextOptions?: playwright.BrowserContextOptions;
-
- /**
- * Chrome DevTools Protocol endpoint to connect to an existing browser instance in case of Chromium family browsers.
- */
- cdpEndpoint?: string;
-
- /**
- * CDP headers to send with the connect request.
- */
- cdpHeaders?: Record;
-
- /**
- * Timeout in milliseconds for connecting to CDP endpoint. Defaults to 30000 (30 seconds). Pass 0 to disable timeout.
- */
- cdpTimeout?: number;
-
- /**
- * Remote endpoint to connect to an existing Playwright server.
- */
- remoteEndpoint?: string;
-
- /**
- * Paths to TypeScript files to add as initialization scripts for Playwright page.
- */
- initPage?: string[];
-
- /**
- * Paths to JavaScript files to add as initialization scripts.
- * The scripts will be evaluated in every page before any of the page's scripts.
- */
- initScript?: string[];
- },
-
- /**
- * If specified, saves the Playwright video of the session into the output directory.
- */
- saveVideo?: {
- width: number;
- height: number;
- };
-
- /**
- * The directory to save output files.
- */
- outputDir?: string;
-
- /**
- * Whether to save snapshots, console messages, network logs and other session logs to a file or to the standard output. Defaults to "stdout".
- */
- outputMode?: 'file' | 'stdout';
-
- console?: {
- /**
- * The level of console messages to return. Each level includes the messages of more severe levels. Defaults to "info".
- */
- level?: 'error' | 'warning' | 'info' | 'debug';
- },
-
- network?: {
- /**
- * List of origins to allow the browser to request. Default is to allow all. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
- */
- allowedOrigins?: string[];
-
- /**
- * List of origins to block the browser to request. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
- */
- blockedOrigins?: string[];
- };
-
- /**
- * Specify the attribute to use for test ids, defaults to "data-testid".
- */
- testIdAttribute?: string;
-
- timeouts?: {
- /*
- * Configures default action timeout: https://playwright.dev/docs/api/class-page#page-set-default-timeout. Defaults to 5000ms.
- */
- action?: number;
-
- /*
- * Configures default navigation timeout: https://playwright.dev/docs/api/class-page#page-set-default-navigation-timeout. Defaults to 60000ms.
- */
- navigation?: number;
- };
-
- /**
- * Whether to allow file uploads from anywhere on the file system.
- * By default (false), file uploads are restricted to paths within the MCP roots only.
- */
- allowUnrestrictedFileAccess?: boolean;
-
- /**
- * Specify the language to use for code generation.
- */
- codegen?: 'typescript' | 'none';
+ "mcpServers": {
+ "playwright": {
+ "command": "docker",
+ "args": ["run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp"]
+ }
+ }
}
```
+Or If you prefer to run the container as a long-lived service instead of letting the MCP client spawn it, use:
+
+```
+docker run -d -i --rm --init --pull=always \
+ --entrypoint node \
+ --name playwright \
+ -p 8931:8931 \
+ mcr.microsoft.com/playwright/mcp \
+ cli.js --headless --browser chromium --no-sandbox --port 8931
+```
+
+The server will listen on host port **8931** and can be reached by any MCP client.
+
+You can build the Docker image yourself.
+
+```
+docker build -t mcr.microsoft.com/playwright/mcp .
+```
-## Environment
+
+Programmatic usage
-| Environment |
-|-------------|
-| `PLAYWRIGHT_MCP_ALLOWED_HOSTS` comma-separated list of hosts this server is allowed to serve from. Defaults to the host the server is bound to. Pass '*' to disable the host check. |
-| `PLAYWRIGHT_MCP_ALLOWED_ORIGINS` semicolon-separated list of TRUSTED origins to allow the browser to request. Default is to allow all. Important: *does not* serve as a security boundary and *does not* affect redirects. |
-| `PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS` allow access to files outside of the workspace roots. Also allows unrestricted access to file:// URLs. By default access to file system is restricted to workspace root directories (or cwd if no roots are configured) only, and navigation to file:// URLs is blocked. |
-| `PLAYWRIGHT_MCP_BLOCKED_ORIGINS` semicolon-separated list of origins to block the browser from requesting. Blocklist is evaluated before allowlist. If used without the allowlist, requests not matching the blocklist are still allowed. Important: *does not* serve as a security boundary and *does not* affect redirects. |
-| `PLAYWRIGHT_MCP_BLOCK_SERVICE_WORKERS` block service workers |
-| `PLAYWRIGHT_MCP_BROWSER` browser or chrome channel to use, possible values: chrome, firefox, webkit, msedge. |
-| `PLAYWRIGHT_MCP_CAPS` comma-separated list of additional capabilities to enable, possible values: vision, pdf. |
-| `PLAYWRIGHT_MCP_CDP_ENDPOINT` CDP endpoint to connect to. |
-| `PLAYWRIGHT_MCP_CDP_HEADER` CDP headers to send with the connect request, multiple can be specified. |
-| `PLAYWRIGHT_MCP_CODEGEN` specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript". |
-| `PLAYWRIGHT_MCP_CONFIG` path to the configuration file. |
-| `PLAYWRIGHT_MCP_CONSOLE_LEVEL` level of console messages to return: "error", "warning", "info", "debug". Each level includes the messages of more severe levels. |
-| `PLAYWRIGHT_MCP_DEVICE` device to emulate, for example: "iPhone 15" |
-| `PLAYWRIGHT_MCP_EXECUTABLE_PATH` path to the browser executable. |
-| `PLAYWRIGHT_MCP_EXTENSION` Connect to a running browser instance (Edge/Chrome only). Requires the "Playwright MCP Bridge" browser extension to be installed. |
-| `PLAYWRIGHT_MCP_GRANT_PERMISSIONS` List of permissions to grant to the browser context, for example "geolocation", "clipboard-read", "clipboard-write". |
-| `PLAYWRIGHT_MCP_HEADLESS` run browser in headless mode, headed by default |
-| `PLAYWRIGHT_MCP_HOST` host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces. |
-| `PLAYWRIGHT_MCP_IGNORE_HTTPS_ERRORS` ignore https errors |
-| `PLAYWRIGHT_MCP_INIT_PAGE` path to TypeScript file to evaluate on Playwright page object |
-| `PLAYWRIGHT_MCP_INIT_SCRIPT` path to JavaScript file to add as an initialization script. The script will be evaluated in every page before any of the page's scripts. Can be specified multiple times. |
-| `PLAYWRIGHT_MCP_ISOLATED` keep the browser profile in memory, do not save it to disk. |
-| `PLAYWRIGHT_MCP_IMAGE_RESPONSES` whether to send image responses to the client. Can be "allow" or "omit", Defaults to "allow". |
-| `PLAYWRIGHT_MCP_NO_SANDBOX` disable the sandbox for all process types that are normally sandboxed. |
-| `PLAYWRIGHT_MCP_OUTPUT_DIR` path to the directory for output files. |
-| `PLAYWRIGHT_MCP_OUTPUT_MODE` whether to save snapshots, console messages, network logs to a file or to the standard output. Can be "file" or "stdout". Default is "stdout". |
-| `PLAYWRIGHT_MCP_PORT` port to listen on for SSE transport. |
-| `PLAYWRIGHT_MCP_PROXY_BYPASS` comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com" |
-| `PLAYWRIGHT_MCP_PROXY_SERVER` specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080" |
-| `PLAYWRIGHT_MCP_SAVE_SESSION` Whether to save the Playwright MCP session into the output directory. |
-| `PLAYWRIGHT_MCP_SAVE_TRACE` Whether to save the Playwright Trace of the session into the output directory. |
-| `PLAYWRIGHT_MCP_SAVE_VIDEO` Whether to save the video of the session into the output directory. For example "--save-video=800x600" |
-| `PLAYWRIGHT_MCP_SECRETS` path to a file containing secrets in the dotenv format |
-| `PLAYWRIGHT_MCP_SHARED_BROWSER_CONTEXT` reuse the same browser context between all connected HTTP clients. |
-| `PLAYWRIGHT_MCP_SNAPSHOT_MODE` when taking snapshots for responses, specifies the mode to use. Can be "incremental", "full", or "none". Default is incremental. |
-| `PLAYWRIGHT_MCP_STORAGE_STATE` path to the storage state file for isolated sessions. |
-| `PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE` specify the attribute to use for test ids, defaults to "data-testid" |
-| `PLAYWRIGHT_MCP_TIMEOUT_ACTION` specify action timeout in milliseconds, defaults to 5000ms |
-| `PLAYWRIGHT_MCP_TIMEOUT_NAVIGATION` specify navigation timeout in milliseconds, defaults to 60000ms |
-| `PLAYWRIGHT_MCP_USER_AGENT` specify user agent string |
-| `PLAYWRIGHT_MCP_USER_DATA_DIR` path to the user data directory. If not specified, a temporary directory will be created. |
-| `PLAYWRIGHT_MCP_VIEWPORT_SIZE` specify browser viewport size in pixels, for example "1280x720" |
+```js
+import http from 'http';
+
+import { createConnection } from '@playwright/mcp';
+import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
+
+http.createServer(async (req, res) => {
+ // ...
+
+ // Creates a headless Playwright MCP server with SSE transport
+ const connection = await createConnection({ browser: { launchOptions: { headless: true } } });
+ const transport = new SSEServerTransport('/messages', res);
+ await connection.connect(transport);
+
+ // ...
+});
+```
+
+
+### Tools
+
+
+
+
+Core automation
+
+
+
+- **browser_click**
+ - Title: Click
+ - Description: Perform click on a web page
+ - Parameters:
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string): Exact target element reference from the page snapshot
+ - `doubleClick` (boolean, optional): Whether to perform a double click instead of a single click
+ - `button` (string, optional): Button to click, defaults to left
+ - `modifiers` (array, optional): Modifier keys to press
+ - Read-only: **false**
+
+
+
+- **browser_close**
+ - Title: Close browser
+ - Description: Close the page
+ - Parameters: None
+ - Read-only: **false**
+
+
+
+- **browser_console_messages**
+ - Title: Get console messages
+ - Description: Returns all console messages
+ - Parameters:
+ - `level` (string): Level of the console messages to return. Each level includes the messages of more severe levels. Defaults to "info".
+ - `filename` (string, optional): Filename to save the console messages to. If not provided, messages are returned as text.
+ - Read-only: **true**
+
+
+
+- **browser_drag**
+ - Title: Drag mouse
+ - Description: Perform drag and drop between two elements
+ - Parameters:
+ - `startElement` (string): Human-readable source element description used to obtain the permission to interact with the element
+ - `startRef` (string): Exact source element reference from the page snapshot
+ - `endElement` (string): Human-readable target element description used to obtain the permission to interact with the element
+ - `endRef` (string): Exact target element reference from the page snapshot
+ - Read-only: **false**
+
+
+
+- **browser_evaluate**
+ - Title: Evaluate JavaScript
+ - Description: Evaluate JavaScript expression on page or element
+ - Parameters:
+ - `function` (string): () => { /* code */ } or (element) => { /* code */ } when element is provided
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string, optional): Exact target element reference from the page snapshot
+ - Read-only: **false**
+
+
+
+- **browser_file_upload**
+ - Title: Upload files
+ - Description: Upload one or multiple files
+ - Parameters:
+ - `paths` (array, optional): The absolute paths to the files to upload. Can be single file or multiple files. If omitted, file chooser is cancelled.
+ - Read-only: **false**
+
+
+
+- **browser_fill_form**
+ - Title: Fill form
+ - Description: Fill multiple form fields
+ - Parameters:
+ - `fields` (array): Fields to fill in
+ - Read-only: **false**
+
+
+
+- **browser_handle_dialog**
+ - Title: Handle a dialog
+ - Description: Handle a dialog
+ - Parameters:
+ - `accept` (boolean): Whether to accept the dialog.
+ - `promptText` (string, optional): The text of the prompt in case of a prompt dialog.
+ - Read-only: **false**
+
+
+
+- **browser_hover**
+ - Title: Hover mouse
+ - Description: Hover over element on page
+ - Parameters:
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string): Exact target element reference from the page snapshot
+ - Read-only: **false**
+
+
+
+- **browser_navigate**
+ - Title: Navigate to a URL
+ - Description: Navigate to a URL
+ - Parameters:
+ - `url` (string): The URL to navigate to
+ - Read-only: **false**
+
+
+
+- **browser_navigate_back**
+ - Title: Go back
+ - Description: Go back to the previous page in the history
+ - Parameters: None
+ - Read-only: **false**
+
+
+
+- **browser_network_requests**
+ - Title: List network requests
+ - Description: Returns all network requests since loading the page
+ - Parameters:
+ - `includeStatic` (boolean): Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.
+ - `filename` (string, optional): Filename to save the network requests to. If not provided, requests are returned as text.
+ - Read-only: **true**
+
+
+
+- **browser_press_key**
+ - Title: Press a key
+ - Description: Press a key on the keyboard
+ - Parameters:
+ - `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a`
+ - Read-only: **false**
+
+
+
+- **browser_resize**
+ - Title: Resize browser window
+ - Description: Resize the browser window
+ - Parameters:
+ - `width` (number): Width of the browser window
+ - `height` (number): Height of the browser window
+ - Read-only: **false**
+
+
+
+- **browser_run_code**
+ - Title: Run Playwright code
+ - Description: Run Playwright code snippet
+ - Parameters:
+ - `code` (string): A JavaScript function containing Playwright code to execute. It will be invoked with a single argument, page, which you can use for any page interaction. For example: `async (page) => { await page.getByRole('button', { name: 'Submit' }).click(); return await page.title(); }`
+ - Read-only: **false**
+
+
+
+- **browser_select_option**
+ - Title: Select option
+ - Description: Select an option in a dropdown
+ - Parameters:
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string): Exact target element reference from the page snapshot
+ - `values` (array): Array of values to select in the dropdown. This can be a single value or multiple values.
+ - Read-only: **false**
+
+
+
+- **browser_snapshot**
+ - Title: Page snapshot
+ - Description: Capture accessibility snapshot of the current page, this is better than screenshot
+ - Parameters:
+ - `filename` (string, optional): Save snapshot to markdown file instead of returning it in the response.
+ - Read-only: **true**
+
+
+
+- **browser_take_screenshot**
+ - Title: Take a screenshot
+ - Description: Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.
+ - Parameters:
+ - `type` (string): Image format for the screenshot. Default is png.
+ - `filename` (string, optional): File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified. Prefer relative file names to stay within the output directory.
+ - `element` (string, optional): Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too.
+ - `ref` (string, optional): Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too.
+ - `fullPage` (boolean, optional): When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots.
+ - Read-only: **true**
+
+
+
+- **browser_type**
+ - Title: Type text
+ - Description: Type text into editable element
+ - Parameters:
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string): Exact target element reference from the page snapshot
+ - `text` (string): Text to type into the element
+ - `submit` (boolean, optional): Whether to submit entered text (press Enter after)
+ - `slowly` (boolean, optional): Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.
+ - Read-only: **false**
+
+
+
+- **browser_wait_for**
+ - Title: Wait for
+ - Description: Wait for text to appear or disappear or a specified time to pass
+ - Parameters:
+ - `time` (number, optional): The time to wait in seconds
+ - `text` (string, optional): The text to wait for
+ - `textGone` (string, optional): The text to wait for to disappear
+ - Read-only: **false**
+
+
+
+
+Tab management
+
+
+
+- **browser_tabs**
+ - Title: Manage tabs
+ - Description: List, create, close, or select a browser tab.
+ - Parameters:
+ - `action` (string): Operation to perform
+ - `index` (number, optional): Tab index, used for close/select. If omitted for close, current tab is closed.
+ - Read-only: **false**
+
+
+
+
+Browser installation
+
+
+
+- **browser_install**
+ - Title: Install the browser specified in the config
+ - Description: Install the browser specified in the config. Call this if you get an error about the browser not being installed.
+ - Parameters: None
+ - Read-only: **false**
+
+
+
+
+Coordinate-based (opt-in via --caps=vision)
+
+
+
+- **browser_mouse_click_xy**
+ - Title: Click
+ - Description: Click left mouse button at a given position
+ - Parameters:
+ - `x` (number): X coordinate
+ - `y` (number): Y coordinate
+ - Read-only: **false**
+
+
+
+- **browser_mouse_down**
+ - Title: Press mouse down
+ - Description: Press mouse down
+ - Parameters:
+ - `button` (string, optional): Button to press, defaults to left
+ - Read-only: **false**
+
+
+
+- **browser_mouse_drag_xy**
+ - Title: Drag mouse
+ - Description: Drag left mouse button to a given position
+ - Parameters:
+ - `startX` (number): Start X coordinate
+ - `startY` (number): Start Y coordinate
+ - `endX` (number): End X coordinate
+ - `endY` (number): End Y coordinate
+ - Read-only: **false**
+
+
+
+- **browser_mouse_move_xy**
+ - Title: Move mouse
+ - Description: Move mouse to a given position
+ - Parameters:
+ - `x` (number): X coordinate
+ - `y` (number): Y coordinate
+ - Read-only: **false**
+
+
+
+- **browser_mouse_up**
+ - Title: Press mouse up
+ - Description: Press mouse up
+ - Parameters:
+ - `button` (string, optional): Button to press, defaults to left
+ - Read-only: **false**
+
+
+
+- **browser_mouse_wheel**
+ - Title: Scroll mouse wheel
+ - Description: Scroll mouse wheel
+ - Parameters:
+ - `deltaX` (number): X delta
+ - `deltaY` (number): Y delta
+ - Read-only: **false**
+
+
+
+
+PDF generation (opt-in via --caps=pdf)
+
+
+
+- **browser_pdf_save**
+ - Title: Save as PDF
+ - Description: Save page as PDF
+ - Parameters:
+ - `filename` (string, optional): File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified. Prefer relative file names to stay within the output directory.
+ - Read-only: **true**
+
+
+
+
+Test assertions (opt-in via --caps=testing)
+
+
+
+- **browser_generate_locator**
+ - Title: Create locator for element
+ - Description: Generate locator for the given element to use in tests
+ - Parameters:
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
+ - `ref` (string): Exact target element reference from the page snapshot
+ - Read-only: **true**
+
+
+
+- **browser_verify_element_visible**
+ - Title: Verify element visible
+ - Description: Verify element is visible on the page
+ - Parameters:
+ - `role` (string): ROLE of the element. Can be found in the snapshot like this: `- {ROLE} "Accessible Name":`
+ - `accessibleName` (string): ACCESSIBLE_NAME of the element. Can be found in the snapshot like this: `- role "{ACCESSIBLE_NAME}"`
+ - Read-only: **false**
+
+
+
+- **browser_verify_list_visible**
+ - Title: Verify list visible
+ - Description: Verify list is visible on the page
+ - Parameters:
+ - `element` (string): Human-readable list description
+ - `ref` (string): Exact target element reference that points to the list
+ - `items` (array): Items to verify
+ - Read-only: **false**
+
+
+
+- **browser_verify_text_visible**
+ - Title: Verify text visible
+ - Description: Verify text is visible on the page. Prefer browser_verify_element_visible if possible.
+ - Parameters:
+ - `text` (string): TEXT to verify. Can be found in the snapshot like this: `- role "Accessible Name": {TEXT}` or like this: `- text: {TEXT}`
+ - Read-only: **false**
+
+
+
+- **browser_verify_value**
+ - Title: Verify value
+ - Description: Verify element value
+ - Parameters:
+ - `type` (string): Type of the element
+ - `element` (string): Human-readable element description
+ - `ref` (string): Exact target element reference that points to the element
+ - `value` (string): Value to verify. For checkbox, use "true" or "false".
+ - Read-only: **false**
+
+
+
+
+Tracing (opt-in via --caps=tracing)
+
+
+
+
+