Privacy Tech

Puppeteer Real Browser Alternatives 2026: 6 OSS Tools Compared

BC

BotCloud Team

May 4, 2026·13 min read

The Short Answer

There are six actively-shipping open-source libraries in the "undetected Puppeteer / Playwright" niche in 2026. Each one solves a different slice of the detection signal space. None of them solve all of it, because the surfaces they cannot reach (engine-level fingerprints, CDP-side runtime artifacts, TLS-layer signals) are upstream of where any patched-driver library can act. Engine-level builds — Chromium forks where the patches are baked into the C++ source — handle the full stack but ship as a binary distribution rather than an npm package.

This post walks through the six, what each one is good at, where each one still fails, and a decision tree at the end.

The Six Libraries, By the Numbers

The npm and PyPI registries tell you which projects are actually getting patches in 2026 and which are coasting. The data below is from npm view, pip metadata, and the GitHub releases API on 2026-05-05:

LibraryLanguageLatestLast ReleaseWhat it forks
patchright (Node)Node1.59.42026-04-09Playwright
patchright (Python)Python1.59.12026-04-29Playwright
rebrowser-puppeteer-coreNode24.8.12025-05-09Puppeteer
puppeteer-real-browserNode1.4.42025-09-03Puppeteer wrapper
nodriverPython0.48.12025-11-09(no driver — direct CDP)
camoufoxBinary + Python wrapperv146-hardware (beta), 0.4.11 wrapper2026-03-14 (binary), 2025-01-29 (wrapper)Firefox
@ulixee/heroNode2.0.0-alpha.342025-09-08(own browser stack)

The release-recency column is the one to read first. patchright is the only project shipping monthly into 2026. nodriver and puppeteer-real-browser are on a 6-9 month cadence. rebrowser-puppeteer-core last shipped about a year ago. @ulixee/hero has been on 2.0.0-alpha for over half a year. Camoufox stable is a year stale; the active work is in beta tags.

This matters because detection vendors ship updates on a monthly cadence. A library that has not released in 12 months has a 12-month detection-vector backlog by definition.

What Each One Actually Does

patchright

A maintained Playwright fork in Node and Python. The fork's value-add is renaming and removing the runtime artifacts that vanilla Playwright leaves on window (__playwright__binding__, the various init-script globals) and trimming the CDP attachment to be quieter. Same Playwright API, drop-in replacement for playwright in most scripts. Active monthly releases through April 2026.

What it does not change: the underlying Chromium binary. Canvas, audio, WebGL, font metrics, and TLS fingerprint are whatever stock Chromium ships. If your detection target is reading those, patchright alone does not move the needle.

rebrowser-puppeteer-core

The same idea as patchright but for Puppeteer. Renames CDP-side globals, fixes a handful of framework-attribution surfaces, exposes the standard Puppeteer API. Pairs with rebrowser-patches, a separate companion repo that holds patches against the Puppeteer source tree. Last npm release was 2025-05-09, so the active surface there has gone roughly a year without a published update — a long time in this space.

puppeteer-real-browser

A wrapper, not a fork. It launches a real Chrome (the user's installed Chrome, not a downloaded Chromium) via Puppeteer-extra, applies stealth patches, and exposes a Puppeteer-compatible page handle. Easier to install than a fork, but inherits the structural problems of the puppeteer-extra-stealth chain it sits on top of: JavaScript-layer patching, with the patch-shape detectability that comes with that. Last release 2025-09-03.

nodriver

Python. The successor to undetected-chromedriver. It does not use the WebDriver protocol at all — it speaks CDP directly to Chromium, sidestepping the WebDriver-specific tells (the cdc_* window globals, the WebDriver flag in navigator). Last release 2025-11-09.

The price for ditching WebDriver is that you do not get the Selenium/Playwright API surface. You write code against nodriver's own primitives. It is a smaller, lower-level library.

camoufox

A Firefox fork, not a Chromium one. The patches are at the Firefox engine layer: canvas randomization, audio context noise, WebGL rendering surface mutation, font enumeration scrambling. Distributed as a forked binary, with a Python wrapper for orchestration. Stable releases (2025-03 last) are aging; active work is in beta tags through early 2026.

The catch: it is Firefox. Most detection in 2026 is calibrated against Chrome user agents and Chrome-shaped fingerprints. A Firefox build with engine-level patches is technically excellent but lands in a position where it has to either claim to be Firefox (small market share, more suspicious to vendors who tune against Chrome distributions) or claim to be Chrome through user-agent spoofing (which fails the consistency checks that look at navigator properties, JS engine quirks, and TLS fingerprint together).

@ulixee/hero

A complete rebuild — Hero is its own browser stack, not a Puppeteer or Playwright fork. The thesis is that the entire automation surface (CDP layer, navigator surface, behavior emulation) needs to be rebuilt cleanly rather than patched. Ambitious, but as of 2026-05 it is on 2.0.0-alpha.34 and has been in alpha for an extended period. Not the right pick for production stacks that need a stable API today.

The Detection Signal Matrix

The way to compare these is not "which is best" — it is "which signals does each one cover". The table below maps each library to the major signal classes detection vendors check. "Yes" means the library has explicit work in that area. "Partial" means some patches exist but coverage is known-incomplete. "No" means out of scope for that library's design.

Signal classpatchrightrebrowserpuppeteer-real-browsernodrivercamoufox@ulixee/hero
Framework artifacts (__playwright__, cdc_*)YesYesPartialYesN/AYes
navigator.webdriverYesYesYesYesYesYes
CDP-injected runtime globalsYesYesNoYesN/AYes
Canvas fingerprintNoNoNoNoYesPartial
Audio context fingerprintNoNoNoNoYesPartial
WebGL renderer/vendorNoNoNoNoYesPartial
Font enumerationNoNoNoNoYesNo
TLS / JA4 fingerprintNoNoNoNoNoNo
Sec-CH-UA Client Hints consistencyNoNoNoNoPartialNo
Behavioral (mouse, timing)NoNoNoNoNoPartial

The pattern: the patched-driver libraries (patchright, rebrowser, nodriver) share a column. They handle framework and CDP surfaces; they do not touch engine-level fingerprints because those live below the layer they patch. Camoufox covers engine-level Firefox surfaces but has nothing for the Chrome-side framework surfaces (because it is not Chromium-based). No library in this list addresses TLS fingerprint, because TLS happens below the browser layer entirely — it is a function of the network stack and is read by the server before any browser code runs.

Three Structural Approaches

Stepping back from individual libraries, there are three structural approaches in this space, and the tradeoffs between them matter more than the differences between libraries within the same approach.

Approach 1: Plugin Injection (Dead)

puppeteer-extra-plugin-stealth and the Python playwright-stealth port. Load vanilla Chromium; inject JavaScript patches at runtime. Last release of the canonical plugin was 2023-03. The detection ecosystem has shipped roughly 36 months of new signatures since. Coverage is frozen at the 2023 surface, the project does not respond to new-vector issues, and the patch-shape problem (Function.prototype.toString audits, Reflect.ownKeys order) has matured on the detection side.

This category is here only because it is what most legacy stacks still run. The migration is to one of the next two approaches.

Approach 2: Patched Driver

A fork of Puppeteer or Playwright, plus surgical patches against the Chromium attachment surface. Examples: patchright, rebrowser-puppeteer-core, nodriver.

Strength: handles the framework-attribution and CDP-runtime classes cleanly, because the patches are at the right layer to do that. Drop-in API for Puppeteer or Playwright code.

Limit: the underlying Chromium is unchanged. Canvas, audio, WebGL, font metrics — whatever stock Chromium ships, the detection script reads. Detection vendors who fingerprint at the engine layer go through patched drivers.

Approach 3: Patched Browser

A forked browser binary with engine-level patches in the C++ source. Examples: Camoufox on the Firefox side; Chromium-based managed builds on the Chrome side.

Strength: the suspicious surfaces are not "patched", they are absent or replaced at the engine layer. navigator.webdriver is removed from the source code, so there is no override shape, no enumeration tell, no timing window. Canvas and audio fingerprints come from per-context profiles loaded at the engine, so the values are internally consistent rather than randomized per-call.

Cost: shipping and maintaining a forked Chromium (or Firefox) through the upstream's monthly major releases. Most teams will not do that themselves, which is why these projects exist as binary distributions or managed services rather than as npm packages.

Where Each Library Still Fails

Honest version, lib by lib:

patchright — Same Chromium as vanilla Playwright. A detection script that reads canvas hash, AudioContext fingerprint, or WebGLRenderingContext.getParameter(UNMASKED_RENDERER_WEBGL) gets the stock-Chromium values. Patchright does not ship per-context profile loading. If your target's detection includes engine-level fingerprint depth, patchright handles only the framework slice.

rebrowser-puppeteer-core — Same engine constraint as patchright, plus the more concerning issue that the npm release cadence has slowed. A library on a 12-month gap is shipping no fixes for the detection signatures that arrived in those 12 months.

puppeteer-real-browser — Sits on top of puppeteer-extra-plugin-stealth. Inherits all the structural issues of JavaScript-layer patching: patch shapes, CDP-injected globals out of scope, asymmetric pace against detection vendors. The "real browser" name describes that it launches the user's installed Chrome rather than a downloaded one — it does not mean engine-level patches are present.

nodriver — Direct CDP without WebDriver is a real win for the WebDriver-flag class of signals, but the underlying browser is still vanilla Chromium. Engine-level fingerprints are unchanged from default Chrome. Smaller API surface than Selenium or Playwright, so existing code does not port for free.

camoufox — Engine-level work is real, but it is Firefox. Most detection in 2026 is tuned against Chrome distributions; presenting as Firefox is a more suspicious starting position with most vendors. User-agent spoofing back to Chrome breaks consistency with the JS engine identity and other Firefox-shaped tells. Stable releases are aging into beta-only status.

@ulixee/hero — Long-running alpha. Ambitious scope (custom browser stack, behavior emulation, cluster orchestration) means a wide surface to mature. Not the right pick if you need a production stack today.

Decision Tree

If you are picking a stealth automation stack in 2026, work the questions in this order:

  1. Is your target's detection concentrated on framework artifacts? (navigator.webdriver, CDP-injected __playwright__binding__, the WebDriver cdc_* cluster, framework-attributable globals on window) — A patched driver handles this. Pick patchright for Playwright-style code or rebrowser-puppeteer-core for Puppeteer; pick nodriver if you are in Python and willing to use a smaller API.

  2. Does your target read engine-level fingerprints? (canvas hash, AudioContext fingerprint, WebGL renderer, font enumeration, hardware concurrency consistency) — A patched driver is insufficient. You need a patched browser. If Firefox is acceptable, Camoufox. If you need Chrome-shaped output, a managed Chromium build is the practical option (self-hosting a Chromium fork through monthly upstream releases is rarely worth it for most teams).

  3. Does your target use Cloudflare's higher Bot Fight tiers, or DataDome, or FingerprintJS Pro? — Plan for the full stack: engine-level browser, residential proxy with clean reputation, behavior pacing that does not look automated. None of these alone is sufficient against the top tier of detection. The active-solver vs passive-pass tradeoff becomes the next decision.

  4. Are you running this at scale, with profile rotation, on infrastructure? — At that point the relevant question is no longer which library, but who maintains the patched Chromium build through monthly upstream releases. That is a managed-service decision. Self-hosting an engine-level fork at scale takes a dedicated team.

What "Engine-Level" Buys Against What

The argument for engine-level patching, made specifically against the patched-driver approach: any property that gets overridden in JavaScript leaves a shape. Object.defineProperty(navigator, 'webdriver', { get: () => undefined }) is detectable through Function.prototype.toString audits, through Reflect.ownKeys enumeration, through the timing of when the override fired relative to other page-init events. Patched drivers reduce the surface (they avoid the obvious overrides where they can) but they cannot remove what Chromium itself ships.

When the C++ Chromium build has navigator.webdriver removed from the source, it is genuinely absent — no override shape, no timing tell. When the C++ build does not install __playwright__binding__ to begin with, no race condition can leak it. The plugin and patched-driver categories defend by deleting; the engine category defends by never setting.

This is the same reason camoufox's canvas patches are stronger than any JavaScript-layer canvas spoof: the values come from inside the engine's rendering path, internally consistent, not randomized by a JS hook that runs after getContext('2d') is already called.

Quick FAQ

Q: Is patchright better than nodriver?

They solve different things. Patchright is a Playwright fork in Node and Python; nodriver is a Python-only library that bypasses WebDriver entirely by talking CDP directly. If you need the Playwright API and you are in Node, patchright is the only option of the two. If you are in Python and want the smallest detection surface specifically for the WebDriver-flag class of signals, nodriver is the better fit. Neither one addresses engine-level fingerprints — for that you need a patched browser, regardless of which patched driver you pick.

Q: Why did the stealth plugin approach fail?

Three structural reasons. (1) Asymmetric pace: a community plugin maintained in spare time cannot keep up with detection vendors who ship weekly. (2) Patch shapes: any JavaScript-layer override leaves enumeration/toString/timing tells that detection scripts can read. (3) CDP-injected globals are upstream of where any plugin can act — Chromium itself installs __playwright__binding__ before any page JS runs, and a plugin can only delete it after the fact, which is a race the detection script wins.

Q: What is the engine-level approach?

A forked browser binary (Chromium or Firefox) where the suspicious surfaces are removed or replaced at the C++ source level. Examples: Camoufox on the Firefox side, with Chromium-based options available as managed builds. Trade-off: you lose npm-package install convenience and gain a binary distribution. You also gain coverage of fingerprint surfaces that no patched driver can touch.

Q: Does any of this matter against TLS/JA4 fingerprinting?

No. TLS fingerprint is read at the network layer, before browser code runs. Patched drivers and patched browsers both ride on whatever TLS stack the binary was compiled against, so against JA4 you need either a residential proxy that re-terminates TLS or a network layer (e.g., a custom HTTP client) that adjusts the ClientHello directly. This is out of scope for any of the libraries discussed here.

Q: I have a working puppeteer-extra-plugin-stealth stack. Should I migrate?

Not urgently if your targets still pass. The plugin's existing patches do not stop working when the package stops releasing. Migrate when you start seeing CAPTCHA frequency rise on previously-clean targets, when new targets fail outright, or when you encounter a detection vendor whose 2024+ signatures the plugin has no patch for. Start with rebrowser-puppeteer-core or patchright as the lowest-friction step; escalate to a patched browser if engine-level fingerprints are the issue.

Bottom Line

The OSS undetected-Puppeteer space in 2026 is six libraries split across two structural approaches: patched drivers (patchright, rebrowser-puppeteer-core, puppeteer-real-browser, nodriver, @ulixee/hero) and patched browsers (camoufox). Patched drivers are the right pick when your detection target is framework artifacts and CDP-injected globals; they are insufficient when the target reads engine-level fingerprints. Patched browsers are the right pick for the engine-level case but ship as binary distributions rather than npm packages, and the only currently-active OSS one is Firefox-based.

If you need the Chromium-shaped engine-level path with a managed binary and a per-context fingerprint API on top of the standard Puppeteer/Playwright surface, BotCloud provides that.

#puppeteer#playwright#stealth#automation#open-source

Share this post