
Anti-detect browser stealth for Playwright: undetected headless Firefox fingerprint spoofing. Python web scraping and automation, Cloudflare, captcha and anti-bot detection bypass.

Los anti-bots hacen dos preguntas, y reCAPTCHA, hCaptcha y Cloudflare Turnstile puntúan las respuestas. invisible_playwright responde sí a ambas.
1. ¿Es un navegador real? Sí. Es Firefox, parcheado a nivel del código fuente en C++.
2. ¿Lo está usando una persona real? Sí. Las acciones están humanizadas en el driver.
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
Requiere Python 3.11 o superior.
Plataformas compatibles: Windows x86_64, Linux x86_64 / arm64.
La API de Playwright, sync y async, 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 peticiones de la API - y go_back() y go_forward() están retenidos por un defecto en las páginas restauradas; cada uno rechaza con una frase que explica por qué en lugar de comportarse mal en silencio. Si ya usas Playwright, cambiar son 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 distinta (GPU, audio, fuentes, pantalla, ~200 campos) y movimiento del ratón con curvas de Bezier.
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")
El objeto browser es un playwright.sync_api.Browser / playwright.async_api.Browser - todos los métodos de Playwright funcionan tal cual.
Registra la seed para reproducir una ejecución:
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:
...
Esquemas compatibles: socks5, socks4, http, https. El DNS se enruta a través del proxy por defecto, sin fuga local.
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:
...
Por defecto todo proviene de seed. Para forzar valores específicos mientras el resto sigue derivándose 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 de GPU elige 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 renderer y un detector los contrasta contra él. Un nombre que el pool no
contiene lanza un error, y el error lista 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.
El comando instalado es invisible-playwright, con 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
Si prefieres promptear en lugar de programar. Esta página es el motor, como
librería de Python. Dos formas de usarlo sin escribir código, ambas en una línea: desde un cliente
MCP que ya tengas (Claude Code, Claude Desktop, Cursor),
claude mcp add stealth -- uvx aihawk, consulta
la página del servidor MCP; o con una
interfaz y un modelo incluidos, necesitando solo una clave de OpenRouter,
uvx aihawk ui --openrouter-key sk-or-..., consulta
AIHawk. El mismo motor por debajo, y el segundo
es un cliente del primero.
Todo se lee mejor, y es buscable, en la wiki, organizada en cuatro secciones en lugar de una lista plana:
Si no sabes por dónde empezar: Tres formas de hacer Playwright indetectable es el mapa al que enlazan la mayoría de las otras páginas, Playwright detectado como bot en un sitio es el orden de resolución de problemas, y navigator.webdriver no es la señal que crees explica la propiedad más famosa de este ámbito y por qué parchearla sola no te aporta casi nada.
La sección de detectores ahora cubre los productos anti-bot comerciales por nombre, cada uno leído desde su propia documentación o desde ingeniería inversa confirmada: Cloudflare Bot Management y Turnstile, DataDome, Kasada, Akamai Bot Manager, PerimeterX, hCaptcha, Imperva, y el resto del conjunto.
Las otras piezas de este. El motor es el del medio de tres, y los dos que lo rodean son cómo la mayoría de la gente llega a él:
uvx aihawk, para cualquier cliente que traiga su propio
modelo) y, en el mismo paquete, una interfaz con un modelo incluido, desde
un solo comando. La interfaz es un cliente del servidor, sin ruta privada
al navegador.Los vecinos de código abierto. Cuál encaja depende de la capa en la que esté tu problema, y de si necesitas Firefox o Chromium: tres formas de hacer Playwright indetectable analiza qué puede alcanzar cada capa, y agentes de navegador con IA y sigilo cubre los frameworks que eligen Chromium sobre CDP por ti.
En el lado de Firefox
En el lado de Chromium
undetected-chromedriver, que controla Chrome a través de CDP. Comparativa.Runtime.enable. Comparativa.Dos reglas se mantienen en todo lo siguiente. Cada valor se decide antes de que una página pueda preguntar, dentro del navegador, así que no hay shim de JavaScript que encontrar. Y cada valor proviene de un solo perfil, así que ninguna superficie se contradice con otra, que es como normalmente se detecta un navegador falsificado. Código fuente: feder-cr/firefox_antidetect_patch.
Identidad
navigator, el user agent y los client hints se derivan juntos, así que no pueden contradecirse: ¿establece Playwright navigator.webdriver?, client hints y Sec-Fetch.navigator.languages y la cabecera Accept-Language son la misma declaración, enviada y leída: Accept-Language y navigator.languages.devicePixelRatio y las media queries que la exponen se declaran, no se leen del host: devicePixelRatio y la pref de Firefox, fingerprinting por media queries CSS.Renderizado
measureText devuelve más de diez números en una sola llamada, sin prompt de permiso: measureText y TextMetrics.Audio y medios
Red
La capa de automatización
isTrusted es true porque lo es: clics de Playwright e isTrusted.null: shadow roots cerrados.MIT - consulta LICENSE. El binario parcheado de Firefox se distribuye bajo la MPL-2.0 (licencia upstream de Firefox). Los parches en C++ contra mozilla-central que producen ese binario están en feder-cr/firefox_antidetect_patch.
Este proyecto es solo para fines educativos. Se proporciona tal cual, sin garantías. No asumo ninguna responsabilidad por cómo se utilice. Úsalo bajo tu propio riesgo y cumpliendo las leyes de tu jurisdicción.
Built by Federico Elia
playwright-python. De qué va esa recomendación.