The Missing Architecture in AI Browser Automation: Why Stateful DOM Beats Both Pure DOM and Pure Vision
The AI browser automation space has settled into two camps: DOM-first and vision-first. But there is a third architecture that most comparisons miss.
The problem with pure DOM-first
DOM-first tools (browser-use, 85K stars) parse the accessibility tree, feed structured text to the LLM, and let it pick actions. It works, the 89.1% WebVoyager score is real.
The issue: every step is a fresh LLM call with no memory of context. The model gets a new DOM snapshot and has to re-derive everything from scratch. No caching. No replay. Every run pays full price.
Stagehand (21.8K stars, TypeScript) solves part of this with a caching layer. First run: LLM figures out the actions. Subsequent runs: replay cached actions without calling the LLM. Smart. But it still treats the page as a passive target, find element, click element, hope it worked.
The problem with pure vision
Skyvern (22K+ stars, AGPL-3.0) bets that looking at pixels is more reliable than parsing markup. Feed a screenshot to a vision model. Let it see buttons, forms, text like a human would.
On legacy portals, canvas apps, and obfuscated pages, they are right. It works where DOM parsers give up.
But three tradeoffs:
- Cost: Vision tokens are expensive. A 10-step workflow can burn 30K-50K tokens, or $0.10-0.50 per run.
- Speed: Image encoding adds latency to every action step.
- License: AGPL-3.0. Commercial products that wrap Skyvern may need to open-source their entire stack. Their managed-cloud anti-bot measures are also excluded from the open-source repo.
What stateful DOM brings
BrowserAct uses DOM-based element indexing, but the architecture is fundamentally different from browser-use or Stagehand.
Instead of treating interactions as fire-and-forget commands, it runs an explicit state loop:
browser-act --session prod state # returns [1] button Submit
browser-act --session prod click 1 # interact by index
browser-act --session prod wait stable # explicit readiness check
browser-act --session prod state # verify: did the page change?
Three things set this apart:
1. Indexed elements, not guessed selectors. When state returns [1] button Submit, that is what you click. No XPath, no CSS selector drift, no did the DOM shift anxiety after a site redesign.
2. Explicit verification. wait stable makes page readiness a real step, not an assumption buried in a timeout. The model does not guess, the browser confirms.
3. Session isolation. Each workflow runs in its own session. Login expiration in one workflow does not kill another. Cookie contamination does not happen.
When something fails, and in production it will, you debug at the right level: was the page stable? Did the session survive? Not did the model hallucinate a selector?
When to use what
- browser-use: Largest ecosystem, most examples. Python-native. Good for getting started fast.
- Stagehand: Repeated workflows on the same sites. Caching means costs approach zero after the first run. TypeScript-native.
- Skyvern: Canvas apps, legacy portals, or DOM-hostile sites where parsers give up. Pay the vision tax when you have to.
- BrowserAct: You need explicit reliability, workflows that verify every step, isolated sessions, and a clear recovery path when automation hits a wall.
The real question
The architecture choice is not about which approach is better. It is about one question: what breaks first in your workflows?
browser-use retries. Stagehand re-caches. Skyvern re-plans with its Validator agent.
BrowserAct asks: was the page ready? Was the session intact? Does a human need to take over?
Different failure models. Different tools. Pick the one that matches your actual pain points, not the ones the marketing page assumes you have.
Disclosure: I work on BrowserAct. Try it: npx skills add browser-act/skills --skill browser-act
Top comments (0)