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

Os anti-bots fazem duas perguntas, e o reCAPTCHA, o hCaptcha e o Cloudflare Turnstile pontuam as respostas. O invisible_playwright responde sim a ambas.
1. Isto é um navegador real? Sim. É o Firefox, com patches ao nível do código-fonte C++.
2. Uma pessoa real está a usá-lo? Sim. As ações são humanizadas no 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
Requer Python 3.11 ou mais recente.
Plataformas suportadas: Windows x86_64, Linux x86_64 / arm64.
A API do Playwright, sync e async, sem alterações ao código. Os mesmos objetos, as mesmas chamadas, os mesmos valores de retorno. Algumas superfícies estão fora do âmbito - tracing, HAR, CDP, o contexto de pedidos da API - e go_back() e go_forward() estão retidos por um defeito em páginas restauradas; cada um recusa com uma frase a dizer porquê em vez de se comportar mal em silêncio. Se já usa o Playwright, a mudança são duas linhas:
- 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 sessão recebe um fingerprint distinto (GPU, áudio, fontes, ecrã, ~200 campos) e movimento do rato em 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")
O objeto browser é um playwright.sync_api.Browser / playwright.async_api.Browser - todos os métodos do Playwright funcionam tal como estão.
Registe a seed para repetir uma execução:
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 suportados: socks5, socks4, http, https. O DNS é encaminhado através do proxy por predefinição, sem fuga local.
O fuso horário do navegador segue 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 predefinição, tudo vem da seed. Para forçar valores específicos enquanto o resto permanece derivado da 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:
...
Um pin de GPU escolhe uma das personas validadas em vez de definir uma string livre,
porque os ~81 valores de getParameter e a lista de extensões viajam com o
nome do renderer e um detetor cruza-os com ele. Um nome que o pool não
contém gera erro, e o erro lista os que contém.
A lista completa de chaves fixáveis, como o pinning interage com o amostrador Bayesiano, e padrões comuns estão em docs/pinning.md.
O comando instalado é invisible-playwright, com hífen. python -m invisible_playwright funciona de forma idêntica e não precisa de nada no 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
Se prefere fazer prompts em vez de escrever scripts. Esta página é o motor, como
biblioteca Python. Duas formas de o usar sem escrever código, ambas numa linha: a partir de um cliente
MCP que já tem (Claude Code, Claude Desktop, Cursor),
claude mcp add stealth -- uvx aihawk, veja
a página do servidor MCP; ou com uma
interface e um modelo incluídos, precisando apenas de uma chave OpenRouter,
uvx aihawk ui --openrouter-key sk-or-..., veja
AIHawk. O mesmo motor por baixo, e o segundo
é um cliente do primeiro.
Tudo isto lê-se melhor, e é pesquisável, na wiki, organizada em quatro secções em vez de uma lista plana:
Se não sabe por onde começar: Três formas de tornar o Playwright indetetável é o mapa para o qual a maioria das outras páginas aponta, Playwright detetado como bot num site é a ordem de resolução de problemas, e navigator.webdriver não é o indício que pensa que é explica a propriedade mais famosa nesta área e porque corrigi-la sozinha vale quase nada.
A secção de detetores cobre agora os produtos anti-bot comerciais por nome, cada um lido a partir da sua própria documentação ou de engenharia reversa confirmada: Cloudflare Bot Management e Turnstile, DataDome, Kasada, Akamai Bot Manager, PerimeterX, hCaptcha, Imperva, e o resto do conjunto.
As outras peças deste. O motor é o do meio de três, e os dois à sua volta são como a maioria das pessoas lá chega:
uvx aihawk, para qualquer cliente que traga o seu próprio
modelo) e, no mesmo pacote, uma interface com um modelo incluído, a partir
de um comando. A interface é um cliente do servidor, sem caminho privado
para o navegador.Os vizinhos de código aberto. Qual encaixa depende da camada em que o seu problema está, e de precisar de Firefox ou Chromium: três formas de tornar o Playwright indetetável percorre o que cada camada consegue alcançar, e agentes de navegador de IA e stealth cobre os frameworks que escolhem Chromium em vez de CDP por si.
Do lado do Firefox
Do lado do Chromium
undetected-chromedriver, a controlar o Chrome via CDP. Comparação.Runtime.enable. Comparação.playwright-python. Sobre o que é essa recomendação.Duas regras aplicam-se a tudo o que se segue. Cada valor é decidido antes de uma página o poder perguntar, dentro do navegador, para que não haja um shim de JavaScript para encontrar. E cada valor vem de um único perfil, para que nenhuma superfície contradiga outra, que é como um navegador falsificado é normalmente apanhado. Código-fonte: feder-cr/firefox_antidetect_patch.
Identidade
navigator, o user agent e os client hints são derivados em conjunto, para que não possam discordar: o Playwright define navigator.webdriver, client hints e Sec-Fetch.navigator.languages e o cabeçalho Accept-Language são a mesma declaração, enviada e lida: Accept-Language e navigator.languages.devicePixelRatio e as media queries que o expõem são declarados, não lidos do host: devicePixelRatio e a pref do Firefox, fingerprinting por CSS media query.Renderização
measureText devolve mais de dez números numa só chamada, sem pedido de permissão: measureText e TextMetrics.Áudio e media
Rede
A camada de automação
isTrusted seja verdadeiro porque é verdadeiro: cliques do Playwright e isTrusted.null: shadow roots fechados.MIT - veja LICENSE. O binário do Firefox com patches é distribuído sob a MPL-2.0 (licença upstream do Firefox). Os patches em C++ contra o mozilla-central que produzem esse binário estão em feder-cr/firefox_antidetect_patch.
Este projeto é apenas para fins educativos. É fornecido tal como está, sem garantias. Não assumo qualquer responsabilidade pela forma como é usado. Use-o por sua conta e risco e em conformidade com as leis da sua jurisdição.
Built by Federico Elia