It is three in the morning and the log is still scrolling. A six-hour scraping job stops at request two thousand three hundred and something. No 403. No 429. Just a Cloudflare page asking the script to prove it is human. Nothing crashed. The process sits there quietly, like a river behind a closed gate.
You drop a screenshot into the group chat. Three replies land at once.
The first says: change the engine. Use Camoufox. Firefox fingerprints are baked in at the C++ level, so there is no JavaScript patch for a page to find.
The second says: don’t change the framework. Install Patchright. Swap one import and it replaces the Playwright you already have. The Runtime.enable leak is already plugged.
The third says: this was never a browser problem. What you need is a machine. Something that boots itself, logs itself in, and remembers where it stopped.
All three sound certain. None of them is talking about the same thing.
That night you try all three: the engine swap stalls on a binary, the patch works until morning, the machine never finishes installing. Nobody was wrong. They stood at different heights.
Comparison posts in this space age badly. Line up stars, licenses and languages and the numbers are correct, yet the reader still cannot choose. These three do not sit on the same layer: one rewrites a browser engine, one rewrites an automation library’s protocol behaviour, one builds a computer for an agent. Ranking them for stealth is like asking whether a hammer, a screwdriver or a drill is better. The job decides.
The machine that goes to sleep on its own
The invisible_dots repository states its numbers plainly: 32,129 stars, 4,831 forks, MIT license, TypeScript, created on 4 August 2024, last commit yesterday (17 October 2026). The README positions it as an open, self-hosted alternative to OpenAI Dots and Grok Bot, and it also labels itself status: alpha without dressing that up.
What matters is how it organises the runtime. A Dot is not a script and not a browser context. It is a hardware-accelerated virtual machine: a Linux desktop, its own persistent disk, sleeping when idle. Install a browser, log into accounts, keep cookies, and everything is still there later. The browser inside that VM is invisible_playwright_mcp, a patched Firefox with fingerprints written inside the engine. Same technical direction as Camoufox, except the engine is wrapped inside a computer. Each identity gets its own cookies and login state. Nothing bleeds across.
Identities contaminate each other. Two accounts in one profile get linked by cookies, localStorage, timezone, even font rendering. One VM per identity separates them at the OS boundary, at the cost of a full system per identity.
Above the VM sit memory and skills. You can attach MCP servers. Permissions come in three tiers: allow, ask and deny. A task queue and scheduled automation sit alongside, with a web UI, CLI, HTTP API, Telegram and WhatsApp as entry points. One line is easy to miss: tasks already accepted survive kill -9. That is the divide between a machine and a library. Kill a library and it is dead. Kill a machine and it comes back.
Persistent disks, permission tiers and a task queue mean handing over a job, closing the laptop, and reading the result next day: not a harder-to-detect browser, an executor that keeps working without you.
The costs are concrete. Node 24 or newer, Go 1.25 or newer, Git, hardware virtualisation, x86-64, plus an OpenRouter key. The x86-64 requirement alone shuts out a lot of MacBooks. On Apple Silicon you need an x86 box or a cloud instance. Every Dot is a VM, so memory and disk are real. Idle sleep helps, but five identities and one are different experiences.
Then there is the alpha label. At this scale of stars, 4 open issues reads like maintainers who close things quickly, not a project nobody uses. The tag still says it is not ready for production trust. Setup is not pip install: you need a machine willing to expose virtualisation, and you accept that you now maintain infrastructure. The setup half day hurts most. After that, a new identity costs a boot, a login and a wait while it recovers state. Heavy at the front, light at the back.
A skin grown inside the engine
Camoufox takes another route. It leaves your environment alone and modifies the browser engine itself. 12,619 stars, 1,069 forks, MPL-2.0, Python, created 26 July 2024, last commit also yesterday (17 October 2026), 58 open issues.
The idea fits in one sentence: on every launch it generates a coherent device identity. It does not roll a random user agent, resolution and timezone. It samples a whole set from real device distributions so the values agree. A Windows 11 user agent paired with a macOS font list is the classic failure. Camoufox removes that self-contradiction.
Screen resolution, devicePixelRatio, fonts, WebGL vendor and renderer, tiny AudioContext variations: each looks fine alone, and together they make a device believable. Faking one is easy. Making twenty agree, and keeping them stable, is the hard part.
More important is where the values come from. The fingerprints are written at the C++ layer. The page receives native values, not values JavaScript assigned through defineProperty on navigator. You cannot see the difference; CreepJS can. A JS override leaves descriptor traces. A native value does not. Canvas and WebGL pixels come from the real OS, driver and GPU, not noise sprinkled in JavaScript.
The gap widens as detection escalates. A JS patch is a patch war: you override a property, the other side inspects the descriptor, the toString output, the prototype. Injection at C++ has no such argument, because to the page it is simply how the browser behaves. The price is that you compile it yourself and read source when it breaks.
The driver is Playwright, invisible to the page, which is the advertised selling point. Installation is manageable: pip install -U "camoufox[geoip]", then camoufox fetch. On the Node side, camoufox plus playwright-core is enough. The geoip extra is not decoration. It aligns timezone, language and coordinates with the exit IP. When that fails, everything upstream is wasted. Many people trip here: a beautiful fingerprint, an exit IP in Frankfurt, a timezone in Los Angeles, a language set to en-US. Those three look stranger together than a plain default browser.
The costs hide in a few places. Firefox only. Some sites treat Firefox differently, so selectors, waits and uploads may need rework. Firefox holds a small share of real traffic; a pure Firefox fingerprint on a Chrome-dominated site is itself a weak signal. That is judgement, not measurement, but the probability holds. Camoufox also follows Firefox’s release cadence, and every upstream move means reconciling patches again. One layer stays out of reach: behaviour. A perfect fingerprint with teleporting mouse movement and millisecond-precise intervals still gets blocked. Camoufox answers “what device do you look like”, not “do you look like a person operating it”. The binary is also large and will fatten a container image.
A screwdriver that fits one kind of screw
Patchright is the lightest of the three. It does not touch the engine, only Playwright. 4,897 stars, 239 forks, Apache-2.0, TypeScript, created 7 November 2023, last commit three days ago (15 October 2026), 3 open issues. Packages exist for Python, NodeJS and .NET.
It sells itself as a drop-in replacement. Change from playwright.sync_api import sync_playwright to from patchright.sync_api import sync_playwright and most of the rest stays. But drop-in deserves a discount. The API is largely compatible; the behaviour is not. It disables the Console API, so page logs disappear. It adjusts launch flags, so tools that rely on defaults stop working. Its protocol isolation can leave scripts that depend on the full CDP event stream waiting for messages that never come. Run your regression suite before migrating.
It patches holes at the protocol and launch-flag layers. Runtime.enable opens a path that detection methods follow to find automation, and Patchright executes JS in an isolated ExecutionContext to avoid it. It disables the Console API outright: that works, and console.log disappears, so debugging gets worse. On launch flags it adds Chrome’s disable-blink-features switch for AutomationControlled and removes the enable-automation default. It also supports elements inside closed shadow roots and XPath, which matters because many key buttons live where stock Playwright cannot reach.
Then there is the sentence that needs careful reading. The README says it passes Brotector, Cloudflare, Kasada, Akamai, Shape/F5, Datadome, Fingerprint.com, CreepJS and Sannysoft. That is the project’s own claim, not independent third-party verification. Detection also has a shelf life. Passing today says little about next month. Treat the list as evidence that the author works seriously in this direction, not as an SLA. These lists measure one build against the checks of that moment, while detection rules change weekly. A project passing several checks in a row means the maintainer is paying attention. It does not mean your production run tomorrow is safe.
The ceiling is clear. Chromium only. Firefox and WebKit are explicitly unsupported. More fundamentally, it changes automation traces, not the browser’s fingerprint. Canvas is still that Canvas. The GPU is still that GPU. The fonts are still those fonts. If the other side looks at TLS fingerprints, mouse trajectories or request rhythm, Patchright cannot help. It is a sharp screwdriver, and it fits one kind of screw.
That places it on the last mile. You already have a Playwright project: proxies, retries, parsing, storage. All that remains is the automation trace at launch. Swapping in Patchright is the best value step there. If your script cannot open a page at all, or the other side never inspects the JS layer, swapping libraries only changes the posture of the collision.
Why there can only be one table
Putting them in one table still feels forced. They are not competitors but three heights of solution. Selection needs a table anyway, so here is a compressed one. The second column matters more than the parameters.
| Project | Layer | Approach | Browser support | Language ecosystem | License | Setup cost | Best fit |
|---|---|---|---|---|---|---|---|
| invisible_dots | Whole machine / environment | One hardware-accelerated VM per identity, containing a patched Firefox plus memory, permissions and scheduling | Bundled Firefox engine | Mostly TypeScript, exposed via Web UI, CLI, HTTP API, Telegram, WhatsApp | MIT | High: Node 24+, Go 1.25+, x86-64 hardware virtualisation, OpenRouter key, still alpha | Teams maintaining many identities over months with unattended 24/7 tasks |
| Camoufox | Engine | Modified Firefox source, fingerprints injected in C++, coherent device identity generated at launch | Firefox only | Mainly Python, plus an npm package with playwright-core | MPL-2.0 | Medium: install package and fetch binary, rework Firefox automation logic | Scraping and agent projects that need strong fingerprint disguise and can live in the Firefox ecosystem |
| Patchright | Automation library | Patches Playwright’s protocol leaks and launch flags, does not touch the engine | Chromium only | Python, NodeJS, .NET | Apache-2.0 | Low: one import change, at the cost of no console | Teams with existing Playwright code missing only the final automation layer |
The second column is the one to read. The layer decides what you can change. Patchright cannot touch fingerprints. Camoufox cannot touch scheduling. invisible_dots does not improve your fingerprint either; it installs someone else’s engine inside a machine that runs itself. The reverse holds: a VM for one short script is overkill, and twenty identities for six months on Patchright alone means writing the scheduler, storage, permissions and restart logic yourself. That is another invisible_dots.
One crude test: watch when the failure happens. Rejected as the request leaves, usually IP and TLS, and none of these helps. Page opens then jumps to a challenge, that is fingerprinting, covered by Camoufox and the engine inside invisible_dots. Kicked halfway through an interaction, that is automation traces, Patchright’s ground. The job dies after two days, login lost, process down with nobody to restart it, that is scheduling, and only invisible_dots covers it. Imprecise, but it eliminates two wrong answers.
The three bills you are actually comparing
When the decision arrives, stealth is not what is being compared. Each README answers a different question: how to avoid being recognised, how to make automation look less like automation, how an identity survives the month.
The budget line is where people underestimate. Not the license: all three are open source and cost nothing. invisible_dots costs machines, an x86 host or cloud instance with virtualisation enabled, and every identity is another slice of memory and disk. Camoufox costs people, because someone has to work through Firefox compatibility and follow upstream. Patchright costs luck: it is the cheapest, and its effectiveness depends on the other side not upgrading detection.
Maintenance is more concealed. Patchright means following Playwright and Chrome, fast cadence, small pieces. Camoufox means following Firefox, long cycles, hard fights. invisible_dots means following a whole system: VMs, containers, permissions, queue. When it breaks, the surface is wider. A small team cannot maintain all three. Maintaining one well is enough.
One line should not be crossed: the target site’s terms of service and robots.txt. Getting past Cloudflare technically does not grant the right to get past it. Collecting public data, accessing accounts you are entitled to, and using content you are authorised to use is one thing. Bypassing a login wall to bulk-copy someone’s library is another. The first may be an engineering problem. The second is a legal one.
So back to the script stuck at three in the morning. If the job is one-off, a few hundred pages, install Patchright, change the import, go to sleep. If it runs for months, carries identities and preserves login across weeks, stop patching the browser. Prepare a machine and accept its weight. Camoufox stands in between: a hard-to-recognise skin without a whole infrastructure to maintain.
All three work. Just do not expect one of them to quietly solve the other two’s problems.
Related reading
- CloakBrowser vs Playwright Stealth: Picking an Anti-Detect Browser
- Obscura Alternatives: Choosing a Headless Browser for Your AI Agent in 2026
- Amazon Is Shutting Down Mechanical Turk: The Machine That Hid Humans Inside Finally Doesnt Need Them
- Stagehand Alternatives for Browser Automation: A 2026 Production Comparison



