ScreenshotNeo

BlogAI agents

How to Install and Use Puppeteer MCP in Claude Code

Install Puppeteer MCP in Claude Code, fix Chromium issues, automate browser tasks, and capture screenshots with reliable workflows.

By the ScreenshotNeo team1 October 20268 min read

Direct answer: Install Node.js 18 or newer, register a Puppeteer MCP server with Claude Code, restart Claude Code, then ask it to navigate, interact with, inspect, or screenshot a page. The quickest macOS/Linux setup is:

curl -fsSL https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.sh | bash

On Windows PowerShell:

iwr -useb https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.ps1 | iex

The installer adds the community puppeteer-mcp-claude package and registers it for Claude Code. The first installation normally downloads Chromium, approximately 170 MB according to the project README. [Puppeteer MCP README]

What Puppeteer MCP adds to Claude Code

MCP (Model Context Protocol) connects an AI application to external tools. [MCP documentation] Puppeteer is a JavaScript library for controlling Chrome or Firefox through the DevTools Protocol or WebDriver BiDi, and it runs headless by default. [Puppeteer documentation]

With a Puppeteer MCP server, Claude Code can use a real browser to:

  • Navigate to URLs.
  • Click links, buttons, and other elements.
  • Type into forms.
  • Wait for selectors or page state.
  • Read visible text.
  • Run JavaScript in the page.
  • Manage cookies.
  • Intercept requests and block selected resources.
  • Capture screenshots.

The browser launches automatically with defaults when Claude first uses a browser tool. An explicit launch is useful when you need a custom viewport, proxy, stealth mode, or an existing Chrome WebSocket endpoint.

Prerequisites

  1. Node.js 18 or newer. Verify it with node --version.
  2. Claude Code or another MCP-aware client.
  3. Network access for npm and the initial Chromium download.
  4. Enough disk space for the browser binary and npm package.
node --version
npm --version
claude --version

If Node is older than 18, install a current LTS release before running the MCP installer.

Install on macOS or Linux

Option 1: quick installer

curl -fsSL https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.sh | bash

The script checks Node, installs the package globally, and registers the server with Claude Code at user scope. To register it for the current project instead, set SCOPE=project:

SCOPE=project bash -c "$(curl -fsSL https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.sh)"

Option 2: manual npm installation

npm install -g puppeteer-mcp-claude
claude mcp add puppeteer-mcp-claude -- npx -y puppeteer-mcp-claude serve

Restart Claude Code after registration so it reloads the MCP server list.

Install on Windows

PowerShell quick installer

iwr -useb https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.ps1 | iex

For project scope, set the environment variable before running the script:

$env:SCOPE='project'
iwr -useb https://raw.githubusercontent.com/jaenster/puppeteer-mcp-claude/main/install.ps1 | iex

Restart Claude Code when the script finishes.

Verify the server

Use a simple browser request in Claude Code:

Take a screenshot of https://example.com

If the server is available, Claude should invoke the Puppeteer tools and return a screenshot. You can also ask for a visible action sequence:

Open https://example.com, read the page title, click the first link, wait for navigation, and take a screenshot.

The exact tool names exposed by the community server include puppeteer_navigate, puppeteer_click, puppeteer_type, puppeteer_wait_for_selector, puppeteer_get_text, puppeteer_evaluate, and puppeteer_screenshot.

A dependable browser workflow

  1. Navigate. Ask Claude to use puppeteer_navigate with the complete URL.
  2. Wait for state. Use puppeteer_wait_for_selector for content that appears after JavaScript runs.
  3. Interact. Use puppeteer_click and puppeteer_type. Describe the selector or visible target precisely.
  4. Inspect. Use puppeteer_get_text for visible content or puppeteer_evaluate for page JavaScript.
  5. Capture evidence. Use puppeteer_screenshot only after the page reaches the intended state.

A useful prompt gives Claude a stopping condition:

Navigate to https://example.com/login. Wait for the email field, type the test account, click Sign in, wait for the dashboard heading, then capture a screenshot. Do not submit if the heading does not appear.

Launch options and existing Chrome sessions

For ordinary use, the server’s automatic browser launch is sufficient. Use puppeteer_launch when you need:

  • A custom viewport.
  • A proxy.
  • Stealth mode.
  • An existing Chrome browser endpoint.

To reuse an already authenticated Chrome session, start Chrome through the server helper:

puppeteer-mcp-claude chrome 9222

Then launch with:

browserWSEndpoint: "ws://localhost:9222"

This lets Puppeteer connect to the existing browser profile and preserve its authenticated session. Treat that session as sensitive: browser cookies grant access to the accounts open in Chrome.

Speed up scraping with request interception

If you only need text or a small screenshot, request interception can block images, media, fonts, or stylesheets before navigation. This reduces downloaded data and can make pages reach their usable state sooner. Keep stylesheets and images enabled when visual fidelity matters; blocking them changes layout and screenshot output.

Manual screenshot example with Puppeteer

The MCP workflow is driven by Claude prompts, but the equivalent direct Puppeteer operation looks like this:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900 });
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'example.png', fullPage: true });
await browser.close();

This code is separate from MCP: MCP gives Claude a tool interface, while Puppeteer remains the browser automation library underneath.

Alternative implementation: @modelcontextprotocol/server-puppeteer

@modelcontextprotocol/server-puppeteer is another Puppeteer MCP implementation. Its documentation describes navigation, screenshots, clicking, hovering, form filling, JavaScript evaluation, console logs, and configurable launch options. It provides both an npx configuration and a Docker configuration using headless Chromium. [Server documentation]

When choosing between implementations, compare installation method (npm/npx versus Docker), headless or visible browser mode, available tools, launch-option control, session reuse, and maintenance/version freshness.

Or skip the browser setup

If your goal is a clean screenshot rather than interactive browser control, ScreenshotNeo provides a single GET request. It removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for the complete option set.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);

ScreenshotNeo also supports full-page capture with lazy images loaded, CSS element capture, dark mode, 12 device presets and custom viewports, retina scale, PDF output, custom CSS and JavaScript, clicks before capture, selector hiding, selector or network-idle waits, request blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work to ease migration.

An MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Plans include 1,000 shots per month free with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.

Troubleshooting

Chromium is missing after npm install

Cause: npm, pnpm, Yarn, Bun, or Deno may block dependency install scripts, so Puppeteer’s browser download is skipped.

Fix:

npx puppeteer browsers install

Alternatively, configure your package manager to allow Puppeteer’s install script. [Puppeteer installation guide]

The MCP server does not appear in Claude Code

Cause: registration used a different scope, the command failed, or Claude Code has not reloaded its configuration.

Fix: rerun:

claude mcp add puppeteer-mcp-claude -- npx -y puppeteer-mcp-claude serve

Confirm whether you intended user or project scope, then restart Claude Code.

The browser starts but the page is blank

Possible causes: the page has not finished rendering, JavaScript failed, a bot check appeared, or the site requires authentication.

Fix: wait for a meaningful selector, inspect text with puppeteer_get_text, and capture console or page state with puppeteer_evaluate. For authenticated pages, connect to an existing Chrome session or provide the required login flow.

Clicks or typing fail

Cause: the selector is ambiguous, the element is outside the viewport, an overlay covers it, or the page replaced the element after navigation.

Fix: wait for the selector again, identify a unique CSS selector, scroll to the element, and inspect visible text before interacting.

Cause: the site has slow third-party resources, never reaches the requested load condition, or blocks automation.

Fix: wait for a page-specific selector instead of relying only on network idle, block unnecessary resource types, and check whether the site requires a proxy or authenticated session.

Screenshot layout is inconsistent

Cause: viewport, fonts, animations, lazy content, or network timing differs between runs.

Fix: set a fixed viewport, wait for the final selector, disable or wait for animations where appropriate, and ensure fonts and stylesheets are not blocked.

Performance, reliability, and cost notes

  • Installation cost: budget for the approximately 170 MB Chromium download and local disk space.
  • Runtime speed: reuse a browser session for multiple actions, block resources you do not need, and wait for a precise selector rather than an unnecessarily broad network-idle condition.
  • Reliability: make prompts and scripts state explicit selectors and completion conditions. Retry navigation only when the failure is transient; repeated retries can duplicate form submissions.
  • Authentication: reuse a controlled Chrome endpoint when a session must persist, and avoid exposing its WebSocket endpoint outside the local machine.
  • Screenshot billing: ScreenshotNeo bills only clean shots; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Use the verdict headers to classify responses.
  • Bulk work: ScreenshotNeo supports up to 100 URLs per bulk call and asynchronous jobs with signed webhooks when a synchronous browser session is not necessary.

FAQ

Does Puppeteer MCP require a visible Chrome window?

No. Puppeteer runs headless by default. Launch a visible browser only when debugging or when your chosen launch configuration requires it.

Can I use an existing logged-in browser?

Yes. Start the helper on port 9222 and connect with browserWSEndpoint: "ws://localhost:9222".

Is MCP the same thing as Puppeteer?

No. Puppeteer controls the browser; MCP supplies a standard tool connection that lets Claude Code call that browser.

When should I use ScreenshotNeo instead?

Use ScreenshotNeo when you need dependable screenshots or PDFs through an API, especially when consent banners, popups, chat widgets, failed loads, or AI-agent access matter more than interactive browser control. Sign up free for 1,000 screenshots each month with no card.