Playwright MCP Chrome Extension: What It Is and What to Use
If you searched for a "Playwright MCP Chrome extension," you are probably trying to give an AI agent control of a real browser. The naming is confusing, because there is no official Playwright-branded Chrome extension that does this. What exists is the Playwright MCP server — a Model Context Protocol server that exposes Playwright browser actions as tools an LLM can call — plus a set of ways to attach that server to Chrome, including a real Chrome extension that bridges your own logged-in browser session.
This post separates the three things people conflate: the MCP server, the Chrome extension bridge, and the underlying browser connection (CDP or a launched Chromium). Then it covers where each breaks down in production and how to move to a hosted runtime when you need sessions that survive past your laptop.
The short answer
- Playwright MCP is a server that lets an LLM drive a browser through Playwright. It is not a Chrome extension.
- The Chrome extension in this stack is a bridge. It lets the MCP server talk to a Chrome instance you already have open, using your existing profile and logins.
- The connection underneath is either a launched Chromium process or a CDP endpoint. That distinction determines whether your automation is reproducible or tied to one machine.
If you only need an agent to click around a site you are already logged into, the extension bridge is convenient. If you need agents that run on a schedule, in CI, or across many concurrent tasks, the extension is the wrong layer — you want a remote browser with a CDP endpoint.
What the Playwright MCP server actually does
MCP (Model Context Protocol) is a standard for exposing tools to LLM clients. A Playwright MCP server wraps Playwright's API — navigate, click, type, snapshot the accessibility tree, take screenshots — and publishes them as callable tools. The LLM client (Claude Desktop, an IDE agent, a custom harness) decides which tool to call; the server executes it against a browser.
Two design choices matter:
Accessibility-tree snapshots vs. screenshots. Most Playwright MCP implementations return a structured accessibility snapshot rather than pixels. That is cheaper for the model and more deterministic than vision-based clicking, but it means the agent sees the DOM's semantic structure, not the rendered page. Canvas apps, heavily styled widgets, and anything behind a shadow DOM boundary can be invisible to it.
Session lifetime. The server holds a browser context for the duration of the conversation. When the client disconnects, that context typically dies. There is no built-in persistence unless you configure a user data directory or connect to an external browser.
That last point is where the Chrome extension enters.
The Chrome extension bridge: what it solves
A plain Playwright MCP server launches its own Chromium. That browser has no cookies, no logins, no extensions, and a fresh fingerprint. For a lot of real tasks — checking an internal dashboard, operating a SaaS tool you pay for, testing a page behind auth — that is a blocker.
The extension bridge solves it by inverting the connection. Instead of the server launching a browser, the server connects to a browser you already have open. The extension runs inside that browser and relays CDP-level commands between the MCP server and the live tab.
What you get:
- Your existing cookies, sessions, and logged-in state
- Your real profile, including installed extensions
- The ability to watch the agent work in a tab you can see
- No separate browser download or install step
What you give up:
- Reproducibility. The browser state is whatever you happened to have open.
- Isolation. The agent shares a profile with your personal browsing.
- Concurrency. One extension, one browser, effectively one agent at a time.
- Headless operation. The browser has to be running, which usually means a desktop session.
For interactive, human-in-the-loop work, that trade is fine. For anything that runs unattended, it is not.
How the pieces connect: CDP is the common denominator
Whether you launch Chromium, attach to a running Chrome, or connect to a cloud browser, the wire protocol is the same: the Chrome DevTools Protocol. Playwright's connectOverCDP is the entry point.
import { chromium, Browser, BrowserContext, Page } from 'playwright';
type RemoteTarget = {
cdpUrl: string; // e.g. wss://<host>/cdp or http://127.0.0.1:9222
sessionId?: string; // provider-specific session handle
};
async function attach(target: RemoteTarget): Promise<{
browser: Browser;
context: BrowserContext;
page: Page;
}> {
const browser = await chromium.connectOverCDP(target.cdpUrl, {
timeout: 30_000,
});
// A remote browser usually exposes one persistent context.
// Reuse it so cookies and storage survive across calls.
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = context.pages()[0] ?? (await context.newPage());
// Fail fast if the endpoint is stale rather than hanging on the first action.
await page.goto('about:blank', { waitUntil: 'domcontentloaded' });
return { browser, context, page };
}
// Usage against a hosted endpoint:
// const { browser, page } = await attach({ cdpUrl: process.env.CDP_URL! });
// await page.goto('https://example.com');
// await browser.close(); // closes the client connection, not the remote session
Three details in that snippet are worth calling out, because they are where most connectOverCDP implementations go wrong:
-
connectOverCDPis Chromium-only. It does not work against Firefox or WebKit. If your test matrix includes those engines, you need a different connection strategy — Playwright's own browser server, not CDP. -
browser.close()semantics differ. On a CDP connection, closing the browser object disconnects the client. Whether the remote session terminates depends on the provider. Read the docs for your endpoint before assuming cleanup happened. -
Context reuse is not automatic.
browser.contexts()[0]is a convention, not a guarantee. Some providers return an empty array until you create a context. Handle both branches.
If you are comparing this to a locally launched browser, the relevant Playwright launch flags are in the browser launch options guide — --remote-debugging-port, --user-data-dir, and --headless are the ones that matter for attach-style workflows.
Comparison: extension bridge vs. launched Chromium vs. hosted runtime
| Dimension | Chrome extension bridge | Local launched Chromium | Hosted remote browser |
|---|---|---|---|
| Auth state | Your live profile | Fresh, or a seeded profile dir | Persistent profile per session |
| Isolation | None — shares your profile | Process-level | Session-level, per agent |
| Concurrency | ~1 agent | Limited by local RAM/CPU | Scales with the provider |
| Headless / CI | No (needs a desktop browser) | Yes | Yes |
| Reproducibility | Low | Medium | High (pinned image, fixed config) |
| Debugging | Watch the tab live | Trace files, video | Live viewer + traces |
| Setup cost | Install extension, run server | npx playwright install |
Paste a CDP URL |
| Best for | Interactive, logged-in tasks | Local dev, unit tests | Agents, CI, scheduled jobs |
The extension column is not "worse" — it is optimized for a different job. The mistake is using it for the job in the last row.
Where the extension approach breaks in production
Four failure modes show up repeatedly once you move past a demo:
Session death on disconnect. The MCP client closes, the browser context goes with it. Any multi-step task that spans a client restart loses its place. Persistent profiles fix this, but a local Chrome profile is not designed for programmatic lifecycle management.
No concurrency. One extension, one browser. Ten parallel agent tasks need ten browsers, which means ten desktop sessions. That does not fit on a CI runner.
State drift. Because the browser is your real one, its state changes underneath the agent — you close a tab, log out of a site, install an extension. The agent's assumptions go stale silently.
No resource controls. A runaway agent loop on a local browser consumes your machine. There is no per-session CPU, memory, or time budget to enforce.
None of these are fatal for interactive use. All of them are fatal for unattended workloads.
The production path: hosted Chromium with a CDP endpoint
The pattern that scales is the same one the extension uses — connect to an existing browser over CDP — except the browser is not on your desk. It is a hosted Chromium session with:
- A CDP endpoint you connect to with
connectOverCDP - A persistent profile so logins survive across sessions
- Session isolation so concurrent agents do not share cookies
- A live viewer for debugging without screen-sharing your desktop
- Configurable browser settings, including proxy routing, applied at session creation
- Usage controls so a stuck agent cannot burn budget indefinitely
The migration from an extension-based setup is mostly deleting code. You stop managing a local Chrome process and a bridge; you pass a CDP URL to the same Playwright client you already wrote.
// Before: local Chrome + extension bridge
// const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');
// After: hosted session, same client API
const browser = await chromium.connectOverCDP(process.env.CDP_URL!);
const context = browser.contexts()[0];
const page = context.pages()[0] ?? (await context.newPage());
await page.goto('https://app.example.com/dashboard');
await page.getByRole('button', { name: 'Export' }).click();
Everything downstream — locators, assertions, retries — is unchanged. That is the point of CDP as an interface: the browser's location is an implementation detail.
For a fuller treatment of the runtime model, see Remote Browser for AI agents and the remote web browser overview. If you are specifically wiring an agent harness rather than a test suite, remote control browser covers the control-plane side.
Choosing between them
Use the extension bridge when:
- The task requires a login you cannot or should not script
- A human is watching and may need to intervene
- You are prototyping and want to see the agent's actions in a real tab
- The workload is one-off and interactive
Use a hosted remote browser when:
- The workload runs unattended, on a schedule, or in CI
- You need more than one agent running at once
- Sessions must survive client restarts
- You need per-session resource limits and audit trails
- You want the same code path in dev and production
A reasonable migration is to prototype with the extension, then move to a CDP endpoint once the task definition stabilizes. The Playwright code barely changes; what changes is who owns the browser lifecycle.
Practical setup notes
A few things that save time regardless of which path you pick:
- Pin your Playwright version. CDP compatibility drifts between Playwright releases and Chrome versions. A version bump in CI that silently changes attach behavior is a bad afternoon.
- Set an explicit connect timeout. The default can hang for a long time on a dead endpoint. Thirty seconds is generous.
-
Health-check before the first real action. A
goto('about:blank')costs nothing and fails fast on a stale session. - Log the session ID. When something goes wrong at 3 a.m., the session handle is the first thing you will want.
-
Do not assume
browser.close()kills the remote session. Verify against your provider's docs, and use an explicit session-terminate call if one exists.
Current session limits, concurrency, and pricing for hosted sessions are on the pricing page. The documentation covers CDP connection details, profile persistence, and the live viewer.
Bottom line
There is no Playwright MCP Chrome extension in the sense most people mean. There is an MCP server, and there is an extension that bridges it to your own browser. That combination is genuinely useful for interactive, logged-in work — and genuinely wrong for anything that needs to run unattended, concurrently, or reproducibly.
The underlying connection is CDP either way. Once you internalize that, the decision stops being about extensions and starts being about where the browser lives. For production agent workloads, that answer is usually a hosted session with a persistent profile and a CDP URL you can paste into the Playwright client you already have.
Top comments (0)