
invisible_playwright v0.7.0
Sigilo de navegador antidetect gratuito para Playwright: huella digital de Firefox headless indetectable. Scraping en Python, bypass de recaptcha y detección de bots. Código abierto.
Playwright es detectado por los anti-bots y los captchas.
Este se ejecuta sobre un Firefox anti-detección con una huella no detectada, compatible con tu código Playwright existente.

Cómo funciona
Los anti-bots hacen dos preguntas, y reCAPTCHA, hCaptcha y Cloudflare Turnstile puntúan las respuestas. invisible_playwright responde que sí a ambas.
1. ¿Es este un navegador real? Sí. Es Firefox, parcheado a nivel del código fuente en C++.
- La huella del navegador se establece dentro del motor, no se inyecta en la página: navigator, screen, GPU/WebGL, canvas, fuentes, audio, WebRTC, zona horaria, red. En modo headless o con interfaz, los mismos valores en ambos casos.
- Sin shim de JS, sin override, sin costura que leer.
2. ¿Lo está usando una persona real? Sí. Las acciones están humanizadas en el driver.
- Cada clic, hover y arrastre sigue una trayectoria natural del ratón con tiempos humanos, sin cursor que se teletransporta.
- Cada entrada es idéntica byte a byte a la de un ratón real: fuente de entrada real, presión, eventos de confianza.
Instalación
Windows, en 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
Plataformas compatibles: Windows x86_64, Linux x86_64 / arm64.
Luego guarda uno de los ejemplos a continuación como main.py en my-project y ejecútalo con uv run main.py.
Uso
Huella aleatoria por sesión
La API de Playwright, síncrona y asíncrona, sin cambios en el código. Los mismos objetos, las mismas llamadas, los mismos valores de retorno. Algunas superficies quedan fuera del alcance —tracing, HAR, CDP, el contexto de solicitudes de la API— y cada una de ellas rechaza la operación con una frase que explica el motivo en lugar de comportarse de forma incorrecta de manera silenciosa. Si ya usas Playwright, cambiar es cuestión de dos líneas:
- 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:
Cada sesión obtiene una huella digital distinta (GPU, audio, fuentes, pantalla, ~200 campos) y movimiento del ratón con curvas de Bézier.
Sincronización
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
Asíncrono
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")
El objeto browser es un playwright.sync_api.Browser / playwright.async_api.Browser - cada método de Playwright funciona tal cual.
Registra la semilla para reproducir una ejecución:
sf = InvisiblePlaywright()
with sf as browser:
print("seed =", sf.seed)
# ...
Huella reproducible
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:
...
Esquemas compatibles: socks5, socks4, http, https. El DNS se enruta a través del proxy de forma predeterminada, sin fuga local.
Zona horaria
La zona horaria del navegador sigue a 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:
...
Fijar campos de huella digital específicos
Por defecto, todo proviene de seed. Para forzar valores específicos mientras el resto permanece derivado de la semilla:
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 de GPU selecciona una de las personas validadas en lugar de establecer una cadena libre, porque los ~81 valores de getParameter y la lista de extensiones viajan con el nombre del renderizador y un detector los verifica de forma cruzada contra él. Un nombre que el pool no contiene genera un error, y el error enumera los que sí contiene.
La lista completa de claves fijables, cómo interactúa el pinning con el muestreador bayesiano y los patrones comunes están en docs/pinning.md.
CLI
El comando instalado es invisible-playwright, con un guion. python -m invisible_playwright funciona de forma idéntica y no necesita nada en el 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