From 822d81e02b27ffada4ec04fbdf2e350f19dc2061 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 3 Feb 2026 15:52:13 -0800 Subject: [PATCH] restoring readme --- README.md | 1612 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 910 insertions(+), 702 deletions(-) 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" + ] + } + } +} +``` + +[Install in VS Code](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) [Install in VS Code Insiders](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: + +[Install in Cursor](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: + +[![Install in Goose](https://block.github.io/goose/img/extension-install-dark.svg)](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: + +[![Add MCP Server playwright to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](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: + +[Install in VS Code](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) [Install in VS Code Insiders](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) + +
+ + +