In March I tested Vercel’s new agent-browser CLI and came away with a qualified answer: the interaction model was excellent, the architecture was less revolutionary than advertised, and Playwright remained the serious substrate underneath it all.
That article is now a useful historical document and a terrible buying guide.
The version I evaluated, agent-browser 0.16, used a native Rust command-line client in front of a Node.js daemon that used Playwright. Its experimental native daemon was faster to start but produced noisier snapshots and lacked important features. Meanwhile Playwright had a good internal AI snapshot mode, but its public snapshot API omitted the element references an agent needed to act on what it saw.
Both facts have changed.
agent-browser 0.33.1’s primary Chrome path is a fully native Rust CLI and daemon talking directly to the browser through CDP. Node and Playwright are gone from that runtime. Playwright 1.62.0 now exposes AI snapshots publicly, ships its own official agent CLI and MCP server, and returns actionable refs too.
They spent four months moving toward each other.
The short verdict is that agent-browser is now the better default for my shell-driven autonomous browser agent. It is dramatically lighter than Playwright’s Node control plane, its warm command path is genuinely fast, and it has agent-specific capabilities Playwright still does not package as cleanly. A resident Playwright MCP loop or a coding workflow already built around Playwright has different trade-offs; I benchmarked the library but not MCP transport.
It still does not replace Playwright as a programming library or browser testing system. On large accessibility trees its Rust snapshot implementation also hits a serious scaling problem that the tiny happy-path benchmarks hide.
So: switch the default, keep the escape hatch, and be precise about what would have to change before deleting it.
What changed since the first evaluation
agent-browser removed Playwright
The old architecture was:
Rust CLI → Unix socket → Node.js/Playwright daemon → Chrome
The current architecture is:
Rust CLI → Unix socket → Rust daemon → CDP → Chrome
I did not infer that from a README. I cloned agent-browser v0.33.1, checked out commit 6dcea79, and compiled it:
cargo build --release --locked --manifest-path cli/Cargo.toml
The optimized build completed in 2 minutes 44 seconds and produced a stripped native ELF executable:
agent-browser 0.33.1
ELF 64-bit LSB pie executable, x86-64
On the primary Chrome/Lightpanda path, the Rust daemon owns browser launch, CDP commands, snapshots, refs, interactions, waits, network interception, state, recording and cleanup. Safari/iOS integrations use reduced WebDriver backends and may launch external Appium or SafariDriver processes; plugins are external by design. The important correction to my old article is narrower: the Chrome control plane is not a Node launcher wearing a Ferris costume.
The intervening releases added more than native parity. The changelog includes:
- reliable scrolling and overlay detection before clicks;
- frame-scoped actions and waits, including cross-process iframes;
- a warm CLI latency fix that removed an unconditional 150 ms sleep;
- MCP and plugin interfaces;
- readable page extraction through
read; - namespaced sessions with automatic restore and validation;
- HAR response-body capture;
- stronger domain containment;
- axe-core accessibility audits;
- tab recovery after Chrome Memory Saver discards a renderer;
- a one-hour idle timeout that closes eligible daemon-owned headless sessions instead of leaking Chrome forever.
That last point is not glamorous, but browser automation has produced enough immortal Chrome process trees to qualify as a minor branch of necromancy.
Playwright made its AI mode public
My previous evaluation found Playwright’s useful snapshot method hiding behind _snapshotForAI(). The public ariaSnapshot() returned YAML without refs, making it good for test assertions and poor for an agent that wanted to click the thing it had just observed.
Since Playwright 1.59, the public API has fixed the asymmetry; 1.60 added bounding boxes, and current 1.62 carries the mature form I tested:
const snapshot = await page.ariaSnapshot({ mode: "ai" });
The public AI mode returns refs, cursor hints, URLs and iframe snapshots. It also supports depth and optional element bounding boxes. No underscore, no private protocol gamble.
Playwright now also bundles an official playwright-cli and MCP server. Its CLI can open pages, snapshot, act by ref, manage sessions and storage, inspect requests, mock routes, trace, record video and execute arbitrary Playwright code.
“agent-browser has refs and Playwright does not” is therefore dead. Any current comparison that repeats it is comparing one project’s present to the other’s past.
The snapshot models now look remarkably similar
On the same small form, current agent-browser emits:
- main
- heading "Browser Bench" [level=1, ref=e1]
- navigation
- link "Open details" [ref=e2]
- form
- LabelText
- StaticText "Search"
- textbox "Search" [ref=e3]
- button "Submit" [ref=e4]
- paragraph
- StaticText "Waiting"
Playwright 1.62’s public AI snapshot emits:
- main [ref=e2]:
- heading "Browser Bench" [level=1] [ref=e3]
- navigation [ref=e4]:
- link "Open details" [ref=e5] [cursor=pointer]:
- /url: details.html
- generic [ref=e6]:
- text: Search
- textbox "Search" [ref=e7]
- button "Submit" [ref=e8]
- paragraph [ref=e9]: Waiting
Both are actionable. Playwright’s representation is more compact here and preserves the link target and cursor hint. agent-browser’s full tree still exposes some Chrome-flavoured LabelText and StaticText nodes, although snapshot -i removes most structural noise when an agent only needs controls.
agent-browser retains useful presentation features around the snapshot:
snapshot -ifor interactive nodes only;- compact and depth-limited output;
- annotated screenshots with numbered visual refs;
- built-in structural and pixel diffs;
- inline terminal output by default;
- content boundaries and output limits for untrusted pages.
Playwright CLI takes a different approach: by default, after ordinary commands it writes the resulting snapshot to a file and prints a link. That avoids flooding the coding agent’s immediate context, but the agent must perform a file read when it needs the tree. An explicit snapshot command can return it inline.
Neither design is universally better. agent-browser optimizes the conversational tool loop. Playwright optimizes a coding agent working in a repository where generated evidence belongs on disk.
The benchmark
I compared three things, because collapsing them into “Playwright” would be dishonest:
- agent-browser 0.33.1, source-built native Rust CLI and daemon;
- Playwright CLI 1.62.0, the CLI bundled in the
[email protected]npm package and invoked asplaywright cli; - Playwright library 1.62.0, called directly from a persistent or one-shot Node process.
Playwright CLI was tested three ways:
- with its default 500 ms post-action settle;
- with settle set to zero;
- with a whole workflow collapsed into one
run-codeinvocation.
That default is not accidental waste. In the Playwright 1.62 CLI/MCP configuration I tested, timeouts.settle defaults to 500 ms so asynchronous work triggered by an action has time to appear before the automatic snapshot. It is separate from Playwright’s normal actionability checks; setting it to zero does not disable visibility, stability or event-reception checks. run-code removes repeated command startup and intermediate snapshots, but gives up the small declarative command surface in favour of a Playwright function. All three numbers matter.
All implementations used the exact same Chrome for Testing 151.0.7922.34 executable. The machine was an i9-14900K running Arch Linux. Tests used a deterministic loopback HTTP fixture, not a public site whose CDN, advertisements and mood could change between runs.
Every workflow asserted its final state. A successful process with the wrong page did not count.
The CLI comparison is deliberately product-native rather than pretending the interfaces perform identical internal work. agent-browser can execute a preplanned sequence in one batch and emit one final snapshot. Playwright CLI normally snapshots after each command, so its multi-action workflows perform useful intermediate work that agent-browser’s batch does not. The run-code row removes that asymmetry as far as Playwright CLI permits; the direct library row shows the lower-level engine cost.
For fresh-browser measurements I ran two warmups followed by ten measured repetitions, rotating tool order and allowing Chrome teardown to finish between runs. For warm measurements I retained one browser and ran three warmups followed by twenty repetitions.
“Cold” below means a fresh browser, not a cold operating-system page cache or first install. The control daemon/runtime was available. The raw workflow samples, unbatched agent-browser check, Playwright run-code samples, snapshot scaling samples, memory measurements, harness source and methodology notes are public.
This benchmark does not measure Playwright MCP transport, Firefox or WebKit, public-network variance, authenticated applications, hostile SPAs, shadow-heavy pages, nested-frame success rates or model-level task completion. It establishes command overhead, one-page memory footprint and snapshot behaviour on controlled fixtures. The capability conclusions below come from source and API inspection, not from pretending three buttons constitute the web.
Fresh browser: Rust and the Playwright library tie
Median wall-clock milliseconds, including browser launch, navigation, actions, snapshot serialization and browser close:
| Workflow | agent-browser | Playwright CLI default | Playwright CLI, no settle | Playwright library |
|---|---|---|---|---|
| Open + snapshot | 330 ms | 830 ms | 836 ms | 329 ms |
| Open + click + snapshot | 344 ms | 1,682 ms | 1,176 ms | 337 ms |
| Open + fill + submit + snapshot | 341 ms | 1,939 ms | 1,456 ms | 330 ms |
The clean conclusion is not “Rust destroys Playwright.” A purpose-built Playwright script and agent-browser are effectively tied when Chrome must start. Chrome dominates the bill.
Playwright’s agent CLI is slower for two separate reasons:
- each shell command starts Node and loads the CLI bundle;
- its default settle deliberately waits 500 ms after actions.
Comparing the default and zero-settle rows, the settle accounts for about 500 ms in both action-containing workflows in this benchmark. The remaining gap is command startup and snapshot overhead.
This is a product-level result, not an engine indictment. The Playwright library row proves its browser machinery is not intrinsically slow. The official CLI simply packages it with a heavier per-command client.
Warm browser: agent-browser’s architectural win becomes obvious
Median milliseconds with one persistent browser:
| Workflow | agent-browser | Playwright CLI default | Playwright CLI, no settle | Playwright CLI run-code | Playwright library |
|---|---|---|---|---|---|
| Navigate + snapshot | 8 ms | 294 ms | 292 ms | 297 ms | 15 ms |
| Navigate + click + snapshot | 25 ms | 1,117 ms | 613 ms | 349 ms | 67 ms |
| Navigate + fill + submit + snapshot | 23 ms | 1,383 ms | 894 ms | 349 ms | 50 ms |
agent-browser used its native batch command for the main table. I also repeated its flows as separate ordinary CLI invocations. The medians were 9 ms, 17 ms and 17 ms. The result is not a batch-command trick; the native client is simply cheap.
Playwright CLI’s roughly 290 ms floor is mostly Node startup and module loading on every shell invocation. Collapsing the multi-step flows into one run-code call cuts the tuned click and form cases to roughly 349 ms, proving that repeated CLI startup and intermediate snapshots account for much of the larger numbers. It still remains an order of magnitude behind agent-browser’s native command path because the one remaining invocation must boot Node and load Playwright.
An MCP server kept resident should land much closer to the library row because it removes that startup boundary. I did not benchmark MCP transport here, so I am not assigning it an invented number.
The direct library remains fast. In fact, this is the fairest reading of the warm table:
- agent-browser is the best shell protocol;
- Playwright is an excellent resident library;
- Playwright CLI pays heavily for turning that library into repeated Node commands.
For my use case—an agent that already has a shell tool and sends many small browser commands—the first distinction matters more than the third.
Memory: Chrome is still the elephant, but Rust removes a large sidecar
I loaded the same page in each implementation and sampled Linux RSS from /proc. The figures sum process RSS, not proportional set size, so shared pages may be counted more than once. Treat them as comparative process-footprint measurements, not a claim about exact physical RAM.
| Implementation | Control plane | Chrome tree | Total RSS |
|---|---|---|---|
| agent-browser | 10.5 MB | 395 MB | 406 MB |
| Playwright CLI | 130 MB | 411 MB | 541 MB |
| Playwright library | 126 MB | 403 MB | 530 MB |
Chrome is still most of the memory. Replacing Node does not make a modern browser dainty.
But the one-session control-plane difference is real: about 10 MB for agent-browser’s Rust daemon against roughly 130 MB for Node plus Playwright. On this page that saved around 125 MB total. I am not extrapolating it to many isolated identities: agent-browser launches a separate Chrome tree per session, while Playwright can share one browser across many contexts. That needs its own benchmark.
The result that stops me declaring total victory
Tiny fixtures mostly measure fixed overhead. Browser automation gets less charming when the accessibility tree grows large, so I generated pages containing 1,000 and 5,000 repeated semantic rows. Every row had a heading, paragraph, link and button. The browser and page stayed loaded. The agent-browser and Playwright CLI rows measure each product’s complete snapshot command, including client startup and output; the library row measures in-process snapshot generation and serialization. These are native product outputs, not byte-for-byte identical representations.
| Semantic rows | agent-browser | Playwright CLI | Playwright library |
|---|---|---|---|
| 1,000 | 223 ms | 329 ms | 53 ms |
| 5,000 | 2,094 ms | 551 ms | 279 ms |
Output sizes:
| Semantic rows | agent-browser | Playwright CLI | Playwright library |
|---|---|---|---|
| 1,000 | 191 KB | 250 KB | 240 KB |
| 5,000 | 980 KB | 1.29 MB | 1.29 MB |
agent-browser emits less text, which is good, but its time grows badly. At 5,000 rows it takes 3.8 times as long as Playwright CLI and 7.5 times as long as Playwright’s in-process public AI snapshot.
The final row appeared in every output, which rules out simple tail truncation. It does not prove identical node, role or ref coverage—the output sizes show that the representations differ. What is clear is that agent-browser’s product-native snapshot command regressed sharply between these two fixture sizes: a page five times larger took roughly nine times as long.
I have not profiled that path deeply enough to name the exact cause or claim a general complexity class. Pretending otherwise would turn a benchmark into fan fiction. What the data establishes is narrower and useful: on this 5,000-row semantic fixture, current agent-browser full snapshots are substantially slower than both Playwright paths.
-i, selector scoping, compact output and depth limits reduce the practical impact. They do not erase the implementation problem.
Where agent-browser is now better
It is the cleaner agent tool
The core loop is direct:
agent-browser open https://example.com
agent-browser snapshot -i
agent-browser click @e2
agent-browser diff snapshot
There is one discoverable command surface, one tiny native client, one persistent daemon per session and no generated working directory required for ordinary use. It fits naturally into an agent that already knows how to call shell commands.
It packages agent-specific safety more explicitly
agent-browser has opt-in controls aimed at the fact that a browser page is untrusted input being shown to a model:
- domain allowlists that cover supported subresources and workers;
- content-boundary markers;
- maximum output sizes;
- action policies;
- interactive confirmation for sensitive action classes;
- an encrypted auth vault that can fill credentials without placing passwords in model context.
They are not enabled by default. The domain allowlist is not an operating-system firewall and deliberately rejects modes where equivalent containment cannot be installed early enough, including some CDP/auto-connect, profile, restore, provider and Safari/iOS paths. External plugins are processes, not magically sandboxed extensions of Rust.
Playwright CLI and MCP also support origin allow/block rules, secrets, file-access restrictions, sandbox settings, isolated profiles and output controls. agent-browser’s advantage is narrower: action policy, confirmation, content boundaries and the auth vault are more visibly integrated into the agent workflow. Its security documentation is unusually candid about the limits.
It packages useful investigation tools
Several commands are unusually good for autonomous investigation:
readprefers Markdown and can inspect the rendered authenticated DOM;- snapshot and screenshot diffs explain what an action changed;
- annotated screenshots align visual labels with refs;
- HAR capture can retain response bodies;
- the derive-client skill turns observed traffic into an API client;
- React tree/rerender inspection, Web Vitals and axe-core audits sit beside ordinary browsing;
- named sessions, namespaces, profile reuse and restore validation make authenticated work less brittle.
You can construct most of these from Playwright. “Can be built” and “is already the command I need” are different product qualities.
It is substantially cheaper to keep around
The native control plane is faster to invoke and about one-twelfth the RSS of the Node control plane in this measurement. Its default idle timeout also gives abandoned headless sessions a cleanup backstop.
That is exactly the shape I want for many short agent operations against a browser that remains alive.
Where Playwright is still better
It is a programming system, not just a command system
agent-browser batches are sequences. They do not give me Playwright’s natural loops, branches, data structures and event composition:
for (const row of await page.getByRole('row').all()) {
if (await row.getByText('Failed').isVisible())
await row.getByRole('button', { name: 'Retry' }).click();
}
agent-browser can be orchestrated from Ruby, Python or shell, and its plugin system can extend it. Once I am writing a substantial wrapper, however, Playwright is already the wrapper with a mature browser object model.
Playwright CLI exposes run-code, and Playwright MCP exposes browser_run_code, which are useful bridges: remain in the agent session, but execute a real Playwright snippet when declarative commands become insufficient. They are also remote-code-execution-shaped capabilities and belong behind trusted clients. agent-browser has eval inside the page, not an equivalent host-side browser scripting primitive.
BrowserContext remains a serious structural advantage
Each agent-browser --session has its own browser instance, cookies, storage and authentication state. That is good isolation and expensive isolation.
Playwright can create many clean BrowserContexts inside one browser process. agent-browser’s current source records and uses CDP browser-context IDs—and creates a context internally for recording—but does not expose a general user-facing context-management API. The feature request remains open.
If I need two agents, separate Chrome trees are tolerable. If I need twenty identities in parallel, this becomes the wrong architecture.
Locators and actionability are deeper
agent-browser’s click path now scrolls into view, resolves a point and detects an overlay intercepting the click. That is real actionability logic, not a dumb Runtime.evaluate("element.click()").
Playwright still has the broader contract: live locators that re-resolve through DOM changes, composable filters, strictness, visibility, stability, enabled/editable state, event reception and retrying web assertions.
The difference is largest outside clicks. agent-browser fill and type do not apply the same complete actionability and retry model as Playwright. A model can recover by resnapshotting. A deterministic test should not need a model standing nearby with a mop.
Frames and Shadow DOM are not equivalent yet
agent-browser now handles important same-process and cross-process iframe cases. It can inline accessible iframe content and preserve frame context for refs, although inaccessible cross-origin or empty frames may be omitted. This is much better than the version I first tested.
The gaps are in composition and depth:
- its snapshot recursion currently expands one iframe level;
- frame selection is global command state rather than a retained
FrameLocatorobject; - ordinary CSS/XPath selectors do not recursively pierce open Shadow DOM;
- snapshot refs can reach some shadow-tree elements, but selector semantics are not uniform.
Playwright’s frame and open-shadow-DOM locator behaviour remains the safer choice for payment widgets, federated login and component-heavy enterprise applications.
Events and network interception are more programmable
agent-browser can route or abort requests, mock a response body, inspect traffic and record HAR files with content. That covers common agent investigation.
Playwright exposes requests, responses, downloads, popups, dialogs, workers, frames and WebSockets as programmable events. It can establish a waiter before the triggering click, fetch an original response, modify it and fulfill the route conditionally.
That matters for race-sensitive workflows:
const [download] = await Promise.all([
page.waitForEvent('download'),
page.getByText('Export').click(),
]);
A CLI needs a compound command for each such race. Separate “click, then wait” commands are already too late.
Playwright supports Chromium, Firefox and WebKit
agent-browser’s primary local path is Chrome/Chromium over CDP. Lightpanda is the other --engine choice. Separate Safari/iOS and provider integrations use reduced backends that lack several CDP-only features, so they are not feature-equivalent local engines.
Playwright supports Chromium, Firefox and WebKit with one API and runs an actual cross-browser test matrix. If the requirement is Safari correctness rather than “open this page for the agent,” the comparison ends here.
Playwright is still the test framework
agent-browser has traces, video, screenshots, diffs, console logs, performance tools and accessibility audits. It does not have Playwright Test’s fixtures, projects, web-first assertions, retries, sharding, reporters, trace-on-retry and CI ecosystem.
Trying to make agent-browser replace all of that would be less a migration than an elaborate reimplementation of Playwright under a different name.
A fair capability matrix
| Area | agent-browser 0.33.1 | Playwright 1.62 |
|---|---|---|
| Agent refs and snapshots | Excellent; compact modes and inline output | Excellent; public AI mode, CLI and MCP |
| Warm shell commands | Best | Heavy through CLI; fast through resident MCP/library |
| Control-plane memory | 10.5 MB RSS measured in this setup | 126–130 MB RSS measured in this setup |
| Large snapshot scaling | Weak on the 5,000-row fixture | Much better on this fixture |
| Visual and structural comparison | Ref-annotated screenshots and ad hoc diff commands | Mature screenshot and ARIA snapshot assertions; no equivalent conversational ref-annotated diff |
| Agent safety | Integrated opt-in action policy, confirmation, boundaries and auth vault | Strong origin/file/sandbox/output controls; no equivalent vault/policy workflow |
| Persistent authenticated sessions | Excellent | Excellent |
| Host-side programming | Plugins/wrappers | Full typed APIs and run-code |
| Cheap isolated contexts | Separate browser per session | BrowserContext |
| Locator/actionability depth | Good common path | Excellent |
| Nested frames and Shadow DOM | Partial | Mature |
| Event choreography | Command-specific | General event API |
| Browser engines | Chrome, Lightpanda, reduced Safari/iOS | Chromium, Firefox, WebKit |
| Test runner and CI | Bring your own | Playwright Test |
How close are we to dropping Playwright?
For my browser skill, closer than the broad feature matrix suggests. Most of my work is not cross-browser regression testing. It is:
- open a page;
- inspect what is available;
- click or fill something;
- inspect the result;
- occasionally attach to an authenticated browser or collect a screenshot.
For that shell-driven path, the measured command overhead, memory footprint and tool ergonomics make agent-browser the better default candidate for me. The benchmark does not establish higher success rates on authenticated sites, hostile SPAs, downloads or complex frames; those need operational telemetry after the switch.
The remaining Playwright use is concentrated in difficult workflows: loops over extracted data, response-aware scraping, cheap parallel identities, odd frames, Shadow DOM and one-off scripts with real control flow. This makes the migration amenable to stages rather than theology.
Recommendations, from minimal to maximal
1. Minimal: add agent-browser and keep every Playwright path
Make agent-browser available as another skill and use it explicitly for simple snapshot/ref tasks. Change nothing else.
Cost: tiny.
Playwright reduction: perhaps 30–40%.
Risk: almost none.
This is the conservative option. It leaves duplicated browser instructions and asks the model to choose correctly each time.
2. Practical default: route ordinary browsing to agent-browser
Make agent-browser the default for:
- open/snapshot/action loops;
- screenshots and visual inspection;
- authenticated session reuse;
- basic forms;
- tabs;
- reading and network reconnaissance.
Escalate to Playwright when the task requires:
- loops or meaningful branching;
- several isolated identities;
- response/event choreography;
- complex cross-origin frames or Shadow DOM;
- Firefox/WebKit;
- reusable deterministic automation.
Cost: small skill and routing changes.
Playwright reduction: likely 70–85% for agent browsing.
Risk: low, because fallback remains explicit.
This is what I recommend now.
3. Local compatibility layer: one browser skill, two backends
Expose one term-llm browser tool contract and hide the backend choice:
browser.open
browser.snapshot
browser.click
browser.fill
browser.screenshot
browser.close
Use agent-browser by default. Route capability-tagged operations to Playwright. Record which fallback triggered and why.
The important part is telemetry. After a month, we would know whether Playwright remains because of real requirements or because old instructions keep reaching for it.
Cost: moderate local engineering.
Playwright reduction: measurable rather than guessed.
Risk: backend semantic differences need good postcondition checks.
This is the cleanest migration architecture.
4. Targeted upstream work: remove the fallbacks we actually hit
Do not pursue abstract parity. Fix the gaps observed in real sessions, starting with:
- large-snapshot scaling—profile the 5,000-row regression across intermediate fixture sizes and remove the sharp growth before guessing at its complexity;
- compound event waits—click-and-wait for download, popup, URL, response or DOM condition in one daemon request;
- uniform Shadow DOM selectors—make semantic and CSS paths behave consistently through open roots;
- nested frame composition—remove the one-level snapshot limit and avoid global frame state where possible;
- richer route fulfillment—status, headers, request mutation and conditional response handling;
- host-side scripted operation—a constrained
runprimitive or plugin pattern that can perform loops and branches without one shell process per operation.
Cost: medium to large upstream contributions.
Playwright reduction: potentially above 90% for my use.
Risk: each feature expands the daemon from a focused agent tool toward a general automation library.
The snapshot scaling problem should come first because it is both measurable and squarely inside agent-browser’s core purpose.
5. Structural change: cheap BrowserContext isolation
Promote agent-browser’s existing internal CDP context use into a general public API: context creation and disposal, context-scoped tabs, then a clear context/session distinction.
That would let several isolated agents share one Chrome process instead of launching one browser per identity. It is the largest architectural gap for parallel autonomous use.
Cost: large.
Playwright reduction: high for multi-agent work.
Risk: lifecycle, restore, provider and security semantics all become more complicated.
This is worth doing if concurrent identities become common. It is overengineering if Jarvis normally drives one browser.
6. Maximal: remove Playwright completely
To delete Playwright rather than merely stop using it by default, I would require:
- acceptable large-tree snapshot performance;
- cheap isolated contexts;
- reliable nested-frame and Shadow DOM behaviour;
- race-safe event primitives;
- a programmable host-side escape hatch;
- a regression suite across the exact sites and workflows I use;
- migration of every existing Playwright-only script;
- an explicit decision that Firefox/WebKit and Playwright Test are out of scope.
That last line matters. “Drop Playwright” can mean two different things:
- stop using Playwright for autonomous browsing;
- replace every capability Playwright supplies.
The first is now realistic. The second is a bad goal unless the requirements genuinely shrink. Rebuilding a mature cross-browser programming and testing system so a dependency disappears is how tidy architecture turns into a multi-year hostage situation.
The recommendation
Switch the default browser agent path to agent-browser 0.33.1.
Keep Playwright as a named programmable fallback. Add routing rules, record fallback reasons, and let usage data tell us which upstream changes have the highest leverage. The first engineering target should be agent-browser’s large-snapshot scaling; the first product target should be a unified browser skill that hides backend choice without hiding capability differences.
If those changes work, Playwright should become rare. Once it is rare, we can decide whether the final dependency is carrying its weight.
Today, deleting it would be premature. Continuing to use it for every browser operation would be equally stale.