
Free antidetect browser stealth for Playwright: undetected headless Firefox fingerprint. Python scraping, recaptcha and bot detection bypass. Open source

Anti-bots ask two questions, and reCAPTCHA, hCaptcha and Cloudflare Turnstile score the answers. invisible_playwright answers yes to both.
1. Is this a real browser? Yes. It is Firefox, patched at the C++ source level.
2. Is a real person using it? Yes. The actions are humanized in the driver.
And one thing the stock driver cannot do. Playwright's own documentation says
"Closed-mode shadow roots are not supported", and measured on 2026-09-05 against a page
carrying one open and one closed root, stock Playwright returned zero matches for the
closed content in Firefox and in Chromium alike. This engine returns the element, while
the page still reads null from element.shadowRoot, so nothing observable to the page
changes. The three-arm table and the page that reproduces it:
closed shadow roots.
Driven by the standard Playwright API. Full breakdown: feder-cr/firefox_antidetect_patch.
Once the browser is handled it stops being the variable. If you are still getting challenged, the tell is no longer the browser, it is the IP you come from. Around 90% of proxies are public: anyone can rent the same address, so it is already known and sits on the blocked-IP lists sites check. A perfect browser on a known IP still loses.
pip install invisible-playwright
python -m invisible_playwright fetch # one-time download, sha256-verified: 240 MB (Windows) / 262 MB (Linux x86_64) / 253 MB (Linux arm64), about 550 MB unpacked
Requires Python 3.11 or newer.
Supported platforms: Windows x86_64, Linux x86_64 / arm64. macOS is no longer supported (releases stopped at firefox-20); on a Mac the package refuses at launch with a clear message rather than downloading a binary that no longer exists.
This page is the engine, as a Python library. There are two ways to use it without writing code, and both are one line:
claude mcp add stealth -- uvx invisible-playwright-mcp. See
invisible-playwright-mcp.uvx aihawk ui --openrouter-key sk-or-.... See
AIHawk.Same engine underneath, and the second is a client of the first.
100% Playwright-compatible - sync and async, all methods, zero API changes. If you already use Playwright, switching is two lines:
- from playwright.sync_api import sync_playwright
- with sync_playwright() as p:
- browser = p.firefox.launch()
+ from invisible_playwright import InvisiblePlaywright
+ with InvisiblePlaywright() as browser:
Every session gets a distinct fingerprint (GPU, audio, fonts, screen, ~200 fields) and Bezier-curve mouse motion.
Sync
from invisible_playwright import InvisiblePlaywright
with InvisiblePlaywright(proxy={"server": "socks5://...", "username": "u", "password": "p"}) as browser:
page = browser.new_page()
page.goto("https://example.com")
page.click("#submit") # mouse arcs to the button on a Bezier curve
Async
from invisible_playwright.async_api import InvisiblePlaywright
async with InvisiblePlaywright(proxy={"server": "socks5://...", "username": "u", "password": "p"}) as browser:
page = await browser.new_page()
await page.goto("https://example.com")
await page.click("#submit")
The browser object is a playwright.sync_api.Browser / playwright.async_api.Browser - every Playwright method works as-is.
Log the seed to replay a run:
sf = InvisiblePlaywright()
with sf as browser:
print("seed =", sf.seed)
# ...
with InvisiblePlaywright(seed=42) as browser:
... # same GPU, same canvas hash, same audio context, every run
proxy = {
"server": "socks5://gate.example.com:1080",
"username": "user",
"password": "pass",
}
with InvisiblePlaywright(proxy=proxy) as browser:
...
Schemes supported: socks5, socks4, http, https. DNS is routed through the proxy by default, no local leak.
The browser timezone follows timezone=:
# default: timezone is auto-derived from the egress IP (proxy egress if a
# proxy is set, otherwise the host's own public IP)
with InvisiblePlaywright(proxy=proxy) as browser:
...
# explicit IANA zone always wins, the only way to force a specific zone
with InvisiblePlaywright(proxy=proxy, timezone="America/New_York") as browser:
...
By default everything comes from seed. To force specific values while the rest stays seed-derived:
with InvisiblePlaywright(
seed=42,
pin={
"gpu.renderer": "ANGLE (NVIDIA, NVIDIA GeForce RTX 4090 Direct3D11)",
"gpu.vendor": "Google Inc. (NVIDIA)",
"screen.width": 2560,
"screen.height": 1440,
"hardware.concurrency": 16,
},
) as browser:
...
Full list of pinnable keys, how pinning interacts with the Bayesian sampler, and common patterns are in docs/pinning.md.
The installed command is invisible-playwright, with a hyphen. python -m invisible_playwright works identically and needs nothing on PATH.
invisible-playwright fetch # download the engine if missing, check every cached
# one against the seal, print the path
invisible-playwright version # wrapper, core and engine versions, and where the
# engine is cached
All of it reads better, and is searchable, in the wiki, organised into four sections instead of one flat list:
If you don't know where to start: Three ways to make Playwright undetected is the map most other pages link back to, Playwright detected as a bot on one site is the troubleshooting order, and navigator.webdriver is not the tell you think it is explains the most famous property in this space and why patching it alone buys you almost nothing.
The detectors section now covers the commercial anti-bot products by name, each read from its own documentation or from confirmed reverse engineering: Cloudflare Bot Management and Turnstile, DataDome, Kasada, Akamai Bot Manager, PerimeterX, hCaptcha, Imperva, and the rest of the set.
The other pieces of this one. The engine is the middle of three, and the two around it are how most people reach it:
The open-source neighbours, and what each one is for.
On the Firefox side
On the Chromium side
undetected-chromedriver, driving Chrome over CDP directly and removing the WebDriver-flavoured tells. Full comparison.playwright-python instead; what that recommendation is actually about.Runtime.enable CDP leak on Chromium, independently converging on close to the same fix Patchright uses. Full comparison.Which of these fits depends on the layer your problem is at, and on whether you need Firefox or Chromium. Three ways to make Playwright undetected works through what each layer can and cannot reach, including what this one costs.
If you are picking between engines rather than tools, note that a large share of AI agent frameworks drive Chromium over CDP, which decides the question for you: AI browser agents and stealth.
MIT - see LICENSE. The patched Firefox binary is distributed under the MPL-2.0 (Firefox upstream license). The C++ patches against mozilla-central that produce that binary are at feder-cr/firefox_antidetect_patch.
This project is for educational purposes only. It is provided as-is, with no warranties. I take no responsibility for how it is used. Use it at your own risk and in compliance with the laws of your jurisdiction.
Built by Federico Elia