Patches and plugins that make an automated browser look less automated: stealth plugin sets for Puppeteer and Playwright, CDP-leak fixes, drivers that remove the driver, and the cursor and header libraries that sit alongside them. Everything here is a layer applied to somebody else's stack, which is the single most important property to keep in mind while reading it.
Patches and plugins for Puppeteer, Playwright and Selenium, plus the proxies and cursor libraries that sit beside them.
Why NRND: pushed_at = 2024-07-18 — 757 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2024-07-18
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
7400
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/berstend/puppeteer-extra
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Still the most-copied answer on the internet and two years without a push. That gap is the single best argument for this catalogue existing. — ED.
Why ACTIVE: pushed_at = 2026-08-05 — 9 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-05
archived
false
latest_release
v1.61.1 · 2026-06-23
license.spdx_id
Apache-2.0
stargazers_count
4100
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Kaliiiiiiiiii-Vinyzu/patchright
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-08-09 — 5 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-09
archived
false
latest_release
—
license.spdx_id
Apache-2.0
stargazers_count
1500
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Kaliiiiiiiiii-Vinyzu/patchright-python
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why NRND: pushed_at = 2025-05-09 — 462 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2025-05-09
archived
false
latest_release
—
license.spdx_id
null (none declared)
stargazers_count
1400
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/rebrowser/rebrowser-patches
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ARCHIVED: archived = true, set 2025-09-28. A maintainer's own statement outranks every date rule.
Field
Value at this printing
pushed_at
—
archived
true
archived_at
2025-09-28
latest_release
—
license.spdx_id
null (none declared)
stargazers_count
163
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Kaliiiiiiiiii-Vinyzu/CDP-Patches
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Archived by its own author, which is a maintainer's statement and outranks any inference from a push date. Listed as historical because the technique still explains what the protocol gives away. — ED.
Why NRND: pushed_at = 2025-07-05 — 405 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2025-07-05
archived
false
latest_release
—
license.spdx_id
GPL-3.0
stargazers_count
12800
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/ultrafunkamsterdam/undetected-chromedriver
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why SEMI: pushed_at = 2026-05-13 — 93 days, inside the 90–365 day SEMI band.
Field
Value at this printing
pushed_at
2026-05-13
archived
false
latest_release
none published
license.spdx_id
AGPL-3.0
stargazers_count
4700
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/ultrafunkamsterdam/nodriver
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-08-14 — 0 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-14
archived
false
latest_release
v4.51.12 · 2026-08-10
license.spdx_id
MIT
stargazers_count
12900
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/seleniumbase/SeleniumBase
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why SEMI: pushed_at = 2026-04-04 — 132 days, inside the 90–365 day SEMI band.
Field
Value at this printing
pushed_at
2026-04-04
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
263
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Mattwmaster58/playwright_stealth
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why NRND: pushed_at = 2024-07-29 — 746 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2024-07-29
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
981
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/AtuboDad/playwright_stealth
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-07-15 — 30 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-07-15
archived
false
latest_release
—
license.spdx_id
GPL-3.0
stargazers_count
1000
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Vinyzu/Botright
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why NRND: pushed_at = 2025-04-25 — 476 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2025-04-25
archived
false
latest_release
—
license.spdx_id
NOASSERTION
stargazers_count
861
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/ttlns/Selenium-Driverless
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-07-22 — 23 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-07-22
archived
false
latest_release
—
license.spdx_id
NOASSERTION
stargazers_count
12300
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/g1879/DrissionPage
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-07-16 — 29 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-07-16
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
15200
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/FlareSolverr/FlareSolverr
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-08-13 — 1 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-13
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
2500
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/sarperavci/CloudflareBypassForScraping
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why NRND: pushed_at = 2024-07-15 — 760 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2024-07-15
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
92
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/daijro/hazetunnel
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-08-11 — 3 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-11
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
1600
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/Xetera/ghost-cursor
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why NRND: pushed_at = 2024-11-28 — 624 days, inside the 365–1095 day NRND band.
Field
Value at this printing
pushed_at
2024-11-28
archived
false
latest_release
—
license.spdx_id
MIT
stargazers_count
503
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/riflosnake/HumanCursor
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why SEMI: pushed_at = 2026-02-26 — 169 days, inside the 90–365 day SEMI band.
Field
Value at this printing
pushed_at
2026-02-26
archived
false
latest_release
—
license.spdx_id
Apache-2.0
stargazers_count
1200
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/daijro/browserforge
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why ACTIVE: pushed_at = 2026-08-06 — 8 days, within the 90-day ACTIVE threshold.
Field
Value at this printing
pushed_at
2026-08-06
archived
false
latest_release
v2.1.88 · 2026-08-05
license.spdx_id
Apache-2.0
stargazers_count
2600
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/apify/fingerprint-suite
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
Why SEMI: pushed_at = 2026-01-28 — 198 days, inside the 90–365 day SEMI band.
Field
Value at this printing
pushed_at
2026-01-28
archived
false
latest_release
—
license.spdx_id
GPL-3.0
stargazers_count
2500
http_status
200
fetched_at
2026-08-14T09:12:00Z
rubric_edition
2nd, in force
Endpoint: GET https://api.github.com/repos/QIN2DIM/hcaptcha-challenger
unauthenticated · 60 req/hr
A live read does not change what is printed above it. The site records that you ran it; what GitHub returned is not kept. The printed state moves only when the register is swept and a new printing is issued. raw JSON
The protocol tells and the page tells are different problems
There are two families in this section and they address different layers. The older family works inside the page: a script runs before the document loads and overwrites the properties a detector reads — the webdriver flag, the plugin array, the languages list, the WebGL vendor strings. That approach can only reach what JavaScript can reach, and it leaves its own residue where it does.
The newer family works at the protocol. Driving a browser over the DevTools Protocol changes the browser's own behaviour in ways no page script can undo — the well-known case being an execution-context call that a driven browser makes and an ordinary one does not. Fixing that requires patching the driver or the browser rather than the page, which is why several entries here are forks of Playwright and Puppeteer rather than plugins for them.
Why the push dates in this section decay faster than anywhere else
Every entry here is bound to something it does not control. A stealth plugin is bound to a browser's release cadence; a patch set is bound to a specific driver version; an input-simulation library is bound to whatever behavioural model the other side is currently fitting. When the thing underneath moves, the layer on top either moves with it or quietly stops working while continuing to install cleanly.
That is why this section carries the highest concentration of NRND marks in the catalogue, and why several of them are on projects with substantial visibility. The pattern repeats with unsettling regularity: an author writes the canonical tool, the tool accumulates every tutorial link in the field, the author moves to a successor, and the original keeps being recommended for years afterwards by lists with no check date.
NRND — Not Recommended for New Designs. Works; do not start here.
7 here
ARCHIVED — The maintainer closed it. Historical reference only.
1 here
Questions about automation stealth patches
Answered from the fields printed above, and from nothing this register has not checked.
Why do stealth plugins stop working?
Because they patch a moving target from outside it. A plugin overwrites the properties a known detector reads; when the browser changes, or the detector reads something else, the patch set is silently incomplete. The package still installs and still runs, which is exactly what makes the failure hard to notice.
What is the Runtime.enable leak?
A tell introduced by the DevTools Protocol rather than by the page: driving a browser over CDP has historically involved a call that an ordinary browsing session does not make, and its side effects are observable from inside the page. Several entries in this section exist specifically to remove it, and one of them shipped a written explanation that remains a clear public account of the mechanism.
Is patched Playwright better than a stealth plugin?
They address different layers, and this register does not rate one against the other. A patched driver can fix protocol-level tells that a page script cannot reach; a plugin is easier to adopt and does not bind you to a driver fork. Read the state and licence columns, and decide against your own constraints.
Donut Browser is filed in section 01 of this same catalogue, under the
same rubric, with the same fields printed against it and no exemption:
an open-source anti-detect browser under AGPL-3.0 whose Wayfern Chromium
fork applies fingerprint overrides at engine level over CDP rather than
by patching page JavaScript, with a local REST API and MCP server on your
own machine, self-hostable sync, zero telemetry, and a pre-launch gate
that refuses to start a profile when the proxy's exit geography
contradicts the profile's fingerprint. It is judged here the same way
everything in this section is judged.