The first thing I tried to do with Anthropic's new browser tool was install it.
There's nothing to install. No claude mcp add. No npm package. browser_toolset_20260801 is a line in the tools array of a Messages API request — and the browser it drives is one you host, in your app, driven by a handler you write.
That single fact reframes the whole comparison. Playwright MCP is something you plug into Claude Code to test an app. The browser toolset is something you build into a product that happens to drive a browser. They read the same accessibility tree and they answer different questions.
Which doesn't mean the overlap is zero. If you're a QA engineer who already drives a browser from an agent, there are three places where the choice actually bites — and one of them will quietly turn a bug into a passing step if you get it wrong.
What shipped
Two things, both on 19 August 2026, in the Claude Platform release notes:
Computer use went GA as computer_toolset_20260801. No beta header anymore, batch actions (several actions in one turn), zoom on by default, and per-member configuration through configs. Earlier beta versions still work; upgrading changes the request shape.
The browser use tool launched as browser_toolset_20260801. A client toolset: it works inside a browser viewport your application hosts, reads the page itself — accessibility tree, elements, forms, tabs — and adds element references, direct form input, tab management, download reporting and opt-in file upload on top of the screenshot-and-click model. 31 member tools, 27 enabled by default, 4 opt-in.
Both are available on Opus 5, Sonnet 5, Opus 4.8, Mythos 5 and Fable 5 — on the Claude API only. Not on Bedrock, Vertex or Foundry. Not in Managed Agents. If your CI talks to Claude through a cloud provider, the decision is already made for you.
Meanwhile, on the other side: Playwright MCP v0.0.79 (6 August 2026) extended --codegen to python, java and csharp alongside TypeScript, added WebP screenshots, and made the post-action settle delay configurable via --timeout-settle. That's the release that matters here, and I'll explain why in a minute.
The same flow, run both ways
Scenario: log in, add an item to the cart, verify the total matches the sum of the line items. Boring on purpose — it's the shape of about forty percent of every e-commerce suite I've ever touched.
Route A — Playwright MCP inside Claude Code
claude mcp add playwright -- npx @playwright/mcp@latest \
--codegen typescript --caps testing --isolatedThe prompt:
Using the Playwright MCP tools, against http://localhost:3000:
1. Log in as demo@example.com (password in $DEMO_PASSWORD).
2. Add "Wireless Keyboard" to the cart.
3. Open the cart and verify the order total equals the sum of the line items.
Rules:
- Call browser_find before browser_snapshot. Never snapshot the whole page
when you only need one element.
- Every assertion goes through a browser_verify_* tool. Do not assert by
reading the page yourself and telling me it looks right.
- When you're done, give me the generated Playwright code.What comes back is a call sequence — browser_navigate, browser_find, browser_click, browser_fill_form, browser_find, browser_click, browser_find, browser_verify_text_visible — and then the thing you actually wanted:
await page.goto('http://localhost:3000');
await page.getByRole('link', { name: 'Sign in' }).click();
await page.getByRole('textbox', { name: 'Email' }).fill('demo@example.com');
// …
await expect(page.getByTestId('order-total')).toHaveText('$149.98');A file. You commit it. It runs tomorrow without an API key.
Route B — browser_toolset_20260801
There is no CLI. You send this:
{
"model": "claude-opus-5",
"max_tokens": 2048,
"tools": [{ "type": "browser_toolset_20260801" }],
"messages": [{
"role": "user",
"content": "Log in as demo@example.com, add the Wireless Keyboard to the cart, and tell me whether the order total matches the line items."
}]
}Claude replies with member calls that carry "toolset_name": "browser":
{ "type": "tool_use", "name": "navigate", "toolset_name": "browser",
"input": { "url": "http://localhost:3000" } }
{ "type": "tool_use", "name": "read_page", "toolset_name": "browser",
"input": { "filter": "interactive" } }Your handler executes each one against your own browser session and returns tool_result blocks. read_page gives Claude the tree with references:
link "Sign in" [ref_1]
textbox "Email" [ref_2]
textbox "Password" [ref_3]
button "Continue" [ref_4]and Claude targets them back:
{ "type": "tool_use", "name": "left_click", "toolset_name": "browser",
"input": { "target": { "type": "ref", "ref": "ref_1" } } }You can also attach a browser_state block to any result so Claude tracks tabs, downloads and tab_opened / download_completed events.
At the end you have a correct answer and a transcript. You do not have a test.
Three questions that actually decide it
1. Artifact or outcome?
--codegen gives you a spec file — TypeScript, and since v0.0.79 also Python, Java and C#. The browser toolset gives you a conversation. ref_2 is scoped to a tab and valid only until navigation or a material DOM change. There is nothing in that transcript you can commit, schedule, or hand to someone who doesn't have an API budget.
If your deliverable is a regression test, this question ends the discussion before the other two get asked.
2. Who is your test oracle?
Playwright MCP has real assertions behind --caps testing: browser_verify_text_visible, browser_verify_value, browser_verify_element_visible, browser_verify_list_visible. Playwright executes them. They pass or fail the same way twice.
The browser toolset has no assertion member at all. A "pass" is the model's reading of a screenshot or a tree. For a product feature — "did the agent successfully book the flight?" — that's exactly right. As a test oracle it's a coin with good odds, which is not the same as a coin that always lands the same way.
3. What happens when the element has no accessible name?
This is the one that will get you.
The browser toolset accepts two targeting styles. When there's no accessible name, the model falls back to coordinates:
{ "type": "coordinate", "x": 640, "y": 380 }Every pointer action takes it. The flow keeps going. The docs are upfront that this is intentional — it's how you drive canvases, embedded content and virtualized lists.
Playwright MCP's ref-based tools have no such fallback unless you explicitly enable --caps vision for browser_mouse_click_xy. On paper: a point for the toolset. It's more robust!
For QA that robustness is the failure. An interactive control with no accessible name is two findings at once — an accessibility defect, and a locator nobody can write. A silent coordinate fallback converts both into a green step and a screenshot that looks fine.
So if you do use the toolset in a testing context, do one of two things: keep coordinate targeting out of the loop entirely, or log every single call where the model targeted by coordinate instead of by ref. That log is not debug output. That log is your accessibility backlog, generated for free, and it's the most useful by-product of the whole exercise.
The token question, honestly
I'm not giving you a benchmark. I'd have to run both against the identical page with identical settle timing to say anything real, and I haven't. What I can tell you is that both have a deliberate cheap path and they're shaped differently:
- Playwright MCP:
browser_findsearches the accessibility snapshot for text or a regex and returns matching nodes with a few lines of surrounding context — snippets, not the page. (I went deep on this in browser_find and the token diet.) - Browser toolset:
findtakes natural language and returns up to 20 matches.read_pagetakesfilter: "interactive"and adepthcap, and its output is hard-capped at 50,000 characters.get_page_textreturns plain visible text for prose-heavy pages.
Screenshots and zoom are images on both sides and count as image tokens; the toolset docs note that above 20 images per request, stricter per-image limits kick in and there's no server-side downscaling — you resize before you send.
Measure it yourself with the three-step flow above and log tokens per step. It takes an afternoon and the number is specific to your DOM, which is the only number worth having.
The decision table
| Situation | Pick |
|---|---|
| The deliverable is a spec file you commit | Playwright MCP (--codegen) |
| You're testing your own app's UI | Playwright MCP |
| You need a deterministic pass/fail oracle | Playwright MCP (--caps testing) |
| You're shipping a feature that drives a browser inside your product | browser_toolset_20260801 |
| The browser lives in your app's viewport and you own the session | browser_toolset_20260801 |
| You reach Claude via Bedrock / Vertex / Foundry | Playwright MCP — the toolset is Claude API only |
| The target isn't a browser (desktop app, installer, native dialog) | computer_toolset_20260801 |
| You need console + network inside the agent's loop | Either — toolset configs, or MCP's browser_console_messages / browser_network_requests |
What I'd flag before you build on this
- The toolset is days old. Launched 19 August 2026. I have no long-run experience with it and neither does anyone else. Treat any confident claim about its reliability — including mine — as provisional.
- Prompt injection is real on both sides. The toolset docs are blunt: page text, tab titles and URLs are untrusted input, isolate the browser, allowlist domains at the network layer, keep
javascript_execandfile_uploadoff. Every word of that applies to Playwright MCP pointed at a staging environment with seeded test data — and almost nobody applies it there. --codegenoutput is a recording, not a designed test. It still needs the same review pass as anything else an agent writes for you. Nothing about a new browser tool changes that.- Batch actions cut both ways. Both toolsets now run several member calls per turn, stopping at the first failure. Fewer round trips, but a failure mid-batch means the later calls come back as "not executed" — your handler needs to report that honestly rather than swallowing it.
Takeaways
browser_toolset_20260801is not a Playwright MCP replacement. It's an API primitive for a browser your app hosts, and you write the driver.- Ask "artifact or outcome?" first. If you need a committed spec file,
--codegendecides it and the other differences don't matter. - Playwright MCP has real assertions (
--caps testing). The browser toolset has none. Don't use model judgement as a pass/fail oracle. - The toolset's coordinate fallback is a feature for products and a hazard for testing. Log every coordinate-targeted click — that log is your accessibility backlog.
- Claude API only. Bedrock, Vertex and Foundry users don't have this choice yet.
Next up: the toolset's read_console and read_network members are opt-in for a reason, and wiring them into an agent's loop changes what the agent is willing to claim about a failing page. That one deserves its own post.