## **1. Won’t Hold Still — The Fundamental Problem with Click‑Based Web Agents**
Modern web agents often follow a predictable, fragile pattern: given a task like “pull every listing from this directory into a spreadsheet,” they repeatedly look at a page, predict a single next action (click, type, scroll), observe what changes, and then decide again. This **look → decide → act → repeat** loop is inherently brittle because each step is a point of failure—modals can appear, buttons can move, and element IDs can change.
Early systems relied on vision (screenshots), DOM/accessibility trees, or fixed action menus. While these approaches improved robustness, they all shared a core limitation: **they optimized for single‑step execution, not for programs that can be saved and reused.** Even when agents performed well in benchmarks, the moment the task ended, the knowledge disappeared.
Webwright, a framework from Microsoft Research and the University of Hong Kong, flips this model. Instead of asking a model to decide the next click, Webwright asks it to **write and execute code**—using Bash and Playwright scripts—to complete a task. The result isn’t just a sequence of actions; it’s a **program** that can be inspected, modified, rerun, and reused.
Rather than advancing one fragile action at a time, Webwright treats the **workspace as the source of truth**. The browser becomes temporary; the locally saved scripts, logs, and outputs become permanent. This shift is especially valuable for real‑world data work—dashboards, product catalogs, search results, internal tools, and JavaScript‑heavy sites—where tasks are repeated and reliability matters.
—
## **2. Why Web Agents Keep Breaking**
### **The Limits of One‑Action‑At‑a‑Time**
Most web agents, regardless of whether they use screenshots, DOMs, or fixed APIs, advance one action at a time. This works for short, simple tasks but becomes increasingly unreliable over longer sessions. A single misread element, a layout shift, or a lazy‑loaded component can derail the entire process.
| Agent Family | What the Model Sees | Strengths | Weaknesses |
|————–|———————|———-|———-|
| Vision agents | Screenshots | Works with any page | Sensitive to pixel shifts; expensive |
| DOM / set‑of‑marks agents | HTML, accessibility trees | More grounded than pixels | Large context size; element IDs change |
| Fixed action‑API agents | Click/type/scroll/select | Simple, benchmarkable | Cannot express loops or retries |
| Browser frameworks | Packaged browser control | Easy to integrate | Still session‑centered, artifact‑poor |
Vision agents struggle with layout shifts and high token costs. DOM agents carry enormous, noisy context. Fixed‑action APIs can’t naturally express “do this for every row” or “retry on failure.” Frameworks make browser automation easier but still leave state trapped in the browser session.
### **From Clicks to Code**
Research such as the ICML 2024 paper *Executable Code Actions Elicit Better LLM Agents* (behind **CodeAct**) showed that replacing predefined JSON‑style actions with executable Python code improves success rates and reduces steps. Code lets models use loops, variables, error handling, and file I/O—everything needed for robust data extraction.
Webwright brings this idea to browser automation: instead of clicking through a site, the model **writes a Playwright script** that can run independently, survive layout changes, and be executed again later.
—
## **3. Webwright’s Unique Approach: Make the Workspace the State**
### **The Paradigm Shift**
Most agents keep progress in the browser session. Close the tab, and the work is lost. Webwright flips this: the browser is temporary, but the **local workspace persists**. As the agent works, it writes scripts, logs, screenshots, and output files. When the task finishes, engineers are left with a **reusable tool**, not a one‑off trace.
This offers several practical benefits:
– **More robust interactions** via Playwright selectors and explicit waits instead of pixel coordinates.
– **Better composition** through loops, functions, and variables that can handle hundreds of repeated actions in one turn.
– **Visible state** in files and logs rather than a bloated, stale context window.
– **Reusable output**—once the code works, it can be rerun or integrated into pipelines.
### **Key Advantages Summarized**
– **Robust, reusable interactions** via code-based waits and selectors.
– **Efficient composition** with loops and functions.
– **Workspace as state**—progress lives in files, not fragile sessions.
– **Minimal, focused design** built on a handful of well‑chosen libraries.
### **Webwright vs. Other Approaches**
– **Vision agents**: struggle with precision (e.g., sliders) and token costs.
– **DOM/set‑of‑marks agents**: carry enormous context and suffer from element churn.
– **Fixed‑action APIs**: can’t express complex control flow.
– **Frameworks**: still center the browser; state dies with the session.
Webwright instead gives the model a **terminal and Playwright**, letting it write full scripts that outlive the run.
—
## **4. How Webwright Works**
### **Architecture in Three Components**
Webwright’s harness is surprisingly small—about **1,000 lines of Python** across three core components:
1. **Runner** (~150 lines)
– Tracks the task and context.
– Maintains the agent’s conversation history and workspace state.
2. **Model Endpoint** (~550 lines)
– Connects to OpenAI, Anthropic, or OpenRouter.
– Provides backends for different model providers.
3. **Environment** (~300 lines)
– Gives the model a terminal attached to Playwright and Chromium.
– Executes commands and returns terminal output, logs, and screenshots.
### **The Interaction Loop**
1. The Runner provides the task and context.
2. The model returns a shell command.
3. The Environment executes it and reports results.
4. The Runner updates the context and repeats.
The loop continues until the model declares the task complete and a self‑check passes. Webwright doesn’t hardcode browser actions—it gives the model a general‑purpose interface (the terminal) and lets the model decide how to use it.
### **Benchmarks Show the Impact**
– **Online Mind2Web**: GPT‑5.4 with Webwright scores **86.7%**, the highest among open‑source AutoEval harnesses.
– **Odysseys**: Same GPT‑5.4 jumps from **33.5% (coordinate‑based)** to **60.1% (Webwright)**—a **26.6‑point gain from the harness alone**.
– Even a **9‑billion‑parameter model** performs well once five or more reusable tools are available.
Costs are higher per task (around **$2.37 with GPT‑5.4**, **$6.09 with Claude Opus 4.7**), but the payoff comes when the same tools are reused many times.
—
## **5. Real‑World Experiments**
### **Test 1: Static Pagination — books.toscrape.com**
– **Task**: Scrape 1,000 books across 50 pages into a CSV.
– **Agent**: Claude Sonnet via the Claude Code plugin, using Playwright.
– **Result**: A standalone CLI tool (`–pages`, `–out`) that ran in ~37 seconds with zero missing fields.
– **Bonus**: The agent detected and fixed a bug where `–help` incorrectly cleared the evidence log.
### **Test 2: JavaScript‑Rendered Content — quotes.toscrape.com/js**
– **Task**: Extract 100 quotes rendered by JavaScript.
– **Challenge**: Raw HTML contains no quotes; status codes are unreliable.
– **Solution**: The agent used `wait_for_selector` and DOM checks to detect when content loaded and stop at the correct page.
– **Result**: 100 quotes in ~9 seconds via a reusable script with `–pages` and `–out`.
### **Test 3: Infinite Scroll — quotes.toscrape.com/scroll**
– **Task**: Extract 100 quotes loaded dynamically as the user scrolls.
– **Strategy**: Scroll, wait for new content, detect stability, and stop when no more content appears.
– **Result**: 100 quotes in ~17 seconds. The agent verified correctness by comparing output with the paginated version—row‑for‑row matches.
Across all tests, the agent wrote **debuggable, reusable programs** and actively validated its own work.
—
## **6. FAQ**
**Q: Does Webwright replace vision‑based or DOM agents entirely?**
A: No. It offers an alternative approach for cases where reusability, robustness, and programmability matter. Other agents remain useful for quick, one‑off interactions.
**Q: How much setup is required?**
A: You need to install Playwright and a browser (about 110 MB). After that, Webwright runs from the command line or via its Python API.
**Q: Is it expensive?**
A: Yes—each task costs several dollars when using powerful models. However, the cost is amortized when the resulting scripts are reused many times.
**Q: Can it handle JavaScript‑heavy sites?**
A: Yes, because it drives a real browser. The agent can wait for network idle, poll DOM state, and handle dynamic content.
**Q: How is correctness ensured?**
A: The agent verifies output, checks invariants (e.g., row counts), compares results from different paths, and can fix bugs automatically.
**Q: Who should use Webwright?**
A: Engineers building repeated data extraction pipelines, internal tools, or scrapers that must survive website changes and be maintainable over time.
—
## **7. Conclusion**
Webwright demonstrates that the future of web agents lies not in better clicking, but in **writing programs that use the browser**. By shifting state from the browser session to a local, code‑based workspace, it produces:
– **Reusable tools** instead of one‑off traces,
– **Robust interactions** via Playwright’s reliable selectors,
– **Composable logic** with loops and functions,
– **Transparent, inspectable outputs** that can be verified and diffed.
As websites grow more complex—JavaScript‑driven, paginated, or infinite‑scroll—the ability to reason about the task and produce a working program becomes more valuable than any per‑step optimization.
The broader lesson is simple: **when a task can be expressed as code, write the code—and leave the tool behind.** Webwright makes this practical for web automation, turning browsing history into lasting software rather than ephemeral clicks.
> *The best web agents don’t just click—they write the tool and move on.*



