Retour aux mises à jour
New releaseSep 18, 2026

invisible_playwright v0.20.0

Playwright que les anti-bots ne peuvent pas voir, donc pas de captchas : même API, Firefox headless furtif anti-détection, empreinte indétectable, contournement de la détection de bots, scraping web et automatisation de navigateur en Python.

Partager
invisible_playwright

Playwright se fait repérer par les anti-bots et les captchas.
Celui-ci tourne sur un Firefox anti-détection avec une empreinte non détectée, compatible avec votre code Playwright existant.

invisible_playwright - 5/5 detection suites passed

Comment ça marche

Les anti-bots posent deux questions, et reCAPTCHA, hCaptcha et Cloudflare Turnstile notent les réponses. invisible_playwright répond oui aux deux.

1. Est-ce 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, pas 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.
  • Pas de shim JS, pas de surcharge, aucune couture à lire.

2. Est-ce une vraie personne qui l'utilise ? Oui. Les actions sont humanisées dans le driver.

  • Chaque clic, survol et glisser suit un trajet de souris naturel avec un timing humain, pas de curseur qui se téléporte.
  • Chaque entrée est identique au bit près à une vraie souris : source d'entrée réelle, pression, événements de confiance.

Installation

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

Nécessite Python 3.11 ou plus récent.

Plateformes prises en charge : Windows x86_64, Linux x86_64 / arm64.


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 - tracing, HAR, CDP, le contexte de requête API - et chacune refuse avec une phrase expliquant pourquoi plutôt que de mal se comporter en silence. 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.

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")

L'objet browser est un playwright.sync_api.Browser / playwright.async_api.Browser - chaque méthode Playwright fonctionne telle quelle.

Journalisez la seed 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

Proxies

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, aucune 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 de getParameter et la liste d'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, comment l'épinglage interagit avec l'échantillonneur bayésien, et les motifs courants se trouvent dans docs/pinning.md.


CLI

La commande installée est invisible-playwright, avec un tiret. python -m invisible_playwright fonctionne de manière identique et n'a besoin de 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

Documentation, guides et comparaisons

Si vous préférez le prompt au script. Cette page est le moteur, en tant que bibliothèque Python. Deux façons de l'utiliser sans écrire de code, toutes deux en une ligne : depuis un client MCP que vous avez déjà (Claude Code, Claude Desktop, Cursor), claude mcp add stealth -- uvx aihawk, voir la page du serveur MCP ; ou avec une interface et un modèle inclus, ne nécessitant qu'une clé OpenRouter, uvx aihawk ui --openrouter-key sk-or-..., voir AIHawk. Le même moteur en dessous, et le second est un client du premier.

Tout cela se lit mieux, et est consultable, dans le wiki, organisé en quatre sections au lieu d'une liste plate :

Catégories