
invisible_playwright v0.7.0
Navigateur antidetect gratuit et furtif pour Playwright : empreinte Firefox headless non détectée. Scraping Python, contournement de recaptcha et de détection de bots. Open source.
Playwright se fait repérer par les anti-bots et les captchas.
Celui-ci fonctionne sur un Firefox anti-détection doté d'une empreinte indétectable, compatible avec votre code Playwright existant.

Fonctionnement
Les anti-bots posent deux questions, et reCAPTCHA, hCaptcha et Cloudflare Turnstile notent les réponses. invisible_playwright répond oui aux deux.
1. S'agit-il d'un vrai navigateur ? Oui. C'est Firefox, patché au niveau du code source C++.
- L'empreinte du navigateur est définie à l'intérieur du moteur, et non injectée dans la page : navigator, screen, GPU/WebGL, canvas, polices, audio, WebRTC, fuseau horaire, réseau. En mode headless ou headed, les mêmes valeurs dans les deux cas.
- Aucun shim JS, aucune surcharge, aucune couture à lire.
2. Une vraie personne l'utilise-t-elle ? Oui. Les actions sont humanisées dans le driver.
- Chaque clic, survol et glisser suit une trajectoire de souris naturelle avec un timing humain, sans curseur qui se téléporte.
- Chaque entrée est identique octet pour octet à une vraie souris : source d'entrée réelle, pression, événements de confiance.
Installation
Windows, dans PowerShell :
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
$env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
uv init --python ">=3.11" my-project
cd my-project
uv add invisible-playwright
uv run invisible-playwright fetch # one-time download, sha256-verified: 240 MB, about 550 MB unpacked
Linux :
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env
uv init --python ">=3.11" my-project
cd my-project
uv add invisible-playwright
uv run invisible-playwright fetch # one-time download, sha256-verified: 262 MB (x86_64) / 253 MB (arm64), about 550 MB unpacked
Plateformes prises en charge : Windows x86_64, Linux x86_64 / arm64.
Enregistrez ensuite l'un des exemples ci-dessous sous le nom main.py dans my-project et exécutez-le avec uv run main.py.
Utilisation
Empreinte aléatoire par session
L'API de Playwright, sync et async, sans aucune modification de code. Les mêmes objets, les mêmes appels, les mêmes valeurs de retour. Quelques surfaces sont hors périmètre - le tracing, HAR, CDP, le contexte de requête API - et chacune refuse avec une phrase expliquant pourquoi plutôt que de mal se comporter silencieusement. Si vous utilisez déjà Playwright, la bascule se fait en deux lignes :
- 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:
Chaque session obtient une empreinte distincte (GPU, audio, polices, écran, ~200 champs) et un mouvement de souris en courbe de Bézier.
Synchronisation
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
Asynchrone
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")
L'objet browser est un playwright.sync_api.Browser / playwright.async_api.Browser - chaque méthode Playwright fonctionne telle quelle.
Journalisez la graine pour rejouer une exécution :
sf = InvisiblePlaywright()
with sf as browser:
print("seed =", sf.seed)
# ...
Empreinte reproductible
with InvisiblePlaywright(seed=42) as browser:
... # same GPU, same canvas hash, same audio context, every run
Proxys
proxy = {
"server": "socks5://gate.example.com:1080",
"username": "user",
"password": "pass",
}
with InvisiblePlaywright(proxy=proxy) as browser:
...
Schémas pris en charge : socks5, socks4, http, https. Le DNS est routé via le proxy par défaut, sans fuite locale.
Fuseau horaire
Le fuseau horaire du navigateur suit 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:
...
Épingler des champs d'empreinte spécifiques
Par défaut, tout provient de seed. Pour forcer des valeurs spécifiques tandis que le reste reste dérivé de la seed :
with InvisiblePlaywright(
seed=42,
pin={
"gpu.renderer": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_5_0 ps_5_0, D3D11)",
"gpu.vendor": "Google Inc. (AMD)",
"screen.width": 2560,
"screen.height": 1440,
"hardware.concurrency": 16,
},
) as browser:
...
Un pin GPU sélectionne l'une des personas validées plutôt que de définir une chaîne libre, car les ~81 valeurs getParameter et la liste des extensions voyagent avec le nom du renderer et un détecteur les recoupe avec celui-ci. Un nom que le pool ne contient pas lève une erreur, et l'erreur liste ceux qu'il contient.
La liste complète des clés épinglables, la façon dont l'épinglage interagit avec l'échantillonneur bayésien, et les patrons courants se trouvent dans docs/pinning.md.
CLI
La commande installée est invisible-playwright, avec un trait d'union. python -m invisible_playwright fonctionne de manière identique et ne nécessite rien dans le 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