ZeroDOM
Parses a live web page into a token-optimized interaction graph for AI browser agents — 71% fewer tokens than Playwright's ARIA snapshot mode. Every CSS selector is checked for actual document-wide uniqueness before being returned, not assumed from an attribute.
Install
Install and configure the MCP from https://zerodom.vexralabs.com/docs/ now. Follow the documentation's installation instructions, ask me for anything you can't complete yourself, and verify its tools load.99.0%
selector resolution accuracy
98.9%
median token savings vs raw HTML
10-30ms
deterministic parse, no model call
Two workflows, one graph
The parse is identical either way, a flat list of every element the page can act on. What you pipe it into is the difference.
AI agent & automation engineers
Feed a token-dense graph into your LLM loop (LangChain, LlamaIndex, or a hand-rolled loop) as compact text or a JSONL node stream. Numbered handles stay stable across turns; the selector is resolved on your side, never in context.
- 98.9% fewer tokens than raw HTML
- JSONL straight into the loop: zerodom inspect --pipe
- MCP server for Claude / Cursor, no headless bot walls
Security operators & bug-bounty hunters
Drive your real, logged-in Chrome through the extension to reach authenticated surfaces, or spawn a zero-footprint throwaway Chrome over a raw CDP pipe. Match the parsed surface against deterministic rules that make no network calls of their own.
- Real session via the relay + extension (sidesteps bot walls)
- Zero-footprint recon: zerodom inspect --stealth
- Deterministic client-side rules: zerodom scan
From the terminal
Unix-native. Read a page, stream its nodes as JSONL, or scan a list of authorized targets against your ruleset, stdin in, structured lines out, ready for jq or an agent loop.
# Token-dense interaction graph + a savings report
zerodom inspect https://example.com
# Flat node array as JSONL, one node per line — straight into an agent loop
zerodom inspect --pipe https://example.com
# Scan targets you are authorized to test against surfaces.yaml; findings as JSONL
cat targets.txt | zerodom scan -
# Zero-footprint recon: throwaway-profile Chrome over a CDP pipe, no debug port
zerodom inspect --stealth https://example.com
--stealth spawns a fresh, throwaway-profile Chrome and speaks CDP over inherited file descriptors 3 and 4, no localhost debugging port, nothing left on disk. To drive your real, logged-in browser instead (authenticated pages, existing sessions), use the Chrome extension and relay.
The problem
An agent driving a browser gets two action spaces today. Both are bad. Pixels are slow and produce coordinates that go stale on scroll. The accessibility tree is cheaper but enormous, with no stable handles. ZeroDOM is a third option.
See it in action
Parse any page and get a flat graph of every clickable and fillable element. The model sees numbered handles, not CSS selectors, not raw HTML, not coordinates.
<form class="login-form" id="auth">
<div class="field">
<label for="email">Email</label>
<input type="email" id="email" required>
</div>
<div class="field">
<label for="pass">Password</label>
<input type="password" id="pass">
</div>
<button class="btn-primary">Sign In</button>
<a href="/forgot">Forgot password?</a>
</form>
<nav class="sidebar">
<a href="/dashboard">Dashboard</a>
<a href="/settings">Settings</a>
</nav>
<!-- 200+ more lines -->
[01] textbox 'Email'
[02] textbox 'Password'
[03] button 'Sign In'
[04] link 'Forgot password?'
[05] link 'Dashboard'
[06] link 'Settings'
The model sees [03] and clicks. ZeroDOM resolves button.btn-primary on your side, selector never enters context.
97%fewer tokens for the same six actions (~3,000 → ~80)
How it compares
| Feature | Raw HTML | ARIA snapshot | ZeroDOM |
|---|---|---|---|
| Tokens per page (typical) | ~120,000 | ~8,000 | ~2,000 |
| Unique node ids | No | No | Yes |
| Stable across refactors | No | Rarely | Yes (#id) |
| Selectors in context | Yes | Yes | Never |
| Deterministic output | N/A | No | Yes |
| Latency | N/A | ~50ms | 10-30ms |
How it works
The selector never leaves your process. A model only ever sees a node id like [03], the CSS path that actually addresses the element lives in selector_map(), on your side, and gets resolved right before the click.
1
Live page
a Playwright Page, or HTML you already have
2
ZeroDOMParser
one DFS pass: prune, collect, label
3
InteractionGraph
compact text or JSON, sent to the model
4
Model picks a node
e.g. click [03], never a selector
5
selector_map()[node]
resolved on your side, not the model's
6
Act
click/fill via Playwright, then re-read
Architecture
See Architecture for the full system design, data flow, and token economics.
Get started
Choose your path:
[
I want to try it
Parse a page and read the graph in three lines.
Quickstart](https://zerodom.vexralabs.com/docs/quickstart)[
I want to build an agent
Walkthrough](https://zerodom.vexralabs.com/docs/walkthrough)[
I want to integrate it
Wire ZeroDOM into Claude Desktop, Cursor, or your own agent loop.
MCP setup](https://zerodom.vexralabs.com/docs/mcp-setup)
Explore the docs
[
Architecture
System overview, data flow, parser internals, and token economics.
](https://zerodom.vexralabs.com/docs/architecture)[
Applications
QA testing, pen testing, bug bounty, automation, and data extraction.
](https://zerodom.vexralabs.com/docs/applications)[
Seeing the graph
Screenshots, HTML reports, and the on-page driving bar.
](https://zerodom.vexralabs.com/docs/seeing-the-graph)[
Label resolution
The nine-step priority order for naming controls.
](https://zerodom.vexralabs.com/docs/label-resolution)[
Selector audit
Check existing selectors against a live page.
](https://zerodom.vexralabs.com/docs/selector-audit)[
Integrations
LangChain, OpenAI, Anthropic, Vercel AI SDK, CrewAI.
](https://zerodom.vexralabs.com/docs/integrations)[
Bug bounty recon
Stealth Chrome pipe, surface scanning, and the isolation sandbox.