Skip to main content
Glama

Playwright MCP Server

by alexrwilliam
README.md13.6 kB
# Playwright MCP Server A minimal, robust Playwright MCP (Model Context Protocol) server that exposes core browser automation capabilities via a simple API. ## Features - **Browser Context Management**: Persistent browser context (headless or headed, configurable) - **Multi-Page Support**: Handle multiple tabs/windows, switch between pages, manage popups - **Navigation**: Open URLs, reload, go back/forward - **DOM Interaction**: Click, type, fill, select, hover, scroll using Playwright selectors - **Element Discovery**: Query elements using CSS, XPath, role, text, and other Playwright locators - **Snapshotting**: Get HTML, accessibility snapshots, screenshots, and PDFs - **Token-Aware Outputs**: Configurable caps keep element queries and accessibility snapshots within safe sizes for LLM consumption - **Overflow Artifacts**: Large responses are trimmed automatically, auto-cleaned after ~2 hours by default, and include previews plus file references you can reopen via the `read_artifact` tool - **Script Evaluation**: Run JavaScript in the page context - **Network Monitoring**: Capture and analyze all network requests and responses - **Network Interception**: Block, modify, or mock network requests - **Cookie Management**: Get, set, and clear browser cookies - **Storage Access**: Manage localStorage and sessionStorage data - **Headers & User Agent**: Customize request headers and browser identity - **Raw Output**: All outputs are raw Playwright results with no post-processing ## Installation ### Quick Install from GitHub ```bash # Install directly from GitHub pip install git+https://github.com/alexrwilliam/playwright-mcp-server.git # Install Playwright browsers playwright install ``` ### For Development ```bash # Clone the repository git clone https://github.com/alexrwilliam/playwright-mcp-server.git cd playwright-mcp-server # Install in development mode pip install -e . # Install browsers playwright install ``` ## Usage ### Running the Server After installation, you can use it from anywhere: ```bash # Run with stdio transport (for MCP clients) playwright-mcp stdio # Run with HTTP transport playwright-mcp http --port 8000 # Run in headed mode (default is headless) playwright-mcp stdio --headed ``` ### Command Line Usage ```bash # Run the MCP server playwright-mcp stdio # Run with visible browser playwright-mcp stdio --headed # Run HTTP server playwright-mcp http --port 8000 # Use different browsers playwright-mcp stdio --browser firefox playwright-mcp stdio --browser webkit # Use real Chrome instead of bundled Chromium playwright-mcp stdio --channel chrome # Use real Chrome with your profile (cookies, extensions, history) playwright-mcp stdio --channel chrome --user-data-dir "/Users/you/Library/Application Support/Google/Chrome" # Adjust response budgets (defaults: 4k inline, 400-char previews) playwright-mcp stdio --max-response-chars 6000 --preview-chars 600 # Choose where overflow artifacts are written playwright-mcp stdio --artifact-dir /tmp/playwright-artifacts # Other Chrome channels playwright-mcp stdio --channel chrome-beta playwright-mcp stdio --channel chrome-dev ``` ### Integration with Claude Desktop Add to your `claude_desktop_config.json`: ```json { "mcpServers": { "playwright": { "command": "playwright-mcp", "args": ["stdio"] } } } ``` ### Testing with MCP Inspector ```bash # Install and run MCP inspector uv run mcp dev src/playwright_mcp/server.py ``` ### Response Budgeting & Artifacts High-volume tools (`evaluate`, `get_accessibility_snapshot`, `get_network_requests`, `get_network_responses`, and future additions) now honor a shared response budget. When the serialized payload would exceed `--max-response-chars`: - The inline result is trimmed to fit the budget and marked with `truncated: true`. - A compact `preview` (default 400 chars) snapshots what was retained. - The full payload is written to the artifact directory (default `tmp/playwright_mcp`) and returned as `overflow_path` plus the original size in `overflow_characters`. - Use the `read_artifact` tool (or open the file locally) to retrieve the saved payload. Artifacts that are binary fall back to base64 when read. - Artifacts are auto-pruned—by default anything older than two hours is deleted and the directory is capped at 200 files (`--artifact-max-age-seconds`, `--artifact-max-files`). Tweak the caps per run with `--max-response-chars`, `--preview-chars`, and `--artifact-dir` or override per-call limits where a tool exposes them. ## API Reference ### Tools #### Navigation & Page Control - `navigate(url: str)` - Navigate to a URL - `reload()` - Reload the current page - `go_back()` - Go back in history - `go_forward()` - Go forward in history - `get_current_url()` - Get current page URL with parsed components and query parameters - `wait_for_url(url_pattern: str, timeout: int)` - Wait for URL to match pattern - `wait_for_load_state(state: str, timeout: int)` - Wait for page load states (domcontentloaded, load, networkidle) - `set_viewport_size(width: int, height: int)` - Set viewport dimensions #### Multi-Page Management (Tabs/Windows) - `list_pages()` - List all open browser pages/tabs with IDs, URLs, and titles - `switch_page(page_id: str)` - Switch to a different page/tab by its ID - `close_page(page_id: str)` - Close a specific page/tab (cannot close last one) - `wait_for_popup(timeout: int)` - Wait for and capture a new popup/tab - `switch_to_latest_page()` - Switch to the most recently opened page #### Element Interaction - `click(selector: str)` - Click an element - `type_text(selector: str, text: str)` - Type text into an element - `fill(selector: str, value: str)` - Fill an input field - `clear_text(selector: str)` - Clear input field text - `select_option(selector: str, value: str)` - Select an option - `hover(selector: str)` - Hover over an element - `scroll(selector: str, x: int, y: int)` - Scroll element - `press_key(key: str)` - Press keyboard key #### Form Handling - `check_checkbox(selector: str)` - Check a checkbox - `uncheck_checkbox(selector: str)` - Uncheck a checkbox - `upload_file(selector: str, file_path: str)` - Upload file to input #### Element Discovery & Validation - `query_selector(selector: str, max_text_length: int | None = None)` - Query for single element (optional per-call text cap override) - `query_selector_all(selector: str, max_elements: int | None = None, max_text_length: int | None = None)` - Query for all matching elements (optional per-call overrides) - `query_selector_meta(selector: str, preview_length: int = 200, max_elements: int | None = None)` - Quick metadata preview (tag, role, short text, key attributes) - Element query tools obey global caps, accept per-call overrides, and return `truncated` / `returned_count` metadata when results are clipped. - `is_visible(selector: str)` - Check if element is visible - `is_enabled(selector: str)` - Check if element is enabled - `wait_for_element(selector: str, timeout: int)` - Wait for element to appear - `get_element_bounding_box(selector: str)` - Get element position and size - `get_element_attributes(selector: str)` - Get all element attributes - `get_computed_style(selector: str, property: str)` - Get CSS computed style #### Script Evaluation & Diagnostics - `evaluate(script: str)` - Execute JavaScript in page context (results respect the shared response budget and emit overflow metadata as needed) #### Network Monitoring & Overflow Retrieval - `get_network_requests(url_pattern: str | None = None)` - Inspect captured requests; large result sets spill to artifacts with previews - `get_network_responses(url_pattern: str | None = None)` - Inspect captured responses with the same budgeting behaviour - `read_artifact(path: str)` - Load an overflow artifact referenced in a previous response (returns text or base64 content) #### Content & Snapshots - `get_html()` - Get page HTML - `get_accessibility_snapshot(interesting_only: bool = True, root_selector: str | None = None, max_nodes: int | None = None)` - Get accessibility tree with optional filters and per-call node caps - Accessibility snapshots are pruned to the configured node budget, accept per-call overrides, and include `truncated`, `max_nodes`, and `node_count` metadata. - `screenshot(selector: str, full_page: bool)` - Take screenshot of page or element - `pdf()` - Generate PDF of page #### JavaScript & Debugging - `evaluate(script: str)` - Execute JavaScript in page context - `wait_for_network_idle(timeout: int)` - Wait for network activity to settle - `get_page_errors()` - Get JavaScript errors from page - `get_console_logs()` - Get console output from page #### Network Monitoring & Interception - `get_network_requests(url_pattern: str)` - Retrieve captured network requests with filtering - `get_network_responses(url_pattern: str)` - Retrieve captured network responses with filtering - `clear_network_logs()` - Clear all captured network request/response logs - `intercept_route(url_pattern: str, action: str, ...)` - Intercept and handle network requests - `unroute_all()` - Remove all route interceptors - `wait_for_response(url_pattern: str, timeout: int)` - Wait for specific network responses - `get_response_body(url_pattern: str)` - Extract response body content from network calls #### Cookie Management - `get_cookies(urls: List[str])` - Retrieve browser cookies with optional URL filtering - `add_cookies(cookies: List[Dict])` - Add cookies to browser context - `clear_cookies(name: str, domain: str)` - Clear cookies with optional filtering #### Storage Management - `get_local_storage(origin: str)` - Access localStorage data - `set_local_storage(key: str, value: str)` - Set localStorage items - `get_session_storage()` - Access sessionStorage data - `set_session_storage(key: str, value: str)` - Set sessionStorage items - `clear_storage(storage_type: str)` - Clear localStorage and/or sessionStorage #### Request Headers & Identity - `set_extra_headers(headers: Dict)` - Add custom HTTP headers to all requests - `set_user_agent(user_agent: str)` - Change browser User-Agent string ## Examples ### Handling Multiple Pages/Tabs The server automatically tracks all browser pages/tabs: ```python # Example: Clicking a link that opens in a new tab 1. navigate("https://example.com") 2. click("a[target='_blank']") # Opens new tab 3. list_pages() # Shows all open tabs with IDs 4. switch_to_latest_page() # Switch to the new tab 5. get_current_url() # Get URL of new tab 6. switch_page(original_page_id) # Switch back # Example: Handling JavaScript popups 1. evaluate("window.open('https://example.com', '_blank')") 2. wait_for_popup(timeout=5000) # Wait for and capture popup 3. list_pages() # See all pages including popup 4. close_page(popup_id) # Close the popup ``` All existing tools automatically work on the currently active page. When you switch pages, subsequent operations apply to the new active page. ### Configuration The server accepts the following configuration options: - `--headed` / `--headless` - Run browser in headed or headless mode - `--browser` - Browser type (chromium, firefox, webkit) - `--channel` - Browser channel (chrome, chrome-beta, msedge, etc.) for real browsers - `--user-data-dir` - Path to browser profile directory for persistent context - `--port` - Port for HTTP transport - `--timeout` - Default timeout for operations (ms) - `--max-elements` - Maximum number of DOM nodes returned by query tools (default: 20) - `--max-element-text-length` - Maximum characters returned for element text and attribute values (default: 2000) - `--max-accessibility-nodes` - Maximum accessibility tree nodes returned by `get_accessibility_snapshot` (default: 500) - `--max-response-chars` - Maximum serialized characters returned inline before results spill to artifact files (default: 4000) - `--preview-chars` - Maximum characters included in inline previews when truncation occurs (default: 400) - `--artifact-dir` - Directory where overflow artifacts are written (default: `./tmp/playwright_mcp`) - `--artifact-max-age-seconds` - Maximum age before artifacts are purged (default: 7200 seconds) - `--artifact-max-files` - Maximum number of artifact files kept in the directory (default: 200) All caps accept `0` or negative values to disable truncation entirely. When truncation occurs, tool responses include `truncated` flags and metadata so clients can optionally re-issue a narrower request. ### Real Chrome vs Bundled Chromium By default, Playwright uses bundled Chromium. For web scraping that requires real Chrome features: **Use `--channel chrome`** to use your installed Google Chrome: - Access to all Chrome features and codecs - Better compatibility with some websites - Chrome-specific behaviors **Use `--user-data-dir`** to access your real profile: - All your cookies and login sessions - Browser extensions (AdBlock, etc.) - Browsing history and autofill data - Bookmarks and saved passwords **Example for macOS:** ```bash playwright-mcp stdio --channel chrome --user-data-dir "/Users/$(whoami)/Library/Application Support/Google/Chrome" ``` **Example for Linux:** ```bash playwright-mcp stdio --channel chrome --user-data-dir "/home/$(whoami)/.config/google-chrome" ``` ## Development ```bash # Clone the repository git clone <repo-url> cd playwright-mcp # Install dependencies uv sync --dev # Run tests uv run pytest # Format code uv run black src/ uv run ruff check src/ # Type check uv run mypy src/ ``` ## License MIT

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alexrwilliam/playwright-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server