Chrome DevTools for Agents

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Chrome DevTools for agents is the Chrome team’s answer to a specific question: what does a coding agent need in order to see what a developer sees in DevTools? Its package, chrome-devtools-mcp, is a Model Context Protocol (MCP) server and a command line tool that give an agent control of, and visibility into, a live Chrome browser. Where Playwright MCP & CLI is built for driving a page the way a test does (accessibility snapshot in, action out), this server is built for the other half of the job: reading the console and the network log, recording a performance trace, running a Lighthouse audit, emulating a phone on a slow network, and taking a heap snapshot. It drives the page too, through Puppeteer, so the same session can reproduce a bug and then inspect it.

This page was checked on 25 October 2026. The version at that date was chrome-devtools-mcp 1.12.0 (the 1.x line, released as stable on 19 May 2026; the first public preview was announced in 2025), Apache-2.0 licensed, run against Google Chrome 155. The surrounding baseline of the section is Playwright 1.64, Cypress 16.2 and Selenium 4.51. The examples were run against the Bookshelf example application, served locally. They were run through the real server, started with the same command and flags shown below, but the tool calls were issued one at a time by the model that wrote this page through a small stdio MCP client, reading each result before choosing the next call, which is the observe-and-act loop an agent runs; no agent product (Claude Code or another) produced them. How an agent loop works is covered in Agent Loop & Architectures and the protocol in MCP Architecture; how browser agents work in general is in How AI Agents Drive Browsers.

What it is and how it works

The server speaks MCP over standard input and output (the stdio transport, see MCP Transports). The client starts it as a child process; the server then launches Chrome, or connects to one that is already running, over the Chrome DevTools Protocol (CDP, see How Browser Automation Works). Three libraries do the work:

  • Puppeteer automates the page: navigation, clicks, typing, waiting for the result of each action.

  • The DevTools frontend code turns raw trace events into insights (for example "LCP breakdown") and formats console messages with source-mapped stack traces.

  • Lighthouse runs the audits.

Two details shape how an agent uses it. First, the server does not start the browser when the client connects; Chrome starts the first time a tool that needs a browser is called. Second, elements are addressed by uid values taken from a text snapshot of the accessibility tree (take_snapshot), exactly as with Playwright MCP’s refs, so the page is described to the model as text rather than pixels. Coordinate clicks (click_at) exist only behind --experimentalVision.

Officially supported browsers are Google Chrome and Chrome for Testing. Other Chromium-based browsers may work but are not guaranteed. There is no Firefox or Safari support, because the server is CDP-only; that matters when choosing it (see When to choose it over Playwright MCP).

Installing it

The requirements are a current Node.js LTS, npm and the current stable Chrome. The official configuration works in any MCP client that accepts a command and args:

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "chrome-devtools-mcp@latest"]
    }
  }
}

Using @latest means the client picks up each new release on its next start, which also means behaviour can change under you; pin a version (chrome-devtools-mcp@1.12.0) in shared configuration and in CI.

For Claude Code, the project documents a one-line command that registers the server for the current user in every project:

claude mcp add chrome-devtools --scope user npx chrome-devtools-mcp@latest

--scope user is the Claude Code scope that stores the entry in the user’s own configuration; use --scope project to write it to a .mcp.json file that is committed and shared with the team (see Connecting MCP Hosts). This exact command was taken from the project documentation and was not executed here, because it changes the configuration of the Claude Code installation on the machine; the server command it registers was run directly, as shown below. Arguments such as --headless go after the package name:

claude mcp add chrome-devtools --scope project npx chrome-devtools-mcp@latest --headless --isolated --no-usage-statistics

The same package can also be installed as a Claude Code plugin that bundles the server and a set of skills: run /plugin marketplace add ChromeDevTools/chrome-devtools-mcp, then /plugin install chrome-devtools-mcp@chrome-devtools-plugins, and restart Claude Code. The plugin route was not run here either. The bundled skills (chrome-devtools, chrome-devtools-cli, a11y-debugging, cookie-debugging, debug-optimize-lcp, memory-leak-debugging and troubleshooting) describe the tools of one specific version, so update them whenever the server is updated, otherwise the agent may be told to use parameters that no longer exist. For Gemini CLI the project documents gemini extensions install --auto-update https://github.com/ChromeDevTools/chrome-devtools-mcp, and for Copilot in VS Code the Chat: Install Plugin From Source command.

A first smoke test, from the README, is the prompt Check the performance of https://developers.chrome.com; the client should open a browser and record a trace.

The command line interface

The package also ships a chrome-devtools command that exposes the same tools to a shell, without MCP. It keeps a background server between commands, so a script can chain calls and the agent pays for one shell command rather than for many tool definitions in its context:

npm i chrome-devtools-mcp@latest -g
chrome-devtools navigate_page 1 --url "https://developers.chrome.com"
chrome-devtools take_screenshot 1 --filePath screenshot.png
chrome-devtools stop

The chrome-devtools --help listing of the installed 1.12.0 package was read and shows the same tool names as commands (start, status and stop manage the background server); the example above is from the README and was not run.

Launching and connecting

The flags below are the ones that decide how the browser is obtained. The complete list is in the configuration guide and npx chrome-devtools-mcp@latest --help; every flag also exists in a JSON configuration file.

Flag Effect

(none)

Launch Chrome stable with a persistent profile in $HOME/.cache/chrome-devtools-mcp/chrome-profile. The profile is kept between runs, so cookies and logins survive; only one browser can use it at a time.

--headless

Run Chrome without a window. Default is headed.

--isolated

Use a temporary user data directory that is deleted when the browser closes. Gives every run a clean state and lets several servers run side by side.

--userDataDir

Use a specific profile directory.

--channel

stable (default), beta, dev or canary.

--executablePath

Use a particular Chrome or Chrome for Testing binary.

--viewport

Initial viewport such as 1280x720 (headless maximum 3840x2160).

--autoConnect

Connect to a Chrome you already started instead of launching one (Chrome 144 or later).

--browserUrl

Connect to a Chrome started with a remote debugging port, for example http://127.0.0.1:9222.

--wsEndpoint and --wsHeaders

Connect over a WebSocket, optionally with custom headers for authentication.

--slim

Expose only three tools (navigate, evaluate, screenshot) for basic browser tasks.

--chromeArg and --proxyServer

Extra Chrome arguments and a proxy; only when the server launches Chrome.

--acceptInsecureCerts

Ignore certificate errors (self-signed or expired certificates). Use with caution.

--config and --watchConfig

Read options from a JSON file and apply changes without restarting.

Headless and isolated: the test-friendly mode

For repeatable work, such as an agent that verifies a change, use --headless --isolated. Without --isolated the default profile is shared by every server instance and reused between runs, which is convenient for staying signed in and harmful for reproducing a bug that depends on a clean state. The configuration used for every run on this page was:

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": [
        "chrome-devtools-mcp@1.12.0",
        "--headless",
        "--isolated",
        "--no-usage-statistics",
        "--no-performance-crux"
      ]
    }
  }
}

(The runs started the locally installed chrome-devtools-mcp binary of that version with the same four flags, rather than through npx.) The two --no- flags are explained under Privacy: usage statistics and field data.

Connecting to the browser you are using

By default the agent gets its own Chrome with its own profile. That is the wrong shape in three situations: when a page needs a login that a controlled browser may be refused, when you want to switch between testing by hand and testing by an agent in the same state, and when the agent runs in a sandbox but Chrome runs outside it. Two ways of connecting exist.

Automatic connection (--autoConnect, Chrome 144 or later) targets the Chrome you already have open. Open chrome://inspect/#remote-debugging once to enable remote debugging, then configure the server:

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["chrome-devtools-mcp@latest", "--autoConnect"]
    }
  }
}

Chrome has to be running already (the flag never launches it). Each time the server asks for a debugging session Chrome shows a permission dialog and the session starts only when you click Allow; while it is active Chrome shows a banner that it is being controlled by automated test software. With several profiles the server uses the default one, and it can see all open windows of that profile. Before 144 reached the stable channel the Chrome team’s announcement also needed --channel=beta; with --channel the server looks for the browser of that channel.

Manual connection (--browserUrl) targets a Chrome you started with a remote debugging port. Chrome requires a non-default user data directory when that port is enabled:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-profile-stable

and pass --browser-url=http://127.0.0.1:9222 to the server. The debugging port is open to every process on the machine, so any local application can control that browser; do not browse sensitive sites while it is enabled. Neither connection mode was run here: the automatic mode needs a person to click the Chrome permission dialog, and the manual mode needs a second Chrome instance on the host. Both are documented from the official guides.

When one server instance is shared by several agent sessions, --pageIdRouting (on by default) makes every page-scoped tool require a numeric pageId, so each session routes to its own tab. That is why every call in the examples below carries pageId. Pages are numbered from 1 in the order list_pages returns them, and new_page adds a page without closing the initial about:blank page, so the new tab has pageId 2; the first attempt to run the example in the next section on pageId 1 after new_page inspected the blank page and returned nothing, which is what an agent that does not re-read the list_pages result also experiences.

The tools

The 1.12.0 server exposed 32 tools in the default configuration. More are enabled by category flags, and the reference lists about sixty in total. They fall into groups:

Category Tools (default set) Notes

Input automation

click, drag, fill, fill_form, handle_dialog, hover, press_key, type_text, upload_file

Take a uid from the latest snapshot. includeSnapshot returns a fresh snapshot with the result. click_at (coordinates) needs --experimentalVision.

Navigation

list_pages, new_page, select_page, close_page, navigate_page, wait_for

navigate_page takes type (url, back, forward, reload), ignoreCache, timeout and an initScript.

Emulation

emulate, resize_page

One call sets network conditions, CPU throttling, geolocation, user agent, colour scheme, forced colours, contrast and reduced motion preferences, viewport and extra HTTP headers.

Performance

performance_start_trace, performance_stop_trace, performance_analyze_insight

Records a trace, summarises Core Web Vitals and returns named insights.

Network

list_network_requests, get_network_request

Filter by resourceTypes; fetch headers and bodies, or save them to files.

Debugging

list_console_messages, get_console_message, evaluate_script, get_css_styles, take_snapshot, take_screenshot, lighthouse_audit, screencast_start, screencast_stop, take_heapsnapshot

Console messages carry source-mapped stack traces on request (includeStackTraces).

The table was produced by listing the tools of the running 1.12.0 server (32 entries, including take_heapsnapshot, whose analysis companions are only enabled by --memoryDebugging). Opt-in categories add further tools: extensions (--categoryExtensions: install, list, reload, uninstall and trigger an extension action), Progressive Web Apps (--categoryPwa), WebAuthn virtual authenticators for passkey flows (--categoryWebauthn), and WebMCP and third-party developer tools exposed by the page itself (--categoryExperimentalWebmcp, --categoryExperimentalThirdParty; WebMCP needs a recent Chrome with --enable-features=WebMCP). Each category can be switched off, for instance --categoryPerformance=false, which also saves context tokens and removes capability the agent does not need. Tool definitions are part of every prompt, so a smaller list is cheaper and reduces wrong tool choices.

--slim goes furthest. A listing of the server started with it returned exactly three tools: navigate(url), evaluate(script) and screenshot(filePath). It suits an agent that only needs to load a page and read a value.

Reading console and network

The most common use of the server is the first thing a developer does in DevTools: load the page and look at the Console and Network panels. This sequence ran on the Bookshelf URL of a book that does not exist:

Prompt: Open http://localhost:3930/books/9999 and tell me whether the browser
logged any errors and what the page request returned.
>>> navigate_page {"pageId":1,"type":"url","url":"http://localhost:3930/books/9999"}
Successfully navigated to http://localhost:3930/books/9999.
## Pages
1: Not found - Bookshelf (http://localhost:3930/books/9999) [selected]

>>> list_console_messages {"pageId":1,"types":["error"]}
## Console messages
Showing 1-1 of 1 (Page 1 of 1).
msgid=1 [error] Failed to load resource: the server responded with a status of 404 (Not Found) (0 args)

>>> list_network_requests {"pageId":1,"resourceTypes":["document"]}
## Network requests
Showing 1-1 of 1 (Page 1 of 1).
reqid=1 GET http://localhost:3930/books/9999 [404]

>>> get_network_request {"pageId":1,"reqid":1}
## Request http://localhost:3930/books/9999
Status: 404
### Request Headers
- user-agent:Mozilla/5.0 (Macintosh; ...) HeadlessChrome/155.0.0.0 Safari/537.36
...
### Response Headers
- content-type:text/html; charset=utf-8
...
### Response Body
<!doctype html><html lang="en"> ...
<main id="main"><h1 data-testid="not-found">Book not found</h1></main> ...

>>> evaluate_script {"pageId":1,"function":"() => ({ title: document.title, h1: document.querySelector(\"h1\")?.textContent })"}
Script ran on page and returned:
{"title":"Not found - Bookshelf","h1":"Book not found"}

(The prompt is the one the sequence answers; the calls were issued by hand, as described in the introduction, and the output is trimmed with ....) Three points matter for how an agent should use these tools. The console list reports messages by msgid and the network list by reqid, and the detail tools take those ids, which keeps the first listing short; pageSize and pageIdx paginate large logs. The server keeps console messages and requests for the last three navigations of each page (--maxNavigationSaved, from 1 to 25), so an error logged before an earlier reload is reachable only with includePreservedMessages or includePreservedRequests. And headers can contain secrets: pass --redactNetworkHeaders when the transcript will be stored or shared.

The same server also answers the question that Playwright MCP covers with browser_console_messages and browser_network_requests; the difference is that here the stack traces are source-mapped (a minified bundle error points to the original file) and a request’s body and headers can be written to a file with requestFilePath and responseFilePath for tools that should not read them inline.

Performance traces and Web Vitals

performance_start_trace records a DevTools performance trace. With reload: true it reloads the page first, and with autoStop: true it stops by itself after the page load, so a single call returns the analysis. Without autoStop the agent interacts with the page and calls performance_stop_trace. filePath saves the raw trace (a .json or .json.gz file you can open in the DevTools Performance panel later). On Bookshelf:

Prompt: Reload http://localhost:3930/books/1 with a performance trace and report
the Core Web Vitals and where the LCP time goes.
>>> performance_start_trace {"pageId":1,"reload":true,"autoStop":true}
The performance trace has been stopped.
## Summary of Performance trace findings:
URL: http://localhost:3971/books/1
CPU throttling: 1x
Network throttling: none

## insight set id: NAVIGATION_0
Metrics (lab / observed):
  - LCP: 188 ms, event: (eventKey: r-2317, ...), nodeId: 5
  - LCP breakdown:
    - TTFB: 0.8 ms
    - Load delay: 2 ms
    - Load duration: 1 ms
    - Render delay: 184 ms
  - CLS: 0.00
Metrics (field / real users): n/a - no data for this page in CrUX
Available insights:
  - insight name: LCPBreakdown
  - insight name: LCPDiscovery
  - insight name: RenderBlocking
  - insight name: NetworkDependencyTree
  - insight name: DocumentLatency
  - insight name: Cache
    estimated wasted bytes: 6.5 kB
  ...

>>> performance_analyze_insight {"pageId":1,"insightSetId":"NAVIGATION_0","insightName":"LCPBreakdown"}
...
- Element render delay: 184 ms (97.7% of total LCP time)
## Estimated savings: none
## External resources:
- https://developer.chrome.com/docs/performance/insights/lcp-breakdown
- https://web.dev/articles/lcp

This run used port 3971 for Bookshelf (a different local port from the sequence above) and was trimmed. The numbers belong to a tiny local page with no throttling; they show how to read the output, not a performance budget. The reading is the useful part: of 188 ms of LCP, 184 ms is render delay, the time between the resource being loaded and the element being painted, not network time. An agent that is told "optimise LCP" would otherwise guess at images.

The summary has three kinds of data. Lab metrics (LCP, CLS and, with interaction, INP) come from the trace itself. Field metrics come from the Chrome User Experience Report (CrUX), real-user data collected by Chrome, which the tool fetches for the page URL or origin so lab and field numbers appear side by side; for a localhost page there is none, hence the n/a line. Insights are named analyses (LCP breakdown, render-blocking requests, network dependency tree, document latency, cache use and others) that the agent can drill into with performance_analyze_insight.

A trace gets very large, so the tool returns a summary and the agent asks for details. A file path outside the allowed directories is refused: a filePath outside the configured roots returns Access denied: path ... is not within any of the configured workspace roots. When the MCP client does not offer the MCP "roots" capability the server limits file-reading and file-writing tools to the operating system temporary directory; add --filesystemRoot <dir> (also written --workspace) for each directory the agent may use, or --allowUnrestrictedPaths to remove the restriction, which should be a deliberate decision.

Throttling matters because a fast development machine hides what users on phones see. Combine the trace with emulate (next section) before recording, and the summary header then reports "CPU throttling: 4x" and the network preset.

Emulation

emulate replaces all emulation settings on a page in one call, except extra HTTP headers; pass every setting you want every time. Settings survive navigations in the same page, as the next run shows:

>>> emulate {"pageId":1,"colorScheme":"dark","viewport":"375x812x2,mobile,touch","networkConditions":"Slow 3G","cpuThrottlingRate":4}
Emulation configured successfully
Emulating network conditions: Slow 3G
Default navigation timeout set to 400000 ms
Emulating viewport: {"deviceScaleFactor":2,"isMobile":true,"hasTouch":true,"isLandscape":false,"width":375,"height":812}
Emulating CPU throttling: 4x slowdown
Emulating color scheme: dark

>>> navigate_page {"pageId":1,"type":"url","url":"http://localhost:3971/books"}
Successfully navigated to http://localhost:3971/books.
Emulating network conditions: Slow 3G
...
>>> emulate {"pageId":1,"networkConditions":"No emulation","cpuThrottlingRate":1}
Input validation error: Invalid arguments for tool emulate: networkConditions: Invalid option: expected one of "Offline"|"Slow 3G"|"Fast 3G"|"Slow 4G"|"Fast 4G"

Two real behaviours are visible. The viewport is a compact string, <width>x<height>x<deviceScaleFactor> followed by optional mobile, touch and landscape flags. And networkConditions has no value meaning "none": in 1.12.0 the enumeration is Offline, Slow 3G, Fast 3G, Slow 4G and Fast 4G, so the instruction "turn throttling off" fails validation; the CPU rate is set back with cpuThrottlingRate: 1. The Lighthouse run in the next example shows the other consequence: the throttling stayed active, so it ran on the emulated phone. Reset by omitting networkConditions or by opening a fresh page. resize_page changes only the window size. Geolocation, userAgent, forcedColors, prefersContrast and prefersReducedMotion are further emulate parameters, useful for accessibility checks that the accessibility chapter automates with axe.

Lighthouse

lighthouse_audit runs Lighthouse against the selected page. mode is navigation (reloads the page) or snapshot (audits the current state, which suits a page in the middle of a flow), device is desktop or mobile, and outputDirPath saves the reports. It does not run the performance category, which is the job of the trace tools:

Prompt: Run a mobile Lighthouse audit on the catalogue page and list the failures.
>>> lighthouse_audit {"pageId":1,"mode":"navigation","device":"mobile"}
## Lighthouse audit results
Mode: navigation
Device: mobile
URL: http://localhost:3971/books
### Category scores
- Accessibility: 98 (accessibility)
- Best Practices: 100 (best-practices)
- SEO: 82 (seo)
- Agentic Browsing: 100 (agentic-browsing)
### Audit summary
Passed: 49
Failed: 3
### Failed audits
- heading-order [accessibility]: Heading elements are not in a sequentially-descending order (score: 0)
  Nodes (1):
  - selector="ul.grid > li.card > a > h3" label="The Quiet Compiler" snippet="<h3 data-testid=\"book-title\">"
- meta-description [seo]: Document does not have a meta description (score: 0)
- crawlable-anchors [seo]: Links are not crawlable (score: 0)
  - selector="body > main#main > nav.pager > a" label="Previous" snippet="<a aria-disabled=\"true\" data-testid=\"page-prev\" rel=\"prev\">"
### Reports
- <temp dir>/chrome-devtools-mcp-.../report.json
- <temp dir>/chrome-devtools-mcp-.../report.html

The audit found three real findings in Bookshelf: a heading level skipped (an h3 card title directly under the h1), no meta description, and a disabled "Previous" link that has no href. They are small, but each is specific enough that an agent can open the source and fix it. Note the fourth category, "Agentic Browsing": current Lighthouse versions include a category that checks how well a page can be used by browsing agents, and it scored 100 here. Whether the scoring of that category stays as it is will depend on later Lighthouse releases. Lighthouse’s own accessibility category is a subset of what axe-core finds, which is why the 98 above and a dedicated axe run in a test (see Accessibility Checks in E2E Tests) complement rather than replace each other.

Other debugging tools

  • take_snapshot returns the accessibility tree as text with uid values; verbose adds more detail and filePath saves it. On the missing-book page the snapshot was a short tree (heading "Book not found" level="1" under main), which is what an agent would click or read next.

  • take_screenshot returns an image of the page or of one element (uid), with format png, jpeg or webp, fullPage, and quality for the lossy formats. The server options --screenshotFormat, --screenshotMaxWidth and --screenshotMaxHeight set defaults that keep images small in the model’s context.

  • get_css_styles returns the computed and matched styles of an element.

  • screencast_start and screencast_stop record a video of the page.

  • take_heapsnapshot saves a V8 heap snapshot for memory-leak investigation; with --memoryDebugging further tools compare snapshots, list retainers and find duplicate strings. These tools and the screencast were listed but not run here.

Privacy: usage statistics and field data

Two defaults send data to Google, and both can be switched off with flags:

  • Usage statistics are collected by default: tool invocation success rates, latency and environment information, handled under the Google Privacy Policy and independent of Chrome’s own metrics. Opt out with --no-usage-statistics. Collection is also disabled when the environment variable CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS or CI is set.

  • CrUX lookups: the performance tools may send the URLs of a trace to the CrUX API to fetch field data. Opt out with --no-performance-crux. Both flags are on the command line of every run on this page, because the pages that were traced are local, and because a project that traces an internal URL should not send it anywhere.

  • Update checks: by default the server periodically checks the npm registry for a newer version and logs a notice; CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS disables it.

Security

The README’s disclaimer is blunt: the server exposes the content of the browser instance to the MCP client, allowing it to inspect, debug and modify any data in the browser or in DevTools. Everything the page shows, the model reads, so the page-content injection risk in Prompt Injection applies in full, and with --autoConnect the page can be your signed-in dashboard. Practical measures, all of them documented flags:

  • Prefer --isolated so a session has no stored logins, and never attach to the browser that holds your personal profile.

  • Restrict the network the browser can reach with --allowedUrlPattern (Chrome 149 or later) or --blockedUrlPattern.

  • --no-javascript-evaluation disables evaluate_script, the initScript option and navigation to javascript: and data: URLs; --no-file-navigations rejects file: URLs. The file option is not a filesystem sandbox.

  • Keep file-writing tools inside known directories (--filesystemRoot), and protect the JSON configuration file from the agent: it can set executablePath, chromeArg and the URL patterns, so an agent that can write it can lift the restrictions.

  • Use --redactNetworkHeaders when network output is stored.

  • Pair it with human approval of side effects (see Human in the Loop).

The tool-level threat model is in Excessive Agency & Tool Security, and the browser-agent view in Securing Browser Agents.

When to choose it over Playwright MCP

Question Chrome DevTools MCP Playwright MCP

Main purpose

Inspect and diagnose: performance, network, console, memory, Lighthouse

Drive and verify: a navigation and interaction loop that mirrors a test

Browsers

Chrome and Chrome for Testing only

Chromium, Firefox and WebKit

Page description

Accessibility tree with uid values

Accessibility snapshot with refs, and optional vision tools

Debugging depth

Traces with CrUX field data, insights, Lighthouse, heap snapshots, source-mapped console

Console, network, tracing and video (some behind capability flags)

Output toward a test

None; findings are for a person or for a fix

Verify tools generate expect() code; tracing and locator generation (see Playwright MCP & CLI)

Existing browser session

--autoConnect or --browserUrl

Extension mode or a CDP endpoint

Source: Playwright MCP

Choose Chrome DevTools MCP when the question is "why is this slow, broken or heavy": a regression in LCP, a console error that only appears on a throttled phone, a request that fails with a 4xx, a memory leak. Choose Playwright MCP, the Playwright CLI or the Playwright Test Agents when the output should become a test that runs in Chromium, Firefox and WebKit in CI. The two are not exclusive: nothing stops one agent from having both servers, reproducing a flow with one and profiling it with the other, at the price of both tool lists in the context. The tests that come out of the debugging session still belong in Playwright, Cypress or Selenium; see Choosing a Tool for that choice and Agents That Control the Browser for the wider field. A useful discipline is to put the agent’s findings into a numeric assertion, for example a Lighthouse threshold or an LCP budget, rather than leaving them in a chat transcript.

Pitfalls

  • Forgetting pageId. Every page-scoped tool requires it (unless --no-page-id-routing), and a wrong id inspects a different tab, such as the initial blank page.

  • Stale uid values. They belong to one snapshot; after navigation or a re-render take a new one.

  • Default profile. Without --isolated state leaks between runs and two servers cannot share the profile.

  • Throttling left on. emulate settings persist on the page; a later Lighthouse audit then measures the emulated device.

  • Context cost. The default tool list is long and snapshots can be large; use --slim or turn categories off, and save big outputs to files.

  • Version drift. @latest changes the tool set and parameters over time; pin versions in CI and keep installed skills in step.

  • Chrome only. A bug that appears only in Firefox or Safari cannot be reproduced here.

What changed recently

  • Chrome DevTools for agents 1.0 was announced as a stable release on 19 May 2026, adding Lighthouse audits, extension development tools, memory analysis, WebMCP support, third-party developer tools, a CLI and agent skills; the project now describes itself as "Chrome DevTools for agents" and the npm package is still chrome-devtools-mcp. The registry lists 1.12.0 as the latest version on 22 October 2026.

  • Auto-connect to a running Chrome (Chrome 144 or later) was introduced in December 2025.

  • The performance tools show CrUX field data beside lab data, with a --no-performance-crux opt-out, and usage statistics are on by default with a --no-usage-statistics opt-out.

  • The server restricts file tools to the operating system temporary directory unless roots, --filesystemRoot or --allowUnrestrictedPaths are configured, and pageId is mandatory on page-scoped tools by default.

  • Lighthouse includes an "Agentic Browsing" category in the audit run shown above.

  • Product details such as the number of tools, flags and defaults move quickly; the tool reference and --help of the installed version are authoritative. See also What’s Changed and Upgrading.