- Notifications
You must be signed in to change notification settings - Fork62
Collection of patches for puppeteer and playwright to avoid automation detection and leaks. Helps to avoid Cloudflare and DataDome CAPTCHA pages. Easy to patch/unpatch, can be enabled/disabled on demand.
rebrowser/rebrowser-patches
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This repo contains patches to enhance popular web automation libraries. Specifically, it targets thepuppeteer andplaywright packages.
Some aspects of automation libraries or browser behavior cannot be adjusted through settings or command-line switches. Therefore, we fix these issues by patching the library's source code. While this approach is fragile and may break as the libraries' source code changes over time, the goal is to maintain this repo with community help to keep the patches up to date.
Out of the box Puppeteer and Playwright come with some significant leaks that are easy to detect. It doesn't matter how good your proxies, fingeprints, and behaviour scripts, if you don't have it patched, you're just a big red flag for any major website.
🕵️ You can easily test your automation setup for major modern detections withrebrowser-bot-detector (sources and details)
| Before the patches 👎 | After the patches 👍 |
|---|---|
![]() | ![]() |
If you don't want to mess with the patches and all possible errors, there is a drop-in solution for you. These packages have simply applied rebrowser-patches on top of the original code, nothing more.
Puppeteer:rebrowser-puppeteer (src) andrebrowser-puppeteer-core (src)
Playwright (Node.js):rebrowser-playwright (src) andrebrowser-playwright-core (src)
Playwright (Python):rebrowser-playwright (src)
The easiest way to start using it is to fix yourpackage.json to use new packages but keep the old name as an alias. This way, you don't need to change any source code of your automation. Here is how to do that:
- Open
package.jsonand replace"puppeteer": "^23.3.1"and"puppeteer-core": "^23.3.1"with"puppeteer": "npm:rebrowser-puppeteer@^23.3.1"and"puppeteer-core": "npm:rebrowser-puppeteer-core@^23.3.1". Note: 23.3.1 is just an example, check the latest version onnpm. - Run
npm install(oryarn install)
Another way is to actually use new packages instead of the original one. Here are the steps you need to follow:
- Open
package.jsonand replacepuppeteerandpuppeteer-corepackages withrebrowser-puppeteerandrebrowser-puppeteer-core. Don't change versions of the packages, just replace the names. - Run
npm install(oryarn install) - Find and replace in your scripts any mentions of
puppeteerandpuppeteer-corewithrebrowser-puppeteerandrebrowser-puppeteer-core
🚀 That's it! Just visit therebrowser-bot-detector page and test your patched browser.
Our goal is to maintain and support these drop-in replacement packages with the latest versions, but we mainly focus on fresh versions, so if you're still using puppeteer 13.3.7 from the early 90s, it might be a good time to upgrade. There's a high chance that it won't really break anything as the API is quite stable over time.
Popular automation libraries rely on the CDP commandRuntime.Enable, which allows receiving events from theRuntime. domain. This is crucial for managing execution contexts used to evaluate JavaScript on pages, a key feature for any automation process.
However, there's a technique that detects the usage of this command, revealing that the browser is controlled by automation software like Puppeteer or Playwright. This technique isused by all major anti-bot software such as Cloudflare, DataDome, and others.
We've prepared a full article about our investigation on this leak, which you can read inour blog.
For more details on this technique, read DataDome's blog post:How New Headless Chrome & the CDP Signal Are Impacting Bot Detection.In brief, it's a few lines of JavaScript on the page that are automatically called ifRuntime.Enable was used.
Our fix disables the automaticRuntime.Enable command on every frame. Instead, we manually create contexts with unknown IDs when a frame is created. Then, when code needs to be executed, there are multiple ways to get the context ID.
🟢 Pros: The ultimate approach that keeps access to the main world and works with web workers and iframes. You don't need to change any of your existing codebase.
🔴 Cons: None are discovered so far.
🟢 Pros: All your code will be executed in a separate isolated world, preventing page scripts from detecting your changes via MutationObserver and other techniques.
🔴 Cons: You won't be able to access main context variables and code. While this is necessary for some use cases, the isolated context generally works fine for most scenarios. Also, web workers don't allow creating new worlds, so you can't execute your code inside a worker. This is a niche use case but may matter in some situations. There is a workaround for this issue, please readHow to Access Main Context Objects from Isolated Context in Puppeteer & Playwright.
This triggersRuntime.executionContextCreated events, allowing us to catch the proper context ID.
🟢 Pros: You will have full access to the main context.
🔴 Cons: There's a slight chance that during this short timeframe, the page will call code that leads to the leak. The risk is low, as detection code is usually called during specific actions like CAPTCHA pages or login/registration forms, typically right after the page loads. Your business logic is usually called a bit later.
🎉 Our tests show that all these approaches are currently undetectable by Cloudflare or DataDome.
Note: you can change settings for this patch on the fly using an environment variable. This allows you to easily switch between patched and non-patched versions based on your business logic.
REBROWSER_PATCHES_RUNTIME_FIX_MODE=addBinding— addBinding technique (default)REBROWSER_PATCHES_RUNTIME_FIX_MODE=alwaysIsolated— always run all scripts in isolated contextREBROWSER_PATCHES_RUNTIME_FIX_MODE=enableDisable— use Enable/Disable techniqueREBROWSER_PATCHES_RUNTIME_FIX_MODE=0— completely disable fix for this leakREBROWSER_PATCHES_DEBUG=1— enable some debugging messages
Remember, you can set these variables in different ways, for example, in code:
process.env.REBROWSER_PATCHES_RUNTIME_FIX_MODE="alwaysIsolated"
or in command line:
REBROWSER_PATCHES_RUNTIME_FIX_MODE=alwaysIsolated node app.js
By default, Puppeteer adds//# sourceURL=pptr:... to every script inpage.evaluate(). A remote website can detect this behavior and raise red flags.This patch changes it to//# sourceURL=app.js. You can also adjust it via environment variable:
# use any generic filenameREBROWSER_PATCHES_SOURCE_URL=jquery.min.js# use 0 to completely disable this patchREBROWSER_PATCHES_SOURCE_URL=0
Sometimes, it could be very useful to access a CDP session at a browser level. For example, when you want to implement some custom CDP command. There is a methodpage._client() that returns CDP session for the current page instance, but there is no such method for browser instance.This patch adds a new method_connection() to Browser class, so you can use it like this:
browser._connection().on('Rebrowser.addRunEvent',(params)=>{ ...})
Note: it's not detectable by external website scripts, it's just for your convenience.
The default utility world name is'__puppeteer_utility_world__' + packageVersion. Sometimes you might want to change it to something else. This patch changes it toutil and allows you to customize it via env variable:
REBROWSER_PATCHES_UTILITY_WORLD_NAME=customUtilityWorld# use 0 to completely disable this patchREBROWSER_PATCHES_UTILITY_WORLD_NAME=0This env variable cannot be changed on the fly, you have to set it before running your script because it's used at the moment when the module is getting imported.
| Before patch 👎 | After patch 👍 |
|---|---|
![]() | ![]() |
Note: it's not detectable by external website scripts, but Google might use this information in their proprietary Chrome; we never know.
This package is designed to be run against an installed library. Install the library, then call the patcher, and it's ready to go.
In the root folder of your project, run:
npx rebrowser-patches@latest patch --packageName puppeteer-coreYou can easily revert all changes with this command:
npx rebrowser-patches@latest unpatch --packageName puppeteer-coreYou can also patch a package by providing the full path to its folder, for example:
npx rebrowser-patches@latest patch --packagePath /web/app/node_modules/puppeteer-core-customYou can see all command-line options by runningnpx rebrowser-patches@latest --help, but currently, there's just one patch for one library, so you don't need to configure anything.
npm install oryarn install in your project folder, it might override all the changes from the patches. You'll need to run the patcher again to keep the patches in place.
If you already have your package patched and want to update to the latest version of rebrowser-patches, the easiest way would be to deletenode_modules/puppeteer-core, then runnpm install oryarn install --check-files, and then runnpx rebrowser-patches@latest patch.
All these versions are just wrappers around Node.js version of Playwright. You need to finddriver folder inside your Playwright package and run this patch with--packagePath=$yourDriverFolder/$yourPlatform/package.
✅ Latest fully tested version: 24.8.1 (released 2025-05-06)
Playwright patches include:
Runtime.enableleak:addBindingandalwaysIsolatedmodes.- Ability to change utility world name via
REBROWSER_PATCHES_UTILITY_WORLD_NAMEenv variable. - More patches are coming, star and follow the repo.
Important:page.pause() method doesn't work with the enabled fix, it needs more investigation. You can just disable the fix completely while debugging usingREBROWSER_PATCHES_RUNTIME_FIX_MODE=0 env variable.
These patches work only for Chrome for now. If you really want to use it with WebKit or Firefox, please open a new issue.
✅ Latest fully tested version: 1.52.0 (released 2025-04-17)
UseaddExtra method, here is the example:
// beforeimport puppeteer from 'puppeteer-extra'// afterimport { addExtra } from 'puppeteer-extra'import rebrowserPuppeteer from 'rebrowser-puppeteer-core'const puppeteer = addExtra(rebrowserPuppeteer)We're currently developing more patches to improve web automation transparency, which will be released in this repo soon. Please support the project by clicking ⭐️ star or watch button.
💭 If you have any ideas, thoughts, or questions, feel free to reach out to our team byemail or use theissues section.
Always keep in mind: the less you manipulate browser internals via JS injections, the better. There are ways to detect that internal objects such as console, navigator, and others were affected by Proxy objects or Object.defineProperty. It's tricky, but it's always a cat-and-mouse game.
If you've tried everything and still face issues, try asking a question in the issues section or consider using cloud solutions from Rebrowser.
This package is sponsored and maintained byRebrowser. We allow you to scale your browser automation and web scraping in the cloud with hundreds of unique fingerprints.
Our cloud browsers have great success rates and come with nice features such as notifications if your library usesRuntime.Enable during execution or has other red flags that could be improved.Create an account today to get invited to test our bleeding-edge platform and take your automation business to the next level.
When you try to run this patcher on a Windows machine, you will probably encounter an error because the patch command is not found. To fix this, you need to installGit, which includes patch.exe. After you have installed it, you need to add it to your PATH:
set PATH=%PATH%;C:\Program Files\Git\usr\bin\You can check that patch.exe is installed correctly by using next command:
patch -vzfcsoftware/puppeteer-real-browser - general ideas and contribution to the automation community
Kaliiiiiiiiii-Vinyzu/patchright - set of patches to fix Playwright leaks
kaliiiiiiiiii/brotector - some modern tests, algorithm to distinguish CDP vs devtools
prescience-data/harden-puppeteer - one of the pioneers of the execution in an isolated world
puppeteer-extra-plugin-stealth - where it all started, big props to all the contributors and the community 🙏 berstend and co are the goats
No responsibility is accepted for the use of this software. This software is intended for educational and informational purposes only. Users should use this software at their own risk. The developers of the software cannot be held liable for any damages that may result from the use of this software. This software is not intended to bypass any security measures, including but not limited to CAPTCHAs, anti-bot systems, or other protective mechanisms employed by websites. The software must not be used for malicious purposes. By using this software, you agree to this disclaimer and acknowledge that you are using the software responsibly and in compliance with all applicable laws and regulations.About
Collection of patches for puppeteer and playwright to avoid automation detection and leaks. Helps to avoid Cloudflare and DataDome CAPTCHA pages. Easy to patch/unpatch, can be enabled/disabled on demand.
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.




