Web agents keep failing at the browser layer, not the model layer
The central claim here is architectural, not cosmetic: web agents fail at the browser layer, not the model layer. Most automation frameworks bolt anti-detection measures onto a standard browser after the fact—JavaScript patches, header spoofing, attribute scrubbing. A page can inspect those patches with the same JavaScript that applied them. dots takes a different position: the Firefox engine itself is modified in C++, so the fingerprint is decided inside the engine before any page script runs. There is nothing to find because nothing was added on top.
The identity coherence argument is worth taking seriously. Screen resolution, installed fonts, GPU renderer, timezone, and language are generated together from a single seed value, so they agree with each other the way a real person's machine does. Pass the same seed and you get the same synthetic person back. Add a proxy and the timezone and language shift to match the exit node—because where a connection originates is part of who the browser claims to be, and mismatches between those signals are exactly what detection systems look for.
The behavioral layer follows the same logic. The pointer physically travels to its target rather than teleporting; keys are pressed individually rather than injected as strings. Every event the page receives is structurally indistinguishable from a human-generated one. No WebDriver flag, no DevTools protocol, no automation globals exposed to page context.
The model is almost incidental to the design. Any model available on OpenRouter works, swapped with a single flag. The README's example task—checking flight prices across five consecutive dates and reporting exact fares without guessing—is a reasonable benchmark for what this kind of agent actually needs to do: navigate a real, hostile, dynamic page and return structured information reliably.
For teams building agents that touch authenticated web surfaces, the persistent profile support matters as much as the fingerprinting. Logins and cookies survive across runs, which means the agent does not have to solve authentication fresh every time it starts.
The same browser is also exposed as an MCP server through a companion project, making it available to Claude Code, Codex, Gemini CLI, or any other MCP-compatible client. dots is the interface; the browser is the primitive being offered. That separation is the honest framing: this is not a complete agent framework, it is a browser that agents can actually use without being immediately identified as one.
A C++-patched Firefox that builds synthetic identities from the engine out, not the JavaScript layer up—the right level to fight detection.