invisible_playwright_mcp

feder-crMIT活跃维护

基于 Playwright 的 MCP 服务器,让 AI Agent 在反检测隐身 Firefox 上浏览网页,绕过反爬和验证码,适合自动化抓取与求职等场景。

Playwright MCP server undetected by anti-bots and captchas: AI agent browses the web on anti-detect stealth Firefox, Python, undetected browser automation, scraping, computer use.

v0.73.0发布于 2026-10-21 13:51 UTC878star +3 / 7 天117fork同步于 2026-11-10 23:53 UTC

怎么上手

由 README 提炼,执行前请确认
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env
uvx invisible-playwright-mcp ui --openrouter-key sk-or-...
硬件要求按 README 说明

README 未说明显存或 GPU 要求;引擎为 Firefox 浏览器二进制,首次启动时从 GitHub release 下载,也可用 --binary 指定已装好的同版本引擎。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

基于反检测 Firefox 的 Playwright MCP 浏览器代理,让 AI 助手在反爬和验证码站点上像真人一样操作网页

基于 Playwright 的 MCP 服务器,让 AI Agent 在反检测隐身 Firefox 上浏览网页,绕过反爬和验证码,适合自动化抓取与求职等场景。

核心能力

  • 以 MCP 插件形式接入 Claude Code、Codex、Gemini CLI
  • 用反检测 stealth Firefox 引擎驱动页面,规避反爬识别
  • 提供独立 Web UI,左侧对话右侧实时浏览器画面
  • 支持 --proxy 让时区、语言和出口 IP 跟随代理
  • 用 --seed 固定浏览器指纹,--profile-dir 保留登录态

容易踩的坑

首次启动需联网从 GitHub release 下载引擎,代理场景还会下载 GeoIP 数据库;--binary 指定的引擎必须与固定版本一致,否则启动直接拒绝;Web UI 默认监听 127.0.0.1:8765 且无鉴权,改 host 会暴露接口;命令行传 --openrouter-key 会留在 shell 历史和进程列表中,建议改用环境变量或 .env。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.73.0
  1. v0.73.00.73.0最新正式版2026-10-21 · 2026-10-21 13:51 UTC

    0.73.0: the floor rises to invisible-playwright 0.41.0, the first wrapper sealed to firefox-51

  2. v0.72.30.72.32026-10-17 · 2026-10-17 17:51 UTC
    查看更新说明

    The floor moves to invisible-playwright 0.37.0 (invisible-core 49.44.0, firefox-49), where the snapshot and every read run in the caller's world.

    • A page that replaces getBoundingClientRect keeps its replacement in its own world and no longer reaches the snapshot: the element is measured with the real method and listed. No script can reach the unmeasurable count any more, the caller's included (measured), so its test drives the count through the snapshot's own source with the measuring made to give nothing.
    • A navigation that the previous page's own replace stops answers NS_BINDING_ABORTED, an honest answer upstream Playwright gives as well. The tests admit it only with the page then really on /landed, and the snapshot read right after it may meet the previous page still in place only when the navigation was stopped or overtaken.
    • The minimise test runs in a visible session: headless=True puts the window on a hidden desktop that EnumWindows does not see, and only a visible window can be minimised by a person. On firefox-49 the capture outlives the minimise, so this arm proves the window is watched again; the restart keeps its clock tests.
    • The server builds its engine through one function, process_engine(env), and the one-reader test asks it and plan.engine_here of the same environment.
  3. v0.72.20.72.22026-10-13 · 2026-10-13 19:26 UTC
    查看更新说明
    • 0.72.2: the snapshot and read_html read again on the page that replaced the one they went to

    invisible-playwright 0.35.2 sends the caller's code once: page.evaluate raises Playwright's navigation error when the page moves under it, because a script waiting on a promise ran twice when it was sent again (B285). The snapshot and read_html are this package's fixed reads without effects, and they reached the page through page.evaluate; they ask page.evaluate_read now, which reads again on the page that replaced the one it went to. browser_evaluate, the model's code, stays on page.evaluate and runs once. The floor moves to invisible-playwright>=0.35.2.

    test_read_text_after_a_page_moves_on.py reads each of them first after its own navigation on the seven pages that replace themselves; a unit test says which door each tool takes.

    • 0.72.2: the floor moves to invisible-playwright 0.35.4, where a page that replaces itself keeps its main world

    On 0.35.2 this PR's e2e failed on /head for the snapshot and read_html: "Page.evaluate_read: the main world never appeared for frame mainframe-9. Worlds seen: ['ctx_aux']". The engine announced only the utility world of the document that replaced the one navigated to, and a read in the page's own world waited 30 s for one that never came (B286). firefox-42, through invisible-core 42.39.0 and invisible-playwright 0.35.4, keeps it. Measured with 0.35.6 (core 44.39.0) under Xvfb 1920x1080: the redirect e2e 29 passed, the floor test 2 passed.

  4. v0.72.10.72.12026-10-12 · 2026-10-12 12:38 UTC
    查看更新说明

    The owner's rule of 2026-10-12: a cap only where a real constraint asks for it, never a fixed number out of habit. Three were left that nothing asked for:

    • browser_type quoted what the field kept up to 120 characters and then "...". Those sentences exist to say how the field differs from what was typed, and a page that reformats a long value makes the difference anywhere in it.
    • A turn that failed said the exception's detail up to 200 characters. The detail is kept because it is the only clue when the cause is real, and a provider's JSON error names the cause past that point.
    • The four 503 answers of the panes' routes cut their reason at 200 characters. One function writes that answer now, whole.

    Each has a test that turns red when its cap is put back.

  5. v0.72.00.72.02026-10-12 · 2026-10-12 05:19 UTC
    查看更新说明

    No answer is cut any more. browser_read_text stopped at 6000 characters with a line asking for a larger max_chars, browser_evaluate and the browser listing became {"truncated": true, "preview": ...} above the same number, and browser_snapshot dropped elements from the end. max_chars is gone from both tools, with DEFAULT_MAX_CHARS, json_capped and capped_elements; a caller who wants less narrows the selector. The limits clean.py applies to the HTML stay.

    browser_read_text right after browser_navigate, on a page that replaces itself, failed with "Failed to find execution context" 9 times in 10: it counted, then evaluated on the first match, and the page moved on between the two. It now finds and reads in one call, with the selector still resolved by the engine.

    The floor moves to invisible-playwright 0.35.0 (invisible-core 41.36.0): a read caught by a navigation is made again on the page that took its place, and a navigation the previous page's own redirect beats answers at once, naming where the browser went, instead of after the 45 s timeout. browser_navigate's description says what that answer means.

    The docs' tool-cost figures are measured again on 0.72.0 with their own published method: 17 tools, 9,207 characters of description, 3,497 tokens of complete definitions, median 189 per tool.

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Two ways to use this browser agent

    1. From your assistant, over MCP

    Windows, in PowerShell:

    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
    $env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
    

    Linux:

    curl -LsSf https://astral.sh/uv/install.sh | sh
    source $HOME/.local/bin/env
    

    Then install it in your assistant.

    Claude Code:

    claude plugin marketplace add feder-cr/invisible_playwright_mcp
    claude plugin install invisible-playwright-mcp@feder-cr
    

    Codex:

    codex plugin marketplace add feder-cr/invisible_playwright_mcp
    codex plugin add invisible-playwright-mcp@feder-cr
    

    Gemini CLI:

    gemini extensions install https://github.com/feder-cr/invisible_playwright_mcp
    

    2. Standalone: the web UI

    We bring the interface, you bring an OpenRouter key. Chat on the left, the live browser on the right.

    Windows, in PowerShell:

    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
    $env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
    uvx invisible-playwright-mcp ui --openrouter-key sk-or-...
    

    Linux:

    curl -LsSf https://astral.sh/uv/install.sh | sh
    source $HOME/.local/bin/env
    uvx invisible-playwright-mcp ui --openrouter-key sk-or-...
    

    Then open http://127.0.0.1:8765 and type the same thing.


    What to ask a web browsing agent

    Anything that needs real web automation: a browser rather than an API, and a person's judgement about what is on the page.

    Go to <paste the URL>. One way, Milan to Lisbon, economy, one checked bag, one adult. Check every date from the 12th to the 16th of next month, one at a time, and read the cheapest fare for each day. The date field is a calendar widget, so click the days rather than typing them. If a date has no availability, say so. Do not guess a number.

    It drives the page the way a person would: the pointer moves, keys are pressed.

    Options: proxy, profile, seed

    • --openrouter-key Your key, or the OPENROUTER_API_KEY variable.
    • --model An OpenRouter model id, or INVISIBLE_MCP_MODEL. Defaults to z-ai/glm-5.3-flash.
    • --proxy Optional. http://user:[email protected]:8080 or socks5://proxy.example.com:1080. Host and port are both required. The timezone, locale and egress follow it.
    • --binary An engine binary you already have. It must be the build the seal pins, or startup refuses: this skips the download, not the version check.
    • --seed An integer. Same seed, same browser identity, every run.
    • --profile-dir A directory to keep the profile in, so logins and cookies survive restarts.
    • --headed Show the browser window. The interface shows you the page anyway.
    • --host, --port 127.0.0.1 and 8765. Changing the host exposes an interface that has no authentication.

    A .env beside the command

    Rather than retyping the key and the binary path, put them in a .env in the directory you run from:

    OPENROUTER_API_KEY=sk-or-...
    STEALTHFOX_BINARY=/path/to/firefox
    

    It is read at startup, and on the way in it never overrides something already set, so the order is --flag > the environment > .env > the default. Only the directory you are in is read - there is no search upwards, so running from a subfolder cannot silently pick up a different key. The startup line names the variables it applied and never prints their values.

    Passing --openrouter-key puts the key in your shell history, and on Linux in the process list. OPENROUTER_API_KEY in the environment or in a .env avoids both.

    The wiki: AI browser-agent guides

    The reading room around the agent lives in the wiki: the AI browser-agent landscape: browser-use, Operator-style and computer-use agents compared, what to check when an agent gets blocked, and what happened to OpenAI Operator, among others. Worked examples, transcripts and their outputs live in articles/.

    The rest of the family: engine, core

    The MCP server from option 1 ships inside this package: invisible_playwright_mcp with no subcommand is the server, invisible-playwright-mcp ui the interface. Its config blocks for clients that take a file, its settings and its tools are on the wiki page The MCP server.

    • invisible_playwright The engine, as a Python library, for writing code instead of prompts. The API is Playwright's.
    • invisible_core Seed to fingerprint to preferences, proxy and geolocation.

    Using it responsibly

    This automates a browser under your control. Read the terms of the sites you point it at, respect their rate limits, and do not submit anything a human has not read.

    Privacy Policy

    This browser agent runs on your machine and has no server of its own. What leaves your computer, and to whom:

    • The sites you visit see the browser, as they would any Firefox.
    • Your model provider. The web UI sends the conversation and what the agent reads on the page to OpenRouter under your key. Over MCP, the client you plugged it into does the same with whichever model it uses.
    • GitHub. The engine is downloaded from a GitHub release the first time the server or the interface starts, and a GeoIP database is when a proxy is set. Each browser launch also fetches a one-line counter file from a GitHub release, which is how launches are counted: the request carries no identifier and nothing of yours, and GitHub sees what any HTTPS request shows, your IP address.

    Nothing else is collected and nothing is sent to the author. Sessions, profiles and screenshots are stored locally, under INVISIBLE_MCP_HOME if set and otherwise in the application-data directory of your system, and are yours to delete; nothing is retained anywhere else. Questions go to the issues.

    License

    MIT. Everything distributed before 2 September 2026 was released under AGPL-3.0 and stays under it.