officialstdio

Puppeteer MCP Server

Let Claude Code and Cursor drive a real Chromium browser for scraping and form filling through MCP.

Updated: April 15, 2026

Install

npx @modelcontextprotocol/server-puppeteer
~/.claude/settings.json
{
  "mcpServers": {
    "mcp-server-puppeteer": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-puppeteer"
      ]
    }
  }
}

Capabilities

  • + Navigate to any URL with the full Chromium rendering stack
  • + Click elements by CSS selector or XPath
  • + Fill form inputs and submit forms
  • + Take full-page and element screenshots as PNG
  • + Extract page text and raw HTML after JavaScript executes
  • + Handle JavaScript-rendered single-page apps that break fetch

Limitations

  • - Heavy resource usage - spawns a full Chromium instance per session
  • - No persistent browser sessions between MCP calls
  • - Limited cookie and auth management compared to a logged-in browser
  • - Slow startup time: 4 to 8 seconds for the first navigate

Puppeteer MCP server setup for Claude Code and Cursor

Quick answer: The Puppeteer MCP server launches a headless Chromium instance under Claude Code or Cursor and exposes browser actions as MCP tools. The model can navigate URLs, click CSS selectors, fill inputs, take screenshots, and grab rendered HTML. This is the answer for sites that fail a plain HTTP fetch because they render with JavaScript. Setup takes about 5 minutes. Tested on April 15, 2026 with server version 0.6.2.

For scraping modern SPAs, filling out multi-step forms, or debugging the exact DOM a user sees, this is the right server. Plain fetch servers return pre-render HTML that is often just a loading skeleton. Puppeteer waits for the page to settle, then hands the model real content.

This guide covers installation, both editor configs, resource considerations, 8 example prompts, troubleshooting the common Chromium errors, and when Playwright is a better pick.

What this server does

The server wraps Puppeteer (the Node library that drives Chromium over the DevTools Protocol) with about 7 MCP tools: puppeteer_navigate, puppeteer_click, puppeteer_fill, puppeteer_screenshot, puppeteer_select, puppeteer_hover, and puppeteer_evaluate. The last one runs arbitrary JavaScript in the page context, which is the escape hatch when no other tool does what you need.

When the model wants to interact with a page, it calls tools in sequence: navigate, wait for an element, click, fill, submit. The server keeps a single browser instance alive for the life of the MCP process, but each tool call is a separate command rather than a recorded session.

What works well:

  • Scraping pages that render with React, Vue, Svelte, or other JS frameworks
  • Filling multi-step forms that need specific click order
  • Capturing screenshots for visual debugging or documentation
  • Extracting text after login-gated JavaScript finishes running
  • Testing a landing page across 3 or 4 viewport widths
  • Grabbing the rendered HTML after a SPA router navigates

What does not:

  • Long-lived sessions that span dozens of minutes
  • Heavy cookie or OAuth flows without manual env setup
  • Anything that needs a logged-in browser profile with extensions

Installing the Puppeteer MCP server

The package is @modelcontextprotocol/server-puppeteer. The npx -y pattern downloads the package plus a bundled Chromium on first run. That is about 170 MB. First cold start takes 10 to 15 seconds. After that, npx uses the cache and startup drops to 2 seconds - though the first navigate still takes 4 to 8 seconds because Chromium itself has to boot.

System requirements are modest but not trivial. Chromium wants about 500 MB of RAM per active tab. On a 16 GB machine running Claude Code plus the usual editor and browser, Puppeteer is fine. On an 8 GB machine it will make other things sluggish.

On Linux you need a few system libraries: libnss3, libatk-bridge2.0-0, libxkbcommon0, libdrm2. On Ubuntu, sudo apt-get install -y libnss3 libatk-bridge2.0-0 libxkbcommon0 libdrm2 libxcomposite1 libxrandr2 libasound2 covers the set. On macOS no extra setup is required.

Configuring for Claude Code

Claude Code reads from ~/.claude/mcp.json or a per-project .mcp.json. Add a puppeteer entry:

{
  "mcpServers": {
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
      "env": {}
    }
  }
}

Restart Claude Code. Run /mcp to confirm attachment. You should see the 7 puppeteer tools.

If you are behind a corporate proxy, set HTTPS_PROXY and HTTP_PROXY in the env block. Puppeteer picks these up automatically. If Chromium fails to download on first run, set PUPPETEER_SKIP_DOWNLOAD=true and point PUPPETEER_EXECUTABLE_PATH at an existing Chrome or Chromium binary.

Configuring for Cursor

Cursor's config lives at ~/.cursor/mcp.json on macOS and Linux, or %USERPROFILE%\.cursor\mcp.json on Windows. Same JSON:

{
  "mcpServers": {
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
      "env": {}
    }
  }
}

Toggle the server on. Cursor will spawn the process lazily. If Chromium has not been downloaded yet, the first tool call takes 15 to 30 seconds. You can pre-warm by running the server once from a terminal: npx -y @modelcontextprotocol/server-puppeteer and then Ctrl+C after you see the startup log.

Example prompts and workflows

Some prompts that show what the server can do:

  • "Navigate to https://news.ycombinator.com and list the top 10 story titles with their scores."
  • "Open the /pricing page on stripe.com, screenshot it at 1280x800, and tell me the listed price for the Standard plan."
  • "Fill out the contact form on example.com with test data and take a screenshot of the confirmation."
  • "Navigate to my own localhost:3000 site, click the Sign Up button, fill email and password, and confirm the redirect."
  • "Go to twitter.com/anthropicai, wait 3 seconds for the timeline to render, and extract the text of the most recent 5 tweets."
  • "Evaluate document.documentElement.outerHTML.length on nytimes.com and tell me the rendered size."
  • "Screenshot https://myapp.dev at 3 viewport widths: 375, 768, and 1440, and save all 3."
  • "Click through a 5-step checkout flow on my staging site and screenshot each step."

For scraping, the right pattern is: navigate, wait for a specific selector, extract. Asking the model to "wait for the page to fully load" is vague - tell it exactly which selector indicates the content is ready.

Troubleshooting

Chromium failed to download. Network issue or corporate proxy. Set HTTPS_PROXY in env, or skip download and point at a local Chrome install with PUPPETEER_EXECUTABLE_PATH.

Error: Failed to launch the browser process. On Linux, missing system libraries. Run ldd ~/.cache/puppeteer/chrome/*/chrome and install what is missing.

Screenshots are blank. The page uses lazy loading. Tell the model to scroll to the bottom first with puppeteer_evaluate, then screenshot. Or wait longer before the capture.

Timeout waiting for selector. The selector is wrong, or JavaScript has not rendered it yet. Use the browser devtools on the target page to confirm the selector, then pass an explicit timeout.

Memory keeps climbing. The server does not kill Chromium between calls. Restart the MCP server every 20 to 30 minutes of heavy use. In Claude Code: /mcp restart puppeteer.

Running in Docker. You need --cap-add=SYS_ADMIN or --security-opt seccomp=unconfined, plus the full set of Chromium libraries. The ghcr.io/puppeteer/puppeteer image is the shortest path.

Alternatives

Close neighbors in the MCP ecosystem:

  • playwright-mcp uses Playwright under the hood. Better cross-browser support (Chromium, Firefox, WebKit) and a more modern API. Slightly heavier install.
  • browserbase-mcp runs the browser in a hosted cloud sandbox. You get a real IP and no local Chromium, at the cost of latency and a paid tier.
  • mcp-server-fetch for static pages where JavaScript is not needed. 100x faster, 1000x lighter.

Use Puppeteer MCP when you control the target, you need JavaScript rendering, and you do not need cross-browser. Use Playwright when you want to test against Firefox or WebKit too. Use Browserbase when you need to scrape at scale and want a real residential IP. The verdict from 6 weeks of daily use: attach Puppeteer for local testing and debugging, reach for Browserbase when the target fights back.

Guides

Frequently asked questions

Does the Puppeteer MCP server work headless only?

By default yes, but you can set `PUPPETEER_HEADLESS=false` in env to see a real browser window pop up. Useful for debugging a scrape that is not working. Most production use should stay headless for speed and resource reasons.

Can I reuse a logged-in browser profile?

Not directly. The server spawns a clean Chromium instance each time. To preserve cookies, set `PUPPETEER_USER_DATA_DIR=/path/to/persistent/dir` in env. On the next launch Chromium will reuse cookies, local storage, and service workers from that directory.

How do I handle sites that detect headless browsers?

The stock server uses default Puppeteer which is detectable by most bot-detection services. For stealth, use `puppeteer-extra-plugin-stealth` via a custom MCP fork, or switch to Browserbase which ships with fingerprint evasion built in.

Can the model run JavaScript in the page context?

Yes. The `puppeteer_evaluate` tool takes a JS expression and runs it in the page. The result is returned to the model. This is the right tool for extracting specific values that are hard to target with selectors, or for triggering custom events.

What is the practical rate limit on navigation?

The server itself does not rate limit, but Chromium can only handle about 10 to 15 navigations per minute on a typical laptop before memory balloons. For bulk scraping, use Browserbase or a dedicated queue with throttling.

Why do screenshots sometimes look different from my browser?

Puppeteer defaults to a 800x600 viewport and no device pixel ratio. To match a modern browser, ask the model to set viewport to 1440x900 with deviceScaleFactor 2. That matches a retina MacBook display and usually produces identical rendering.