What you need to know

Browser automation for agents went from research curiosity to default tooling somewhere between late 2024 and now. Microsoft ships an official Playwright MCP server, Google ships an official Chrome DevTools MCP server, Browserbase's open-source Stagehand framework wraps browsers in natural-language primitives, and Browser Use has become one of the most-starred agent projects on GitHub — north of 80,000 stars, per one 2026 comparison. On the model side, Anthropic's computer use — introduced in late 2024 and still labelled beta — and OpenAI's computer-use tooling, which grew out of Operator into ChatGPT's agent mode and a developer-facing API model, both drive interfaces by looking at screenshots and issuing mouse and keyboard actions.

What hasn't closed is the gap between a demo and an automation you'd bet an operations team on. A browser agent that books one test appointment on camera is easy; one that processes five hundred renewals a day for a Mumbai NBFC's back office, or runs nightly checkout smoke tests for a London retailer, without hallucinating a click or burning a fortune in tokens, is a different discipline. Before diving in, the short version:

  • Two architectures dominate: structured accessibility-tree/DOM snapshots (Playwright MCP, Chrome DevTools MCP, Stagehand) and screenshot-based computer use (Anthropic, OpenAI). The first is cheaper and more robust; the second handles UIs the first cannot see.
  • Token cost is the silent killer. One widely circulated 2026 analysis put a single MCP workflow at roughly 114,000 tokens versus about 27,000 for a script-based approach — around 4x.
  • The winning production pattern is hybrid: the agent explores once, writes a deterministic Playwright script, and the script runs in CI for pennies.
  • Anti-bot systems will notice you. Automate only what you're authorised to automate; for your own properties, real browser profiles and managed browser infrastructure keep sessions stable.
  • Reliability is engineered, not prompted: bounded retries, checkpoints, idempotent submissions and human handoff on CAPTCHAs and logins.

Two architectures: reading the tree or reading the pixels

Every browser agent has to answer one question: how does the model perceive the page? The two mainstream answers produce very different systems.

Accessibility-tree and DOM snapshots

Playwright MCP's core trick is the browser_snapshot tool. Instead of sending the model a picture, it serialises the page's accessibility tree — the same structured representation screen readers consume — into text: every interactive element with its role (button, textbox, link), its accessible name ("Get quote", "Vehicle registration") and a short reference the model can target in its next action. The project's own documentation is explicit that it uses "Playwright's accessibility tree, not pixel-based input", which makes it fast, deterministic and usable by models with no vision capability at all. Chrome DevTools MCP takes a similar structured approach while adding DevTools superpowers — network inspection, console logs, performance traces — and Stagehand layers natural-language primitives (act, extract, observe, agent) over the same structured substrate, letting you mix deterministic code with AI-decided steps.

Screenshot-based computer use

Anthropic's computer use tool and OpenAI's computer-use model take the opposite bet: screenshot in, mouse and keyboard actions out. Nothing about the target needs to be a well-formed web page — the model sees exactly what a human sees, which is why this approach generalises to desktop applications, virtual machines and remote desktops (a useful comparison of the two vendors' designs is WorkOS's side-by-side analysis). The price is that every step involves vision inference over an image, coordinates drift when layouts shift, and token bills climb with every screenshot. Pixels are unavoidable, though, when there is no tree to read: canvas-based applications, embedded maps, charting and design tools, video players, and legacy line-of-business UIs that render everything as one big image. If your Indian fintech back office still runs a 2009-era applet-style portal, no accessibility tree is coming to save you.

Dimension Accessibility-tree / DOM snapshots Screenshot-based computer use
Fidelity Sees roles, names, states and values; blind to purely visual content (canvas, images) Sees exactly what a user sees, including canvas and legacy UIs
Token cost per step Text snapshot — smaller, but grows with DOM complexity Image input every step, plus vision-model pricing
Latency Lower — no vision pass; actions target element references directly Higher — screenshot, vision inference and coordinate maths per action
Resilience to redesigns High — role and accessible name survive most CSS and layout changes Moderate — the model re-locates targets visually, but drift and misclicks rise
Where it breaks Canvas apps, image-rendered UIs, poor semantic markup Cost at scale, precision clicking, small targets

The practical rule most production teams have converged on: default to the tree, fall back to pixels. Playwright MCP itself supports this — screenshots and opt-in coordinate-based vision tools are available alongside snapshots — so the fallback can happen per step rather than per project. The same logic explains why the snapshot approach degrades gracefully while the screenshot approach degrades expensively: a text snapshot of a simple form might be a few kilobytes, and only balloons when the DOM itself is bloated, whereas a screenshot costs roughly the same whether the page contains three fields or three hundred. On a long flow, that difference compounds step by step.

It's also worth being honest about what the tree cannot tell you. Accessibility snapshots describe what elements are, not what they look like — so a button rendered off-screen, overlapped by a cookie banner, or styled to be invisible still appears in the tree as perfectly clickable. Screenshot-based agents catch those visual truths naturally. Production stacks that have been burned by this tend to add one cheap safeguard: a single screenshot at each verification point, checked only when the structured action fails, which buys visual ground truth without paying vision prices on every step.

Getting started with Playwright MCP

Setup is genuinely a one-liner. For Claude Code, per the official repository (v0.0.78 as of early July 2026):

# Add Playwright MCP to Claude Code
claude mcp add playwright npx @playwright/mcp@latest

# Same server with flags: headless for servers/CI,
# isolated so each session gets a fresh browser profile
claude mcp add playwright -- npx @playwright/mcp@latest --headless --isolated

By default the server launches a headed Chromium window, which is exactly what you want while developing — watching the agent drive the browser is the fastest way to spot where it goes wrong. Pass --headless once the flow moves to a server. The tools the agent then sees are small in number but composable:

Tool What it does
browser_navigateOpen a URL
browser_snapshotCapture the accessibility-tree snapshot of the current page
browser_click / browser_hoverAct on an element by its snapshot reference
browser_type / browser_fill_formEnter text into one field, or complete several at once
browser_select_option / browser_press_keyDropdowns and keyboard input
browser_wait_forWait for text to appear or disappear, or for a delay
browser_take_screenshotVisual capture — for humans and failure artefacts, not for acting

A first working flow, in plain terms: ask the agent to navigate to your staging checkout, snapshot the page, add a product to the basket, fill the delivery form with test data and stop before payment. Watching that run, you'll see the loop that defines this whole category — navigate, snapshot, decide, act, snapshot again. Every decision the model makes is grounded in the last snapshot, which is why snapshot quality (and cost) dominates everything downstream. Two habits pay off immediately. First, give the agent a crisp goal with an explicit stop condition ("stop at the payment page and report the order summary") rather than an open-ended instruction — browser agents fail more often from ambiguous objectives than from bad clicks. Second, ask it to narrate what it expects to see before each action; when the narration and the next snapshot disagree, you've found your bug while it's still cheap. If you're new to MCP itself, our walkthrough on building your first MCP server with FastMCP explains the protocol mechanics underneath these tools, and the principles in designing tools for AI agents explain why Playwright MCP's small, well-named tool surface works so well for models.

Pro tip

Run with --isolated in development so every session starts from a clean profile, and keep a separate persistent profile for flows that need a logged-in state on your own systems. Mixing the two is how you end up debugging a "flaky agent" that is actually a stale cookie.

Token economics: the 114K problem

Here is where demos and production part company. Because each snapshot lands in the model's context as a tool result, and because the server's tool schemas are injected at session start, long multi-step flows accumulate context at an alarming rate. One widely circulated 2026 analysis — echoed across developer write-ups and tooling comparisons — measured roughly 114,000 tokens for a single seven-step MCP workflow, versus about 27,000 tokens for the same flow driven through a script/CLI approach: a 4x gap, with early adopters reporting anywhere between 4x and 10x depending on page complexity. The same analysis attributed around 36,000 tokens to tool schemas loaded up front and roughly 15,000 tokens per step of page content; on notoriously heavy DOMs, a Salesforce-focused write-up found single snapshots alone could dominate the budget. Treat the specific numbers as one analysis's measurements rather than a law of nature — but the shape of the problem is real and widely reproduced.

Multiply it out and the business case writes itself. At a few tenths of a US dollar per run on a mid-tier model, an agent that re-derives the same seven-step flow five hundred times a day is spending real money to rediscover what it already knew yesterday. That is why the pattern production teams have settled on is explore once, compile, replay: let the agent work out the flow interactively a single time, then have it emit a deterministic Playwright script — plain code, no model in the loop — that runs in CI or a scheduler forever after, at effectively zero marginal token cost. The agent only re-enters the picture when the script breaks.

// renewal-quote.spec.js — generated once by the agent, replayed in CI
// Selectors use role + accessible name, straight from the snapshot.
import { test, expect } from '@playwright/test';

test('renewal quote flow', async ({ page }) => {
  await page.goto('https://portal.example.co.uk/quotes');
  await page.getByRole('button', { name: 'New quote' }).click();
  await page.getByLabel('Vehicle registration').fill('AB12 CDE');
  await page.getByRole('button', { name: 'Get quote' }).click();
  await expect(
    page.getByRole('heading', { name: /Your quote/ })
  ).toBeVisible({ timeout: 15_000 });
});

Notice the selectors: getByRole and getByLabel are the script-world twins of the accessibility-tree snapshot. A flow discovered through the tree compiles naturally into selectors anchored to the same tree — which is precisely why scripts generated this way survive redesigns that would shred CSS-class or XPath selectors. For a Bengaluru lending team, that might mean the agent explores the reconciliation portal once a quarter when the vendor ships UI changes, regenerates the script, and the nightly run costs nothing in between.

The anti-bot reality

Point your shiny new agent at the open web and you will meet the counter-industry. Automated browsers advertise themselves: the W3C WebDriver specification requires automated sessions to set navigator.webdriver to true, and detection stacks read it in the first millisecond. Beyond that flag sit canvas fingerprinting (rendering hidden graphics and hashing subtle per-machine differences), TLS and header fingerprints, mouse-movement analysis, and managed challenges from providers such as Cloudflare's bot management, which score every session before your agent sees a single form field. Headless Chromium with default settings fails several of these checks simultaneously.

The temptation at this point is to reach for the grey-market toolbox — patched browser builds, fingerprint spoofers, CAPTCHA-solving services. Resist it, for practical reasons as much as ethical ones: it is an arms race you fund but do not control, every detection-vendor update can silently break your pipeline, and the moment your automation depends on evading a control, you have built your business process on top of someone else's decision to tolerate you. Production systems need dependencies you can rely on next quarter, and "undetected, for now" is not one.

What legitimately works — for sites you own or are authorised to automate — is unglamorous: run real, headed browser profiles with persistent state rather than fresh headless instances; keep sessions logged in through normal auth flows instead of replaying credentials each run; and, at fleet scale, use managed browser infrastructure such as Browserbase, which hosts real browser sessions with stable profiles as a service and has become common plumbing under agent stacks in 2026. For internal properties, the cleaner answer is to whitelist your automation's service identity so it never has to look human at all. And remember that a browser agent ingesting arbitrary web content is also an injection target — a hostile page can carry instructions aimed at your model, which is why the layered approach in our guide to defending agents against prompt injection applies doubly here.

Watch out

Only automate sites you own or have explicit authorisation to automate, and respect terms of service and robots.txt. Unauthorised access is a criminal offence under the UK's Computer Misuse Act 1990 and India's Information Technology Act 2000, and deliberately evading another site's bot defences can cross that line. A CAPTCHA is the site telling you that you are not welcome as a machine — treat it as a stop sign and a human-handoff point, never as an engineering challenge to defeat.

Reliability patterns that survive 3am

A browser agent's failure modes are mundane: a page loads slowly, a modal appears that wasn't there yesterday, a submit button double-fires, a session expires mid-flow. None of these needs a smarter model; they need the same engineering discipline you'd apply to any distributed system that talks to something flaky.

Timeouts and bounded retries. Every action gets an explicit timeout and a capped retry count with backoff. Unbounded retries against a broken page are how agents burn budgets overnight. Checkpointing. A twelve-step flow that fails at step nine should resume at step nine, not restart at step one — persist state after each verified step. Deterministic selectors. Anchor on role and accessible name from the accessibility tree, so the flow breaks only when the interface's meaning changes, not its styling. Human handoff. CAPTCHAs, unexpected logins, two-factor prompts and anything touching payment should page a person, with the browser session preserved so the human continues where the agent stopped. Idempotency. Before any form submission that creates or moves money, check whether the operation already happened — a client-generated reference number your backend deduplicates on turns a double-submitted refund into a no-op instead of an incident.

Two smaller disciplines round this out. Prefer condition-based waits — browser_wait_for on a specific piece of text, or a visibility assertion in generated scripts — over fixed sleeps, which are simultaneously too slow on good days and too fast on bad ones. And plan for session expiry as a first-class event rather than a surprise: a flow that detects it has landed on a login page should pause, trigger re-authentication through your approved path, and resume from its last checkpoint. Agents that treat an unexpected login screen as just another form to fill are how credentials end up typed into the wrong box.

# Bounded retries + checkpoints + human handoff, in one wrapper
async def run_step(step, attempts=3):
    for attempt in range(1, attempts + 1):
        try:
            result = await step.execute(timeout=15)
            checkpoint.save(step.name, result)   # resume here, don't restart
            return result
        except (TimeoutError, ElementNotFound) as exc:
            if attempt == attempts:
                await artifacts.capture(screenshot=True, trace=True)
                raise HandoffToHuman(step.name, exc)
            await backoff(attempt)               # 2s, 4s, 8s — never unbounded
Pro tip

Make the checkpoint store double as your idempotency ledger. If checkpoint.save("submit_refund", ref) already holds a reference for this task, the retry path skips the submission and verifies the outcome instead — one mechanism, two failure classes solved.

Evaluating and monitoring browser agents

You cannot improve what you only observe anecdotally. The metric that matters is task completion rate — of N attempted end-to-end flows, how many reached the verified success state — tracked per flow and per site, because a redesign on one target will crater one line on the dashboard while everything else stays green. Underneath it, watch steps-per-task (a rising count means the agent is flailing before succeeding), token cost per completed task, and handoff rate (how often a human had to finish the job).

When a run fails, artefacts decide whether the fix takes minutes or days. Capture a screenshot at the moment of failure, the last accessibility snapshot, and — since Playwright supports it natively — a full trace of the session, so you can replay exactly what the agent saw and did. Log every tool call with its arguments and result; a browser agent's trajectory is just a tool-call sequence, which means the evaluation approach we laid out in how to evaluate AI agents across trajectory, tool calls and outcomes transfers directly: score the outcome first, then use trajectory-level checks to explain why the failures failed. Run a small evaluation suite of known flows against staging on every deploy of your agent stack — model upgrades change behaviour, and you want to find that out before the nightly batch does.

Finally, run a canary: one representative flow executed on a short schedule against production, with alerting on consecutive failures rather than single ones (browsers are flaky enough that a lone failure is noise, but two in a row is signal). The canary catches the failure class no staging suite can — the target site changed under you — and turns "the agent has been silently failing since Tuesday" into a page within the hour. For anything an ops team depends on by morning, that single cheap flow is the difference between an incident report and a non-event.

Where to go from here

The stack has matured enough that the choices are now clear. Perceive through the accessibility tree by default and reserve pixels for interfaces that offer nothing else. Prototype interactively with Playwright MCP — it is one command away — but treat interactive MCP driving as the exploration phase, not the production phase: compile discovered flows into deterministic scripts and let CI replay them for free. Automate only what you're authorised to automate, engineer reliability with the boring patterns that already run the rest of your infrastructure, and instrument everything so regressions surface as dashboard lines rather than support tickets.

A browser agent that quietly clears five hundred renewals a night for an NBFC ops team in Mumbai, or keeps a Manchester retailer's checkout monitored around the clock, is exactly the kind of unshowy, production-grade work that hiring teams in both markets are hunting for this year. If you've shipped one — or you're about to — put it where those teams can find it: a Verified Builder profile takes two minutes, and the people browsing the Builders directory are doing so because they're looking for precisely this.