Why Playwright and Puppeteer stealth plugins stop working
You install a stealth plugin, rerun a public bot test, and the red warnings turn green. Then you open the site you actually need and get a CAPTCHA, a 403, or a login loop anyway.
Sometimes the setup never works. Sometimes it runs for months and stops after a browser or target-site update. That makes it tempting to say the plugin is broken.
Usually, the more useful explanation is that the plugin controls only one part of the browser session. Modern detection can also look at the automation driver, the browser engine, the network, the profile, and the behavior produced by your script.
Quick answer: Playwright and Puppeteer stealth plugins can still hide basic automation indicators. They are not a complete anti-detection layer, and passing a public checker does not prove that the whole session looks consistent to a production anti-bot system.
What a stealth plugin actually changes
The best-known Node option is puppeteer-extra-plugin-stealth, which can also be used through playwright-extra. Its current source enables 16 evasions. They cover familiar surfaces such as:
navigator.webdriver- plugins and MIME types
- languages and permissions
- WebGL vendor and renderer values
- user agent and platform values
- selected Chrome APIs, iframe behavior, and window dimensions
Calling all of these “JavaScript patches after page load” would be inaccurate. Some evasions change browser launch arguments. Others use init scripts that run in a new document before the site’s normal JavaScript executes.
But an early init script is still an init script. It can change values exposed to the page; it cannot rewrite every browser subsystem or control how Playwright communicates with Chromium.
The Python package playwright-stealth is also not simply the frozen Node plugin under another import. It began as a port, but its current maintainer has added features and changed the API. Version 2.0.3 was released in April 2026. Its own documentation describes it as a proof-of-concept for simpler bot detection, which is a useful description of the category: helpful within a limited scope, not a universal bypass.
Why stealth plugins stop being enough
There is rarely one magic property that explains every block. A plugin can fail for several different reasons, and stacking more overrides helps only when the missing signal is actually in the JavaScript layer.
1. The target checks more surfaces than the plugin covers
A fixed set of evasions can hide a fixed set of signals. A production detection system can combine many more: canvas and audio output, installed fonts, graphics capabilities, screen and hardware values, browser features, storage history, request patterns, and interaction timing.
This does not mean every site checks all of them. It means a plugin can pass a short public checklist while leaving other parts of the session untouched.
2. The values do not form one believable device
Individual values can look reasonable and still contradict one another. A Windows user agent, a macOS-like graphics stack, Linux fonts, an unusual screen configuration, and a proxy in another timezone do not describe one ordinary device.
Good stealth projects try to preserve property descriptors, native-looking functions, and cross-frame behavior. That work matters. It still becomes harder as more properties are overridden and browsers add new APIs. Consistency across the entire identity is a broader problem than hiding navigator.webdriver.
3. The automation driver sits outside the plugin
Playwright and Puppeteer control Chromium through the Chrome DevTools Protocol. A page-level plugin cannot change the commands the driver sends, the launch defaults it selects, or every internal object it creates.
Projects such as rebrowser-patches and Patchright work at this layer. They modify Playwright or Puppeteer behavior around execution contexts, launch flags, bindings, utility worlds, and other framework-level artifacts.
Runtime.enable is one widely discussed example, but it should not be treated as a timeless yes-or-no bot test. Chromium changes, and detection techniques that worked against an older release may stop working in a newer one. The durable point is simpler: an init script cannot repair a signal created by the automation driver itself.
4. The browser is only one part of the session
A clean browser fingerprint cannot rescue an IP address with poor reputation. A residential proxy cannot make a fresh profile look like a returning account. Neither one can make instant clicks, impossible typing speed, or aggressive request volume look normal.
When a stealth plugin appears to have stopped working, the actual change may be somewhere else:
- the proxy pool or IP reputation
- cookies, local storage, or account history
- headless and container configuration
- browser version and operating-system consistency
- navigation, typing, clicking, or request timing
- a selector or application flow that broke and only looks like blocking
Before changing tools, compare the same workflow under controlled conditions. The full diagnostic process is covered in Playwright detected as bot.
Maintenance matters, but age is not the whole argument
The last commit affecting puppeteer-extra-plugin-stealth in its official repository was published on March 1, 2023. That is a real maintenance concern for code coupled to browser internals. Chrome and anti-bot systems have continued changing since then.
The Python package tells a different story: playwright-stealth received multiple 2.x releases in 2025 and 2026. It is actively maintained, but its maintainer still does not claim that it handles advanced detection.
This distinction matters. Old code is more likely to miss new browser behavior, but age alone does not prove that a session will be detected. A current plugin can still operate at the wrong layer for the problem you have.
JS plugins, driver patches, and patched browsers
These approaches are related, but they do different jobs.
| Approach | What it changes | Where it helps | What it does not solve by itself |
|---|---|---|---|
| Stealth plugin | Selected page-visible values, init scripts, and some launch options | Basic headless and automation checks | Browser-engine fingerprints, most driver behavior, network identity, profile history, and user behavior |
| Driver patch or Playwright fork | How Playwright or Puppeteer launches and controls the browser | Framework and CDP-related artifacts outside page-level plugins | A broad, internally consistent device fingerprint, proxy reputation, and behavior |
| Source-patched browser | Fingerprint and automation-related behavior compiled into the browser engine | Signals that cannot be reliably changed from an init script | Some framework-originated artifacts that require driver-side changes, plus IP reputation, account history, and behavior |
The rows are not mutually exclusive. A source-patched browser can also address some automation signals, and a driver patch can ship improved launch defaults. The right question is not “Which tool is undetectable?” It is “Which layer is producing the signal?”
When each approach makes sense
Use a stealth plugin when: the target performs basic checks, the job is low-risk, and you want the smallest change to an existing script. A plugin may be entirely sufficient for that case.
Look at driver patches when: browser-level protections are already in place, but a remaining difference appears to originate in Playwright or Puppeteer itself. Browser and driver fixes can overlap; Patchright and rebrowser-patches are designed to address the framework side of that overlap.
Use a source-patched browser when: the target evaluates a broader browser fingerprint and maintaining a growing collection of JavaScript overrides is no longer reliable.
Treat the whole stack as production infrastructure when: the workflow matters enough that proxy quality, profile persistence, browser updates, monitoring, and interaction patterns need to be controlled together.
Do not install three overlapping stealth packages and assume the combination must be stronger. Conflicting overrides can make the resulting identity less coherent and make failures harder to diagnose.
Where CloakBrowser fits
CloakBrowser takes the source-patched browser approach. Its core fingerprint and automation changes are compiled into a custom Chromium build instead of being implemented primarily as JavaScript overrides on top of stock Chrome.
The wrapper keeps a familiar Playwright and Puppeteer workflow:
from cloakbrowser import launch
browser = launch(humanize=True)
page = browser.new_page()
page.goto("https://example.com")
browser.close()
That broader browser-level coverage removes the need for a separate stealth plugin, but it does not make the rest of the session irrelevant. Proxy reputation, geography, profile continuity, account history, and behavior remain separate inputs. Some driver-level signals can also depend on exactly how the browser is launched or attached.
The practical advantage is not invisibility. It is moving core browser identity work into the layer that owns those values, while keeping the automation API developers already use.
Try CloakBrowser with the workflow that is failing, or start with the quickstart.
Frequently asked questions
Is puppeteer-extra-plugin-stealth dead?
It has not received a source update in its official stealth-plugin directory since March 2023, but that does not make every evasion useless. It can still help against basic checks. The problem is relying on it as complete protection against systems that examine signals outside its scope.
Is playwright-stealth enough in 2026?
It depends on the target. The current Python package is maintained and can hide several common indicators, but its own documentation says not to expect it to bypass more than simple bot detection. Treat it as one layer, not a complete browser identity.
Does Patchright replace a stealth plugin?
Patchright changes the Playwright driver layer and its defaults. That can remove signals a page-level plugin cannot reach. It does not automatically give stock Chromium a complete alternative fingerprint or solve proxy, profile, and behavioral problems.
Is Runtime.enable still detectable?
It has been the basis of documented CDP detection techniques, and current driver-patching projects still account for it. But the observable behavior has changed across Chromium versions. Do not use one historical Runtime.enable test as proof that every current Playwright session is detectable in the same way.
Do I still need a proxy?
If the target evaluates IP reputation, location, ASN, or request volume, yes. For other targets, a proxy may be unnecessary. Browser identity and network identity are separate layers and should be tested separately.
Does a source-patched browser make automation undetectable?
No. It provides control over browser-engine signals that JavaScript plugins cannot reliably own. The complete session can still be challenged because of its driver, network, profile, account, or behavior.
What holds up
Stealth is not a package checkbox. It is a coverage problem.
A JavaScript plugin can be useful without being sufficient. A driver patch can close framework-level gaps without changing the browser’s broader identity. A source-patched browser can control deeper signals without fixing a bad proxy or an implausible workflow.
When a Playwright stealth setup stops working, do not begin by adding another override. Find the layer that changed, then use the smallest tool that actually controls it.