
The short answer: Playwright's current documentation says MCP has a higher context cost because tool schemas and snapshots enter the conversation, while the CLI is the lower-cost fit for coding agents because it uses concise shell commands and loads skills on demand. It does not promise a universal percentage. Historical community tests reported roughly 4x differences on two specific tasks, but those figures are not an official benchmark and should not be used as a budget forecast.
Playwright CLI can also use persistent or explicitly configured authentication state.
A Reddit user summed up the Playwright MCP experience in one line: after just one or two browser tests, Claude Code's chat gets compacted because the context is full.
That report is consistent with a known trade-off in snapshot-heavy workflows. Playwright MCP is a protocol server that commonly returns structured accessibility information after browser actions, and on real pages those responses can be large.
What does Playwright officially say about MCP vs CLI?
Playwright's current MCP documentation makes the product boundary explicit: MCP is best for specialized agentic loops and exploratory automation, while the CLI is best for coding agents working with large codebases. The same comparison labels MCP token cost as higher because tool schemas and snapshots enter context, and CLI cost as lower because its output is concise and skills load on demand.
Read the current official MCP comparison as a decision rule, not a benchmark result. It does not publish a fixed multiplier, and current MCP and CLI releases have controls that older comparisons did not evaluate. Page shape, enabled tools, snapshot strategy, client behavior, and the number of actions all change the bill.
Two historical community measurements point in the same direction. One article cited 114K tokens for an MCP run against 27K for CLI, then reported about 89K versus 24K in a separate 8-step login-and-dashboard test. The tasks, versions, model clients, and measurement methods were not standardized, so compare only within each pair.
A test engineer on Medium then ran his own side-by-side on an 8-step task (log in to a staging app, open an analytics dashboard, verify three KPI cards, click into a report, screenshot) and landed at about 89K tokens over MCP vs 24K over the CLI.
Historical community token measurements
Two task-specific comparisons, not an official Playwright benchmark
Both pairs were near 4x in that article. The only durable conclusion is directional: the interface and evidence strategy can materially affect context use. Measure the release and page shapes you actually run.
Where do MCP tokens actually go?
The historical 8-step measurement is useful because it itemizes one bill. Its values describe that setup, not current Playwright defaults or every MCP client.
First, the reported fixed cost: that MCP client loaded two dozen-plus tool schemas, measured at about 4,200 tokens, while its CLI path used a 68-token help read. Tool discovery and caching differ by client and release, so these are not package constants.
Second, the reported per-step cost: the tested flow returned accessibility trees after actions. The author measured about 3,800 tokens for a login form and 12,000 for a dashboard, then noted larger enterprise pages. Current Playwright MCP can search a snapshot with browser_find, write a snapshot to a file, limit its depth, or set snapshot mode to none. Those controls can materially change the result.
The current official MCP command reference describes browser_find as cheaper than returning a whole snapshot when the target text is known. That is now the first optimization to try before disabling snapshots entirely.
We measured this ourselves in August 2026, on a different MCP server built on the same accessibility-snapshot pattern (Chrome DevTools MCP, not Playwright MCP, since that's the one we had a live harness for), to see the actual byte cost of a single snapshot call with our own eyes. One take_snapshot call on a moderately simple page, Hacker News's front page, came back at 38,285 characters, roughly 9-10K tokens, for one snapshot:
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
params = StdioServerParameters(
command="npx",
args=["--yes", "chrome-devtools-mcp@latest", "--headless", "--isolated"],
)
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
nav = await session.call_tool("navigate_page", {"url": "https://news.ycombinator.com/"})
print("navigate_page chars:", len("".join(c.text for c in nav.content if hasattr(c, "text"))))
snap = await session.call_tool("take_snapshot", {})
snap_text = "".join(c.text for c in snap.content if hasattr(c, "text"))
print("take_snapshot chars:", len(snap_text))
print(snap_text[:700])
asyncio.run(main())navigate_page chars: 123
take_snapshot chars: 38285
## Latest page snapshot
uid=1_0 RootWebArea "Hacker News" url="https://news.ycombinator.com/"
uid=1_1 link url="https://news.ycombinator.com/"
uid=1_2 link "Hacker News" url="https://news.ycombinator.com/news"
uid=1_3 StaticText "Hacker News"
uid=1_4 link "new" url="https://news.ycombinator.com/newest"
uid=1_5 StaticText "new"
uid=1_6 StaticText " | "
uid=1_7 link "past" url="https://news.ycombinator.com/front"
uid=1_8 StaticText "past"
uid=1_9 StaticText " | "
uid=1_10 link "comments" url="https://news.ycombinator.com/newcomments"
uid=1_11 StaticText "comments"
uid=1_12 StaticText " | "
uid=1_13 link "ask" url="https://news.ycombinator.com/ask"
...A historical issue shows how release changes matter. Issue #889 on the microsoft/playwright-mcp repo reported token usage multiplying 6x between two minor versions for the same task and requested a verbosity setting. The issue is closed, and current releases expose more targeted snapshot controls. Use it as historical evidence for version-sensitive measurement, not as a description of today's default behavior.
The context meter can grow with repeated observations.

Why does the gap grow with every step?
Short tasks may show little practical difference. The gap can open on multi-step work when full MCP snapshots accumulate in the conversation while CLI artifacts stay on disk and the agent reads only a narrow slice. It can also shrink when MCP uses browser_find or depth-limited snapshots, or when a CLI agent reads every artifact back into context.
In the community author's measured session, the agent reportedly carried 60-90K tokens of page state by step 12-15 and then referenced an element from an earlier page. The author's CLI workflow wrote snapshots to disk and read only selected output. This is one historical failure mode, not a threshold Playwright guarantees.
How context tokens pile up across a multi-step task
MCP commonly returns page observations per step; the CLI writes artifacts to files and can read back only what it needs
That workaround is worth pausing on. When users independently converge on "make the agent write code instead of calling MCP tools," they are choosing a file- and shell-oriented route similar to the CLI.
When is Playwright MCP still the right choice?
A fair comparison has to state what MCP does better, because there are real cases where it's the correct pick despite the token bill.
| Situation | Better route | Why |
|---|---|---|
| Agent has no shell or filesystem access (Claude Desktop, sandboxed clients) | MCP | The CLI can't run without a shell. MCP works over the protocol alone. |
| Short exploratory session, under ~10 steps | MCP | Zero-code setup, and full page structure in context helps the model reason about unfamiliar pages. |
| Agent that can't write code (pure conversational agent) | MCP | Tool calls may be the practical interface; CLI assumes shell and file access. |
| Long tasks, 15+ steps, or browser work mixed with coding | CLI | Snapshot accumulation can pressure long MCP sessions; CLI context can stay smaller when artifacts are read selectively. |
| Cost-sensitive workloads at scale | CLI | A roughly 4x context-token reduction can reduce model input cost for the browser portion, but the invoice also depends on model pricing, output tokens, retries, and the workload. |
| Tasks behind logins on your own accounts | Both, with explicit setup | CLI can persist a profile, load storage state, attach through the Playwright extension, or attach to Chrome/Edge over CDP. MCP supports persistent or isolated profiles, storage state, and its browser extension. Each route requires deliberate authorization and profile handling. |
MCP's honest pitch is convenience and compatibility: one config line, and many MCP-capable clients can use it without code skills. That convenience can be worthwhile for short tasks; measure the context cost before using it for long workflows.
What does the CLI route require?

The official CLI is @playwright/cli, shipped by the Playwright team for exactly this problem. Setup is two commands:
npm install -g @playwright/cli@latest
playwright-cli install --skills # installs agent skills for Claude Code / Copilot
playwright-cli open https://example.com
playwright-cli snapshot # refs like e15, saved to disk
playwright-cli click e15The key gate is shell and file access: the agent must be able to run commands, read files, and compose scripts. Claude Code, Codex, Cursor, and Copilot can do this when configured with those permissions; a chat-only client may need an MCP-capable integration instead. The current official CLI README and npm package require Node.js 18 or newer.
How do you use Playwright CLI with OpenCode?
OpenCode can use the official Playwright CLI as a shell-accessible skill. Install the CLI, install its skills when your agent supports them, then tell OpenCode to run playwright-cli commands; there is no Playwright MCP server to register for this route. The minimal setup is:
npm install -g @playwright/cli@latest
playwright-cli install --skills
playwright-cli open https://example.com
playwright-cli snapshot
playwright-cli click e15If your OpenCode setup does not load skills automatically, give it the same command contract explicitly: ask it to check playwright-cli --help, run a snapshot before using a ref, and read output files only when it needs them. The CLI keeps cookies for the current in-memory session; add --persistent when you need the profile to survive a browser restart, or use -s=project-name to keep separate sessions.
If you specifically want Playwright MCP inside OpenCode, that is a separate configuration. The official Playwright MCP README documents a local server entry like this:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"playwright": {
"type": "local",
"command": ["npx", "@playwright/mcp@latest"],
"enabled": true
}
}
}There is a separate profile trade-off: the CLI launches its own browser profile unless you configure persistence or attach to an existing browser. A fresh profile has no cookies or sessions. When a task sits behind a login wall, use an approved login flow, persistent profile, or storage state rather than copying credentials into prompts.
Can the CLI use an existing logged-in browser?

Yes. The current Playwright CLI can attach through the Playwright Chrome extension, attach to a running Chrome or Edge channel over CDP, or connect to a CDP endpoint. Its default session keeps cookies in memory until the browser closes; --persistent or --profile keeps state on disk. Treat an attached personal profile as sensitive access: approve the connection intentionally and use a task-specific profile when possible.
The official session-management reference documents named sessions, persistent profiles, extension attachment, and CDP attachment. The browser must explicitly allow remote debugging for CDP attachment.
ego (lite) is one login-aware route among several, not the only one. It is itself the browser, so an agent drives it directly, with no extension to install and no remote debugging port left open. Session expiry, MFA, account permissions, and site policy still apply.
The token model goes one step past the Playwright CLI. Instead of one shell command per action, the agent writes a short JavaScript program and pipes it in as a heredoc. The whole multi-step workflow (open, wait, extract, loop) executes outside the model, in one round, and only the final result comes back into context:
ego-browser nodejs <<'EOF'
const task = await taskSpace("article release QA")
const page = task.page("p1")
await page.goto("http://127.0.0.1:3013/article/playwright-mcp-vs-cli")
await page.waitForSelector("loc=css:article", { state: "visible" })
await page.cdp("Emulation.setDeviceMetricsOverride", {
width: 390, height: 844, deviceScaleFactor: 1, mobile: true
})
const result = await page.evaluate(() => ({
h1Count: document.querySelectorAll("h1").length,
horizontalOverflow: document.documentElement.scrollWidth > innerWidth,
failedImages: [...document.querySelectorAll("article img")]
.filter(img => img.complete && img.naturalWidth === 0).length,
missingAlt: [...document.querySelectorAll("article img")]
.filter(img => !img.getAttribute("alt")?.trim()).length
}))
console.log(JSON.stringify(result))
EOF# observed on September 10, 2026:
{"h1Count":1,"horizontalOverflow":false,"failedImages":0,"missingAlt":0}That wasn't a toy extraction. We kept eight article pages open in one Space, checked desktop and 390-pixel mobile layouts, validated language tags, canonicals, heading order, image loads, alt text, anchor targets, code overflow, and horizontal overflow, then clicked the article outline and verified the target heading entered the viewport. The localized pages and all three English pages passed the tested checks.
When the authorized profile import is accepted by the target site, the agent can reuse that state instead of scripting a fresh login. Session expiry, MFA, and site policy can still interrupt the flow. In our published heredoc-vs-REPL benchmark, batching work this way finished the same tasks in 44% fewer execution rounds with 35.5% fewer tool calls at 21.6% lower cost, versus command-at-a-time execution.
That benchmark isolates the execution style. For the whole stack, we ran Real-World Bench: the same 31-task suite on live production sites (X, Amazon, Zillow, government data portals) plus deterministic local sites. Every tool used the same model (gpt-5.6-sol at max effort) with the same independent judge, with no per-task cherry-picking. playwright-cli itself was one of the five tools measured, so this is a direct head-to-head with the CLI route this article covers. Note the scope: the measured tool was playwright-cli, the official CLI; the MCP server was not benchmarked separately.
Real-World Bench: tasks finished perfectly, out of 31
Perfect = every binary rubric passes (up to 6 per task, 154 total); no partial credit
The turn counts explain the gap: playwright-cli averaged 42.8 model turns per task, ego (lite) 30.3, because the heredoc batches what the CLI does one command at a time, and every round trip saved is one fewer chance to derail. The billing consequence: playwright-cli averaged $3.42 per task, and $3.42 per task ÷ 71% completion = $4.82 per completed task, because the misses still show up on the invoice. ego (lite): $1.64 per task ÷ 93.5% completion = $1.75 per completed task. It was also the fastest of the five tools measured, at 398 seconds average per task against playwright-cli's 648. Every session log and judge verdict is public in the ego-browser-benchmark-framework repo, so you can recheck any number here.
Being fair the other way: ego (lite) is a desktop browser. It won't run in a headless CI container, and it isn't a test framework, so it is the wrong tool when you need repeatable headless runs in CI. Where it fits instead is a live account you already control, where the agent starts from the login state you chose to import. assertion-heavy regression suites still belong to Playwright proper. Its place is the daily work that needs your own accounts.
Pick by task shape, not by hype: the full ego (lite) vs Playwright MCP comparison walks through it dimension by dimension, or download ego (lite) for Mac and run one real task, it's free.
How do you reduce token usage in Playwright browser automation?
Reduce Playwright token usage by controlling the evidence that returns to the model. Keep a task-specific tool set, use a filtered snapshot or targeted locator instead of a full page dump, batch repeated actions in a script, and write large outputs to files for selective reading. Set limits for pages, actions, retries, and tokens so a failed run stops predictably.
- Start with a scope contract. Name the URLs, fields, and success condition. A coding agent should not repeatedly rediscover the same page or read links outside the requested scope.
- Prefer targeted observations. Ask for a locator's text, a small table, or a specific DOM property when the target is known. Current MCP provides browser_find for matching text with surrounding context; current CLI provides find, element snapshots, and --depth. Use a full accessibility snapshot only when the agent must discover the page structure.
- Batch work outside the chat. Have the CLI execute a loop and emit one JSON or CSV result instead of asking Claude to call a browser tool for every row. Read only the output slice needed to decide the next step.
- Measure accepted results. Log input and output tokens, browser actions, retries, and rows that pass validation. Compare cost per accepted row, not token totals alone.
When should you use MCP versus CLI for cost efficiency?
Use MCP when a short, exploratory task benefits from immediate structured page context or when the client cannot run shell commands. Use the CLI when the task is long, repetitive, cost-sensitive, or mixed with coding, because outputs can remain on disk and scripts can batch actions. The choice is an interface decision, not a claim that one browser engine is inherently cheaper.
| Question | Prefer MCP | Prefer CLI |
|---|---|---|
| Can the agent run shell commands? | No; MCP is the available interface | Yes; scripts and files are available |
| Does the agent need to discover the page? | Often; a live snapshot is convenient | Only when the script reads a snapshot |
| Will the task run for many steps or rows? | Works, but snapshot context accumulates | Usually; batch and checkpoint the loop |
| Is the job a deterministic CI test? | Useful for drafting or exploration | Best fit for repeatable test commands |
For a mixed workflow, keep both installed: use MCP to inspect an unfamiliar page, then convert the stable path into a CLI script or Playwright test. If the task needs a live account you already control, neither interface automatically inherits your everyday Chrome; use an explicitly authorized persistent profile, or a browser such as ego (lite), which imports your Chrome profile in one click.
How do you control tool bloat and context-window usage?
Treat tool schemas and page snapshots as part of the context budget. Disable unused MCP servers, expose only the commands a task needs, trim snapshots or use locator-scoped reads, and periodically summarize the run into a small state file. Context control is a configuration and workflow problem; adding a larger model does not make an unbounded transcript cheap.
- Load tools per task. Keep browser, filesystem, deployment, and design tools in separate configurations where possible. A tool that is never called can still add schema tokens at session start.
- Use a context checkpoint. Write URL, task state, completed keys, failures, and next action to a file. Start a new conversation from that file when the transcript becomes noisy.
- Cap evidence size. Limit rows, characters, screenshots, and trace retention per step. Save the full artifact for audit, but send Claude the summary and the relevant excerpt.
Playwright MCP's snapshot controls and the CLI's file-oriented workflow make different trade-offs. Compare the enabled tools and returned evidence against the exact client context window; do not copy a community token number into a production budget without measuring your own page shapes.
How do you automate browser verification in a local coding workflow?
Put browser verification after the code change and before the merge, with the agent producing a reproducible command and a small evidence bundle. A local workflow can open the app, run a smoke path, capture a screenshot or trace on failure, and summarize the result for a pull request. Schedule the check only when the environment, test data, and credentials are controlled and the run is safe to repeat.
- Build a deterministic fixture. Use a local server, seeded database, or test account. Avoid making a live production account the only source of pass/fail evidence.
- Run a small smoke contract. Check navigation, a key interaction, the resulting URL or API response, and one user-visible assertion. Keep exploratory notes separate from the gate.
- Attach evidence to the change. Record the commit, browser and Playwright versions, command, duration, and redacted trace or screenshot on failure. A reviewer should be able to rerun it without reconstructing the chat.
A scheduled CLI can open a pull request with the evidence, but it should not merge or deploy solely because an agent says passed. Require the repository's normal checks and a human review for external side effects.
Does installing Playwright CLI replace the MCP plugin?
Installing Playwright CLI does not technically replace Playwright MCP; they are separate interfaces to Playwright. Keep MCP when a chat client needs tool calls and live page structure without shell access. Use the CLI when a coding agent can run commands, persist artifacts, or batch a long workflow. You can keep both installed, but disable the unused MCP server when context cost matters.
npm install -g @playwright/cli@latest
playwright-cli --version
playwright-cli --helpThe CLI can open pages, create snapshots, click refs, evaluate scripts, save output, and install agent skills; it does not automatically write a durable test suite for you. Have Claude turn a proven command sequence into a Playwright Test when you need assertions, fixtures, retries, traces, and CI reporting.
Read the official Playwright CLI guide before treating an exploratory CLI command as a regression test.
How do you troubleshoot OpenCode subagents and providers?
Troubleshoot OpenCode browser failures from the outside in: verify the model provider, then subagent permissions, then the Playwright command, and finally the target page. Capture the exact command, provider response, and first failing step. A subagent that cannot invoke a tool is a configuration problem; a tool that returns an empty or blocked page is a browser or site-state problem.
- Check provider health first. Run a minimal completion with the selected provider and model. Confirm the base URL, model name, credentials, quota, and network path before changing Playwright flags.
- Check subagent permissions. Confirm the subagent can run the shell command, read its output directory, and access the configured MCP server. Keep permissions narrow and inspect the generated config instead of granting every tool.
- Reduce to one browser step. Run playwright-cli --help, open a static page, take one snapshot, and inspect the raw output. This isolates wiring from a React shell, login wall, or anti-bot response.
- Record the first error. Save stderr, HTTP status, URL, browser version, and the last successful action. Do not keep retrying a rate limit or authentication denial; route it to a human or approved alternative.
For a custom provider, prove that its API answers independently, then add OpenCode, then add Playwright. One new layer at a time keeps “provider unavailable,” “subagent denied,” and “page blocked” from collapsing into one misleading browser error.
How do you connect a local Ollama model to OpenCode?
Connect Ollama to OpenCode by starting with a locally served model, confirming its API endpoint and model identifier, then adding that provider to OpenCode before attaching Playwright. Keep the browser test small until the model can reliably call one tool. Local inference can lower API spend, but it shifts cost to memory, latency, context length, and model reliability.
- Verify Ollama alone. Run the local server, list installed models, and send a short prompt through its documented API. Confirm the model supports the tool-calling or structured-output behavior your workflow needs.
- Add one OpenCode provider entry. Use the provider's current OpenCode schema and keep the base URL, model name, and optional key in the environment or secret store. Do not paste secrets into a browser prompt or commit them.
- Test one Playwright action. Open a local or static page, inspect one locator, and return one structured value. If it fails, inspect the provider response before changing browser flags or adding more tools.
Expect trade-offs: smaller local models may need tighter prompts and more explicit selectors; larger local models need more RAM and may be slower. Measure completion rate, tool-call retries, wall-clock time, and total machine cost against a hosted baseline rather than assuming local means free.
FAQ
Is the Playwright CLI faster than Playwright MCP?
Playwright officially describes CLI as lower-token-cost for coding agents, but it does not promise a fixed speedup. One historical community article reported near-4x context differences on two specific tasks. Wall-clock speed depends on browser work, model round trips, retries, and how much evidence the agent reads, so measure your own workflow.
Why does Playwright MCP use so many tokens?
The official comparison identifies tool schemas and snapshots as contributors. In one historical community measurement, schemas were about 4,200 tokens and two page snapshots were about 3,800 and 12,000. Those are not current defaults. Use browser_find, depth-limited or element snapshots, and your client's own token reporting to measure the workflow you run.
Can I use the Playwright CLI with any AI agent?
Use it with an agent that can run shell commands and read files, such as Claude Code, Codex, Cursor, or Copilot when configured that way. A chat-only client needs another integration, such as an MCP-capable route.
Does either route work on sites behind a login?
By default, each route starts with its own browser state. Playwright CLI can preserve an in-memory session, save a profile with --persistent, load storage state, or attach through its extension or CDP. Playwright MCP can use a persistent user-data directory, storage state, or its browser extension. Configure and authorize those paths deliberately.
How were the Real-World Bench numbers measured?
The 31-task suite ran on live production sites. Tasks were graded on up to 6 binary rubrics (154 across the suite) by an independent judge agent that reads the raw session logs and screenshots itself; a task counts as perfect only if every rubric passes. All five tools used the same model (gpt-5.6-sol at max effort). playwright-cli finished 71.0% of 31 tasks perfectly; ego (lite) finished 93.5% across 31 tasks. The measured Playwright tool was playwright-cli, not the MCP server. The full harness and dataset are public in the ego-browser-benchmark-framework repo on GitHub.

