Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
invisible_playwright — Playwright that anti-bots cannot see, so no captchas: same API, anti-detect stealth headless Firefox, undetected fingerprint, bypass bot detection, Python web scraping and browser automation. | Kitploit
工具/GitHubGitHub/feder-cr/invisible_playwright
IDS/IPS EvasionImpersonation ToolsWeb SecurityAnti-BotFingerprint SpoofingCAPTCHA Bypass
GitHubfeder-cr/invisible_playwright

invisible_playwright

Playwright that anti-bots cannot see, so no captchas: same API, anti-detect stealth headless Firefox, undetected fingerprint, bypass bot detection, Python web scraping and browser automation.

查看仓库
1.8k2013463小时33分前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
内容在请求的语言中不可用。显示英文版本。
invisible_playwright, Playwright on an anti-detect Firefox. An animation: the two-line switch from Playwright, the fingerprint set inside the engine, a mouse that moves like a hand, and the bot tests it passes.

browser launches engine downloads GitHub stars

Playwright gets caught by anti-bots and captchas.
This one runs on an anti-detect Firefox with an undetected fingerprint, compatible with your existing Playwright code.

invisible_playwright - 5/5 detection suites passed

How it works

Anti-bots ask two questions, and reCAPTCHA, hCaptcha and Cloudflare Turnstile score the answers. invisible_playwright answers yes to both.

1. Is this a real browser? Yes. It is Firefox, patched at the C++ source level.

  • The browser fingerprint is set inside the engine, not injected into the page: navigator, screen, GPU/WebGL, canvas, fonts, audio, WebRTC, timezone, network. Headless or headed, the same values either way.
  • No JS shim, no override, no seam to read.

2. Is a real person using it? Yes. The actions are humanized in the driver.

  • Every click, hover and drag follows a natural mouse path with human timing, no teleporting cursor.
  • Each input is byte-identical to a real mouse: real input source, pressure, trusted events.

Install

Windows, in 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, about 550 MB unpacked

Supported platforms: Windows x86_64, Linux x86_64. Linux arm64 is no longer supported from firefox-56 (firefox-55 is the last engine built for it).

Then save one of the examples below as main.py in my-project and run it with uv run main.py.


Usage

Random fingerprint per session

Playwright's API, sync and async, with no code changes. The same objects, the same calls, the same return values. A few surfaces are out of scope - tracing, HAR, CDP, the API request context - and each one refuses with a sentence saying why rather than misbehaving quietly. If you already use Playwright, switching is two lines:

- 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:

Every session gets a distinct fingerprint (GPU, audio, fonts, screen, ~200 fields) and Bezier-curve mouse motion.

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

The browser object is a playwright.sync_api.Browser / playwright.async_api.Browser - every Playwright method works as-is.

Log the seed to replay a run:

sf = InvisiblePlaywright()
with sf as browser:
    print("seed =", sf.seed)
    # ...

Reproducible fingerprint

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:
    ...

Schemes supported: socks5, socks4, http, https. DNS is routed through the proxy by default, no local leak.

Serving one browser to many clients

launch_server() serves one browser on a WebSocket to any Playwright client. Install the extra that carries the WebSocket library with uv add "invisible-playwright[remote]".

# server.py
from invisible_playwright import launch_server

with launch_server(seed=42, headless=True) as server:
    print(server.ws_endpoint)          # ws://127.0.0.1:<port>/<secret>
    input("serving, press Enter to stop")
# client.py: any Playwright client; this one is Playwright for Python (uv add playwright)
import sys
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.firefox.connect(sys.argv[1])      # the address the server printed
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()                               # ends this client; the server's browser keeps running

The server listens on 127.0.0.1 with a random secret path; host=, port= and path= choose another address. A client in another language (Node, Java, .NET, Go) connects to the same address with the connect call of its own Playwright. The browser belongs to the server and ends with server.close() (or with the with block).

On Linux, set MALLOC_ARENA_MAX=2 in the environment of the process that runs it (glibc keeps a memory arena per thread otherwise); the server already hands freed memory back with malloc_trim (INVPW_MALLOC_TRIM=0 turns that off).

下载工具