关于 cdpilot
cdpilot 是一个零依赖的命令行浏览器自动化工具,直接通过原始 CDP 控制浏览器,无需 Puppeteer、Playwright 或 Selenium。适合 AI 代理与开发者在本地执行浏览器操作。
主要功能
- 01零依赖,基于 CDP over HTTP 实现
- 02提供 70 余条命令,覆盖导航、交互与截图
- 03每个项目使用独立的浏览器实例与端口
- 04支持 iframe 内元素的定位
- 05支持扩展开发所用的 Chrome for Testing
适用场景
- 01通过命令行快速打开页面并截图
- 02在隔离的浏览器配置中执行自动化脚本
- 03为 Claude Code 等工具提供浏览器操作能力
MCP 相关
该项目提供 MCP 服务(npx cdpilot mcp),向 MCP 客户端暴露其浏览器命令,供 AI 代理调用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
cdpilot
从终端实现零依赖的浏览器自动化。一条命令,全面掌控。
快速开始
npx cdpilot launch # Start browser with CDP
npx cdpilot go https://example.com
npx cdpilot shot # Take screenshot
无需配置文件,无需样板代码。只需运行 npx 即可开始。
为什么选择 cdpilot?
AI Agent 和开发者需要一种开箱即用的浏览器控制方式:
- 零配置 —
npx cdpilot launch即可启动隔离的浏览器会话 - 零依赖 — 无需 Puppeteer、Playwright 或 Selenium。通过 HTTP 使用纯 CDP
- 70 多条命令 — 支持导航、点击、输入、截图、网络、控制台、无障碍、视频理解、渐进式反机器人韧性等
- 适合 AI Agent — 专为 Claude、GPT、Gemini 及任何大模型工具调用工作流设计
- 隔离会话 — 不会影响你的个人浏览器。cdpilot 使用独立配置运行
- 可视化反馈 — 绿色发光叠加层、光标可视化、点击涟漪和按键显示,让你随时了解自动化进度
- 多项目隔离 — 每个项目都会自动获得独立的浏览器实例和端口,互不冲突
- AI 控制警告 — 自动化运行期间,将鼠标悬停时会出现红色提示通知
- 隐私优先 — 所有操作均在本地运行。数据不会离开你的设备
浏览器选择(根据工作负载自动选择)
cdpilot 会根据你的操作选择合适的浏览器。auto(默认)采用双轴策略 — 扩展工作负载 × 平台稳定性:
| 你的工作负载 | 自动选择顺序 |
|---|---|
已注册扩展(ext-install) | vivaldi → brave → edge → chromium → chrome(→ Chrome for Testing,如果已安装) |
| 无扩展(纯自动化) | chrome → vivaldi → edge → chromium → brave |
可随时覆盖:
cdpilot browser # show current pick + reason
cdpilot browser vivaldi # pin to Vivaldi
cdpilot browser chrome-for-testing # pin to Chrome for Testing (after installing it, below)
cdpilot browser auto # restore smart default
为什么要区分?
- Chrome 137+ 会静默忽略非打包扩展的
--load-extension(无错误、无警告)——Google 已从品牌版 Chrome 构建中移除此功能 (说明)。 已验证 —chrome://extensions显示 0 个项目。 - Vivaldi、Brave、Edge、Chromium 和 Chrome for Testing 均支持
--load-extension(已测试)。 - 在 macOS 26 (Tahoe) 上,Brave 1.89 会在运行约 7 分钟后稳定崩溃 (ThreadPoolForegroundWorker 中出现 SIGTRAP)。在修复版 Brave 发布前,cdpilot 会检测操作系统并自动降低 Brave 的优先级。
每个浏览器都有独立的配置文件(如 ~/.cdpilot/.../profile-vivaldi),
因此切换浏览器不会导致偏好设置损坏。
扩展开发:Chrome for Testing
如果你直接针对 Chrome 开发扩展,请安装 Chrome for Testing(CfT)—— Chrome 团队提供的带版本号、不会自动更新的 Chrome 构建版本,专为自动化设计, 同时仍支持加载未打包的扩展:
cdpilot browser install chrome-for-testing # latest Stable
cdpilot browser install chrome-for-testing --channel beta # stable | beta | dev | canary
cdpilot browser install chrome-for-testing --version 154 # a milestone, or a full version (154.0.8037.57)
cdpilot ext-install ./my-extension/ # register your unpacked extension
cdpilot browser status # shows the CfT version and path
- 仅在执行该命令时下载。 这是一次性下载的约 150–190 MB zip 文件(mac-arm64 版本
154.0.8037.57:191,429,663 字节);cdpilot 不会自行获取该文件。此构建版本来自官方
CfT JSON 端点
(
last-known-good-versions-with-downloads.json、按版本和里程碑划分的文件)。 这些文件仅列出 URL,不含哈希值,因此下载内容会根据服务器的Content-Length和x-goog-hashmd5 进行校验;zip 文件的 SHA-256 会被记录。 - 文件会解压到
$CDPILOT_HOME/browsers/chrome-for-testing/<version>/(在 macOS 上, 只会清除该目录的隔离属性),并记录在installed.json中。 - 自动用于扩展开发: 注册了开发扩展期间,选择品牌 Chrome(
cdpilot browser chrome, 或者在 Chrome 是唯一支持扩展的选项时选择auto)会使用 Chrome for Testing,并在 stderr 输出一行说明。若尚未安装 CfT,在 Chrome 上执行ext-install会打印安装命令, 并继续提供 Vivaldi/Brave 作为替代选项。cdpilot browser chrome-for-testing始终会选择它。 不会替换显式设置的CHROME_BIN。 - 它使用 cdpilot 常用的按项目隔离配置文件(
profile-cft)。 - 它用于扩展开发和测试,不是隐身浏览器。 cdpilot 不会声称它能规避反机器人检测; 如需此类用途,请使用你常规的浏览器设置。
- Linux(Ubuntu 23.10+): AppArmor 会阻止非特权用户命名空间,而 CfT(与发行版的
Chrome 软件包不同)没有允许使用这些命名空间的配置文件,因此会在启动时退出。cdpilot
会打印此提示;运行
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0即可允许使用。
安装
# Use directly (no install needed)
npx cdpilot <command>
# Or install globally
npm i -g cdpilot
要求: Node.js 18+、Python 3.10+,以及以下浏览器之一:Brave Browser、Google Chrome 或 Chromium。(首次启动时,预检向导会自动安装 Python websockets 模块。)
首次设置
npx cdpilot setup # Auto-detect browser, create isolated profile
npx cdpilot launch # Start browser with CDP enabled
npx cdpilot status # Check connection
Claude Code 插件市场
将 cdpilot 的 MCP 服务及其技能直接安装到 Claude Code 中,无需编辑
.mcp.json:
/plugin marketplace add mehmetnadir/cdpilot
/plugin install cdpilot@cdpilot
这会注册 cdpilot MCP 服务(npx cdpilot mcp)以及一项简短技能,指导 Claude Code
何时以及如何使用 cdpilot 的命令。请参阅
.claude-plugin/marketplace.json 和
plugins/cdpilot/。
MCP Bundle(.mcpb)
对于支持一键安装本地服务的 MCP 客户端(Claude
Desktop 等),请下载附在
最新版本中的 .mcpb 文件并
打开,或自行构建:
npm run build:mcpb # writes cdpilot.mcpb at the repo root
此 Bundle 仍需要在运行它的机器上安装相同的运行环境:Node.js
18+、Python 3.10+,以及 Brave/Chrome/Chromium。请参阅
manifest.json 了解 Bundle 的 MCP Bundle 清单
(规范)。
从 0.4.x 升级到 0.5.0 — 请先阅读
有一项不兼容变更,其余都是新增内容。
不兼容变更 — 视觉反馈默认关闭。 绿色发光边框、动画假光标、点击波纹和按键显示,让 cdpilot 在每个页面上的表现都像个生手。现在这些功能改为选择启用:
cdpilot show on # restore the old visual feedback layer
cdpilot show off # default since 0.5.0
MCP 服务的持久发光流程(CDPILOT_MCP_SESSION=1)保持不变
——依赖会话期间可见反馈的 AI Agent 仍会自动看到这些反馈。只有直接使用 CLI 的用户会感受到变化。
0.5.0 新增功能(无需迁移):
cdpilot dismiss— 在 LLM 聊天注册墙上,启发式地自动点击“保持退出登录 / 不用了”等按钮。cdpilot adaptive on— 在受 CAPTCHA 保护的主机上自动切换到 stealth 模式,并按主机持久保存状态。cdpilot cookies save/load— 将 Cookie 导出/导入为 JSON,以便在多次运行间复用 CF/DataDome 验证状态。cdpilot context create/list/close+CDPILOT_TARGET— 创建隔离的浏览器上下文,在单个浏览器内实现真正的并行自动化。cdpilot fast/cdpilot show— 集中管理计时和视觉开关。- 纯性能优化:页面加载后等待时间从 1500ms 缩短至 300ms、
scrollIntoView立即执行、WebSocket 连接池、/jsonTTL 缓存。
完整列表及原因说明请参阅 CHANGELOG.md。
命令
导航与内容
cdpilot go <url> # Navigate to URL (alias: open <url>)
cdpilot content # Get page text content
cdpilot html # Get page HTML
cdpilot shot [file] # Take screenshot (PNG)
cdpilot pdf [file] # Save page as PDF
交互
cdpilot click <selector> # Click element
cdpilot type <selector> <text># Type into input
cdpilot fill <selector> <val> # Set input value (React-compatible)
cdpilot submit <form> # Submit form
cdpilot hover <selector> # Hover element
cdpilot keys <combo> # Keyboard shortcut (ctrl+a, enter, etc.)
cdpilot scroll-to <selector> # Scroll element into view
cdpilot drag <from> <to> # Drag and drop
如果真实鼠标点击(在框架内,或使用 --entropy=on)的目标在按住鼠标按钮期间发生移动或被遮挡,脚本不会再次点击:click 会打印 Pressed (released elsewhere, not clicked): …,并以 退出码 3 结束(已按下,但释放时目标未命中,未点击;1 仍表示“错误”)。如果页面在 mousedown 时替换了目标或导航离开了目标,则会打印 Pressed (the page replaced or left it, not clicked): …,并以退出码 0 结束。MCP(browser_click、browser_smart_click)会返回 isError: false,首行内容为 {"clicked": false, "reason": "moved"|"gone"|"unknown"}。batch 和 run 会完成每个步骤,然后在任一步骤失败时以退出码 1 结束;否则,如果有点击未成功,则以退出码 3 结束;否则以退出码 0 结束。
定位 iframe 内的元素
银行卡表单(Stripe/iyzico 风格)、嵌入式登录组件和 reCAPTCHA
复选框都位于 <iframe> 内。使用 >>> 在元素选择器前指定框架链,或传入 --frame:
# Payment-style page: the card fields are inside <iframe id="card" title="Secure card payment">
cdpilot fill "iframe#card >>> input[name=cardnumber]" "4242424242424242"
cdpilot type --frame "#card" "input[name=cvc]" "123"
cdpilot click "iframe[title='Secure card payment'] >>> button#pay-btn"
# Nested frames: outermost first
cdpilot click "iframe.checkout >>> iframe.card >>> button"
# --frame <selector|index|url-substring>, nestable with >>>
cdpilot click --frame 0 "button.submit" # first iframe (same order as `frame list`)
cdpilot fill --frame "url=js.stripe.com" "input[name=cardnumber]" "4242424242424242"
cdpilot frame list --frame "#card" # iframes inside that frame
cdpilot frame eval --frame "#card" "document.title" # runs in the frame's own page context
- 适用于
click、fill、type、submit、hover、dblclick、rightclick、smart-click、smart-fill、smart-select和frame list|eval|shadow。 - 帧跳转可以是 CSS 选择器、从 0 开始的索引、
name/id,或url=<src substring>。--frame也接受不带前缀的src子串。 引号内或[...]中的>>>会按字面处理。若选择器匹配的是一个 包裹 iframe 的元素(Stripe 的#card-element),则会进入其中的 iframe,并在 stderr 上说明:note: '#card-element' is not an iframe; using the iframe inside it。 - 已包含
>>>的选择器和文本仍可正常使用:如果第一个>>>之前的部分在页面中找不到 iframe,或某一段为空(click "Next >>>"),则会照原样使用整个字符串,与之前完全相同。如果这样也失败,stderr 会输出一行说明:note: 'Home' matched no iframe; used the selector as written。--frame不会回退:找不到指定帧时会报错(退出码为 1)。 - 对于
smart-click/smart-fill/smart-select,第一个>>>之前的部分只有在看起来像选择器(包含#、.或[, 或以iframe/frame标签开头)或为url=…时才会被视为帧; 普通词语仍视为文本。即使<main>元素中包含 iframe,smart-click "Main >>> Settings"仍会点击页面上名为 "Main >>> Settings" 的链接。帧索引或不带前缀的名称请使用--frame。 - 同源和跨源帧均可使用,包括进程外 iframe(站点隔离):cdpilot
通过 CDP 解析每次跳转(
DOM.describeNode→ 帧 ID → 帧的执行上下文,或通过Target.attachToTarget使用扁平会话连接进程外帧),绝不会通过contentDocument,因为浏览器会阻止跨源访问。 - 在帧内,
click和smart-click会发送真实鼠标输入 (isTrusted: true),与hover、dblclick、rightclick和--entropy=on点击一样;如果元素没有边框框,则会回退到脚本点击。 鼠标输入会在页面坐标中分发:系统会自动应用每个帧在页面中的偏移量和缩放 (transform: scale()、zoom),让浏览器将命中测试定位到正确的帧。按下鼠标前,cdpilot 会检查该点(沿途每个文档中都调用elementFromPoint);如果有内容遮挡目标(例如 Cookie 横幅),则会改用脚本点击目标,并在 stderr 上输出一行说明(note: … is covered by div#cookie at the click point; used a script click)。cdpilot 自带的输入拦截器(show on、 MCP 会话)只会放行 cdpilot 自己的点击,仅限该次点击。 smart-click/smart-fill/smart-select会先在页面中查找, 并比较经过空白折叠的文本( 和换行符都按一个空格处理)。如果页面上某个已启用元素的文本或标签包含完整查询内容,就会使用该元素。如果页面上唯一符合条件的元素都已禁用,命令会像以前一样失败(no enabled element matches …),且不会查找帧。否则会按广度优先顺序搜索可见帧,查找完整查询匹配项(最多 20 个帧,所有搜索 CDP 调用总计限时 2 s),并在 stderr 上报告匹配结果:smart-click: matched inside frame iframe#card (https://…)。搜索只会查找,不会点击或输入;随后命令会在选定的帧中执行一次。若没有匹配的帧,则会像以前一样使用页面上的部分(词语)匹配。超过 2 s 时:smart-click: frame search stopped after 2s (3 of 7 frames);届时尚未响应的帧不会被触及。smart-fill和smart-select只会自动搜索与页面同源的帧,确保输入值不会意外填入第三方帧(广告、聊天或支付组件);如需访问跨源帧,请使用>>>或--frame。smart-click会搜索所有可见帧。- 不带
--frame的frame list会像以前一样打印相同的列表。
调试
cdpilot console [url] # Capture console logs
cdpilot network [url] # Monitor network requests
cdpilot debug [url] # Full diagnostic (console+network+perf+shot)
cdpilot perf # Performance metrics
cdpilot eval <js> # Execute JavaScript
cdpilot eval-batch <json> # Run N JS expressions in 1 roundtrip (5-30x faster)
# Example: read 4 DOM values in a single CDP roundtrip instead of 4
cdpilot eval-batch '["document.title","location.href","document.links.length","document.images.length"]'
# → [{"ok":true,"value":"..."}, {"ok":true,"value":"..."}, ...]
性能
cdpilot block # Show status
cdpilot block on # Enable (default preset: images+fonts+ads)
cdpilot block off # Disable
cdpilot block preset images,fonts,ads,media # Set patterns from named presets
cdpilot block patterns '*.png' '*.woff2' # Custom URL patterns
cdpilot block clear # Drop all patterns
隐身注意事项:
block会改变指纹特征——真实浏览器会加载 图片、字体和分析脚本。Cloudflare 级别的机器人检测器会注意到缺失的 请求。对于隐身/反机器人目标,请保持block关闭;对于已知安全的内部网站, 如果速度比伪装更重要,则将其开启。
cdpilot fast # Show status (effective auto-wait ms)
cdpilot fast on # Auto-wait 5s → 2s, less idle padding
cdpilot fast off # Back to defaults
CDPILOT_WAIT_MS=1000 cdpilot click # Per-command override (env wins over fast mode)
cdpilot show # Show status (visual feedback on/off)
cdpilot show on # Re-enable glow border + cursor + ripples + keystrokes
cdpilot show off # Default since 0.4.4 — quiet, professional output
0.4.4 中更改了视觉反馈的默认设置——旧动画(绿色光效、 移动光标、点击涟漪)会让每个操作看起来都像是新手在操控屏幕。现在可通过
cdpilot show on选择启用。MCP 服务的 持续光效流程(CDPILOT_MCP_SESSION=1)不受影响——依赖会话期间可见反馈的 AI Agent 仍会自动看到这些效果。
标签页管理
cdpilot tabs # List open tabs
cdpilot new-tab [url] # Open new tab
cdpilot switch-tab <id> # Switch to tab
cdpilot close-tab [id] # Close tab
cdpilot close # Close active tab
网络控制
cdpilot throttle slow3g # Simulate slow 3G
cdpilot throttle fast3g # Simulate fast 3G
cdpilot throttle offline # Go offline
cdpilot throttle off # Back to normal
cdpilot proxy <url> # Set proxy (legacy single-URL form)
cdpilot proxy off # Remove proxy
# v0.7.0: named pools (BrightData, IPRoyal, Anchor, etc.)
cdpilot proxy add brd "http://USER:[email protected]:22225" --geo us
cdpilot proxy add ipr "http://USER:[email protected]:12321" --sticky
cdpilot proxy use brd # Activate one pool
cdpilot proxy list # Show pools (credentials redacted)
cdpilot proxy show [<name>] # Active or named pool URL (redacted)
cdpilot proxy remove <name> # Drop a pool
TLS 指纹(v0.8.0)
cdpilot tls-check # Probe JA3/JA4/H2 via tls.peet.ws
cdpilot tls-check --service browserleaks # Alternate echo
cdpilot tls-check --json # Raw JSON
已知限制: v0.8.0 附带了探测工具(tls-check),但没有内置 TLS 修复方案。
目前没有基于 Chromium、已修正 TLS 且以独立二进制形式发布并支持 --remote-debugging-port 的浏览器。
Camoufox 使用 Firefox+Juggler(不支持 CDP);
Patchright / undetected-chromedriver / nodriver 是 Python/Playwright 库,
而非独立浏览器。若没有协议适配器,cdpilot 的纯 CDP 架构与它们都不兼容。
跟踪计划: v0.9 路线图(采用 curl-impersonate 语义的 TLS-MITM 插件,
或采用经过 BoringSSL 修补的 Chromium 分支)。
请求拦截
cdpilot intercept block <pattern> # Block requests
cdpilot intercept mock <pattern> <json-file> # Mock responses
cdpilot intercept headers <pattern> <header:value> # Add headers
cdpilot intercept list # List active rules
cdpilot intercept clear # Clear all rules
设备模拟
cdpilot emulate iphone # iPhone emulation
cdpilot emulate ipad # iPad emulation
cdpilot emulate android # Android emulation
cdpilot emulate reset # Back to desktop
地理位置
cdpilot geo istanbul # Set location to Istanbul
cdpilot geo london # Set location to London
cdpilot geo 41.01 28.97 # Custom coordinates
cdpilot geo off # Remove override
无障碍功能
cdpilot a11y # Full accessibility tree
cdpilot a11y summary # Quick summary
cdpilot a11y find <role> # Find elements by ARIA role
会话管理
cdpilot session # Current session info
cdpilot sessions # List all sessions
cdpilot session-close [id] # Close session
高级功能
cdpilot cookies [domain] # List cookies (filter by domain)
cdpilot cookies save <file> [<domain>] # Export cookies as JSON
cdpilot cookies load <file> # Import cookies (replay CF clearance)
cdpilot cookies save --host x.com # Save to per-host cache
cdpilot cookies load --host x.com # Load from per-host cache
cdpilot cookies list # Cached hosts + age + CF clearance flag
cdpilot cookies clear --host x.com # Remove one host
cdpilot cookies clear --all # Wipe entire cache
cdpilot cookies clear --older-than 7d # Remove stale entries
cdpilot cookies auto on # Toggle global auto-save/replay flag (v0.6.1: requires safe-list)
cdpilot cookies auto add <host> # Opt host into auto save/replay (v0.6.1)
cdpilot cookies auto remove <host> # Remove host from safe-list
cdpilot cookies auto list # Enable flag + current safe-list
cdpilot cookies cf-replay <url> # Inject cached CF clearance before nav
cdpilot wipe [--cookies|--storage|--tabs|--keep h1,h2]
# v0.6.2: per-task state hygiene (cross-task contamination)
cdpilot storage # localStorage contents
cdpilot upload <sel> <file> # Upload file to input
cdpilot multi-eval <js> # Execute JS in all tabs
cdpilot headless [on|off] # Toggle headless mode
cdpilot frame list # List iframes (index = --frame <index>)
cdpilot frame eval --frame <f> <js> # Run JS inside an iframe (cross-origin too)
cdpilot dialog auto-accept # Auto-accept dialogs
cdpilot permission grant geo # Grant geolocation
并行上下文
cdpilot context create [url] # Make fresh browser context + tab (prints JSON)
cdpilot context list # Tree of contexts and their tabs
cdpilot context close <ctx> # Destroy a context (refuses 'default')
通过环境变量固定目标上下文,以便在后续命令中操作其标签页:
ID=$(cdpilot context create https://example.com | jq -r .target_id)
CDPILOT_TARGET=$ID cdpilot eval 'document.title'
真正的隔离——每个上下文都有独立的 Cookie/存储空间。适用于并行运行 N 个 AI 聊天查询且不污染历史记录, 或测试已登录与未登录流程的 A/B,而无需启动多个浏览器。
智能导航(支持大模型)
cdpilot dismiss # Click best "Stay signed out / No thanks" button
cdpilot dismiss aggressive # Handle chained modals (cookie banner → signup)
内置英语和土耳其语模式库。明确排除具有破坏性、外观相似的选项(删除账户、退出登录、订阅), 可安全地串联到查询工作流中。
视频理解
单张截图无法捕捉动态画面。cdpilot watch 会运行连续
屏幕录制(Page.startScreencast),将 JPEG 帧写入环形缓冲区,让
AI Agent 能查询某个时间段并实际观看发生了什么——
动画、鼠标光标移动、滚动、爆炸效果——而不是仅凭一张静止画面猜测。
cdpilot watch start <url|file://...> # Begin screencast, play the video
cdpilot watch query --at 1:23 --window 5s # Frames around a timestamp
cdpilot watch ask "did the menu animate open?" # Ask about recent frames
cdpilot watch status # Show capture state + buffer size
cdpilot watch stop # Stop the screencast
支持本地文件(file://...)和在线视频(YouTube、Vimeo、
Twitter、Facebook、Instagram)。零依赖——Pillow 是可选的,仅
用于检测帧间动态。
DRM 限制: 受 DRM 保护的播放器(Netflix 等)在 CDP 层会渲染为 黑帧——cdpilot 无法捕获这些画面。所有 非 DRM 内容均可正常使用。
MCP 会将其作为 browser_watch_* 工具提供给 AI Agent。
视频理解(命令)
cdpilot watch start <url|file://> # Start screencast, play video
cdpilot watch query --at 1:23 --window 5s # Frames around a timestamp
cdpilot watch ask "did the modal slide in?" # Ask about recent frames
cdpilot watch status # Capture state + buffer size
cdpilot watch stop # Stop screencast
隐身与 CAPTCHA
零依赖的反指纹层——修补
navigator.webdriver、
chrome.runtime、插件(正确继承 PluginArray)、WebGL
供应商/渲染器、权限、硬件并发数以及 Worker
构造函数。通过 Page.addScriptToEvaluateOnNewDocument 注入,
确保在任何页面脚本运行之前生效。默认禁用;可选择启用。
启动时,cdpilot 还会传入 --disable-blink-features=AutomationControlled,
关闭 Blink 运行时标志;Cloudflare 和 DataDome 会探测该标志,以检测
自动化浏览器。
真实鼠标点击(帧、--entropy=on、click @ref、dblclick、rightclick)会按住鼠标键 40-120 毫秒,模拟真人按压;CDPILOT_PRESS_MS=min-max 可更改范围(0-0 = 立即释放)。
三级隐身模式
cdpilot mode 是推荐的入口——通过一个开关设置 cdpilot 接触多少指纹特征,从最少到最多:
cdpilot mode # show current tier + what it injects
cdpilot mode regular # no fingerprint patch — cleanest, fastest (default)
cdpilot mode stealth # light patch: webdriver / chrome.runtime / permissions
cdpilot mode undetected # full patch: + plugin array + WebGL + Worker
regular 是默认模式,因为 Stealth Bench V1 发现,仅启用完整补丁集本身就会降低评分——合成插件数组本身就是一种暴露。stealth 级别会特意省略插件伪装;只有面对难以应付的目标时,才升级到 undetected。自适应层会为每个主机学习合适的级别,并在遇到 CAPTCHA 时升级。效果会在下次导航时生效。环境变量覆盖项:
CDPILOT_MODE=<tier>。旧版 stealth on/off 开关仍然有效,并与级别保持一致:
cdpilot stealth on # enable fingerprint patches (opt-in)
cdpilot stealth off # disable (default)
cdpilot stealth status # show which patches are applied
cdpilot captcha-check # JSON detection of Turnstile/hCaptcha/reCAPTCHA/
# DataDome/PerimeterX/Arkose/GeeTest. Exit 0/3
cdpilot captcha-wait [sec] # block until user solves (interactive)
# or poll with JSON stream (non-interactive)
cdpilot adaptive [on|off|status]
# Auto-escalate to stealth on hosts that show
# CAPTCHA. Persistent per-host memory.
cdpilot adaptive forget <host>
# Remove a hostname from the stealth list
cdpilot adaptive clear # Drop the stealth host memory entirely
自适应模式是一种“快速运行,遇阻时再翻墙”的自动化方式:cdpilot 默认在开放模式下运行,每次导航后检测 CAPTCHA;一旦检测到 CAPTCHA,就会将主机添加到持久列表,并开启隐身模式重试一次。绝不会自动降级。设计上以保守为原则。
Web Bot Auth(签名 Agent)
与隐身模式相反。隐身模式试图让浏览器看起来像真人;Web Bot Auth 则声明“这是一个自动化 Agent,以下是它的身份凭证”。浏览器发出的每个请求都携带 Ed25519 HTTP Message Signature(RFC 9421) 签名,网站或其前置的 Cloudflare 会根据你在自己域名上发布的密钥目录进行验证。格式遵循 draft-meunier-web-bot-auth-architecture 和 draft-meunier-http-message-signatures-directory, 并复现 Cloudflare 参考实现 (cloudflare/web-bot-auth) 的 Ed25519 测试向量。
**可选依赖项。**签名需要 Python cdpilot 运行环境中的 cryptography 包(如果你设置了 CDPILOT_PYTHON,则使用该环境):
pip install cryptography
如果没有该依赖项,bot-auth 命令和 launch --bot-auth 会显示提示并以状态码 2 退出。其他所有命令仍照常工作。
1. 生成密钥(仅需一次):
cdpilot bot-auth init --agent-url https://your-domain.com
这会将 Ed25519 私钥写入 CDPILOT_HOME/bot-auth/ed25519.key(默认为
~/.cdpilot),并以 0600 模式创建。cdpilot 从不打印或记录密钥;如果该文件可被其他人读取,则会发出警告。Agent URL 必须是 https:// 源站(不能包含路径)。再次执行 init 时会拒绝替换密钥,除非你传入 --force,因为新密钥将不再匹配你发布的目录。
2. 在自己的域名上托管已签名的目录。cdpilot bot-auth directory 会将公钥打印为 JWKS,其中 kid 是该密钥的 RFC 7638 JWK 指纹。Cloudflare 还要求对目录响应进行签名,因此 --headers 会打印随响应一起提供的标头:
cdpilot bot-auth directory --headers # headers, a blank line, then the JSON body
cdpilot bot-auth directory --headers --json # the same as {"authority", "headers", "body"}
Content-Type: application/http-message-signatures-directory+json
Signature-Input: sig1=("@authority";req);created=…;keyid="<thumbprint>";alg="ed25519";expires=…;nonce="…";tag="http-message-signatures-directory"
Signature: sig1=:<base64 Ed25519 signature>:
{ "keys": [ … ] }
将响应正文和这三个标头托管在 https://your-domain.com/.well-known/http-message-signatures-directory。签名覆盖 ("@authority";req),即获取目录时所用的主机:默认使用 Agent URL 的主机,也可通过 --authority <host> 指定。目录中的每个密钥都有一个签名。签名有效期为 24 小时(--ttl <seconds>),因此静态主机需要每天刷新签名,可以使用 cron,或运行相同签名逻辑的边缘函数。以下是一个 cron 示例,用于重写标头文件以及 Web 服务器提供的响应正文:
# m h dom mon dow — every day at 03:17, 48 h validity so one missed run does not break it
17 3 * * * cdpilot bot-auth directory --headers --ttl 172800 --json > /var/www/wba/directory.json.tmp \
&& mv /var/www/wba/directory.json.tmp /var/www/wba/directory.json
你的服务器(或边缘函数)会从该 JSON 中读取 headers 和 body,并在 well-known 路径上提供它们。--content-digest 还会对响应正文进行签名(Content-Digest,RFC 9530),与 Cloudflare 的参考向量一致;此时必须逐字节提供输出的响应正文。
3. 启动签名浏览器:
cdpilot launch --bot-auth # or: CDPILOT_BOT_AUTH=1 cdpilot launch
cdpilot status # ... bot-auth: on (keyid <thumbprint>)
cdpilot go https://example.com # this request is signed, and so is everything after it
cdpilot stop # stops the browser and the signer
launch --bot-auth 会在浏览器旁启动一个小型的分离式签名器。它使用与空闲关闭监视器相同的自派生方式,生命周期与浏览器完全一致。它持有一个 CDP 连接,并自动附加到每个页面、弹出窗口、新标签页、进程外 iframe 和工作线程。它会在 Fetch 的“Request”阶段为每个请求签名,包括每次重定向跳转。因此,页面自行发出的请求也会签名:计时器、fetch()(即使你的 cdpilot 命令已经返回)、以及页面打开的标签页。data:、blob: 和 chrome-extension: 请求不会离开浏览器,因此会原样通过。如果请求签名失败,该请求会以未签名状态发出,一行日志会写入 CDPILOT_HOME/bot-auth/signers/<port>.log(仅主机),页面绝不会因此受阻。对已经运行的浏览器执行 launch --bot-auth 会为其添加签名器。
每个请求会获得三个标头:
| 标头 | 值 |
|---|---|
Signature-Agent | "https://your-domain.com" |
Signature-Input | sig1=("@authority" "signature-agent");created=…;keyid="<thumbprint>";alg="ed25519";expires=…;nonce="…";tag="web-bot-auth" |
Signature | sig1=:<base64 Ed25519 signature>: |
expires 为 created 加 5 分钟。nonce 是 64 个随机字节经 Base64 编码后的值,每个请求都会生成新的值。
这是旧版 Signature-Agent 格式(draft-05 A.2.3),也是默认格式,因为这是 Cloudflare 的验证器接受的格式:Cloudflare 会拒绝后续草案中的字典格式。若要改用字典格式(Signature-Agent: sig1="https://your-domain.com",覆盖项为 "signature-agent";key="sig1"),请运行 cdpilot bot-auth format dict(bot-auth format legacy 可切回旧版格式,bot-auth format 可查看当前格式,bot-auth init --agent-format dict 可在创建时设置)。更改从下一次 launch --bot-auth 开始生效。
不会签名的内容。 WebSocket 握手不会签名:浏览器不会通过 CDP 的 Fetch 域传递这些握手,因此页面打开的 wss:// 连接会在不带这些标头的情况下发出。Service Worker 内部的缓存命中以及 data:/blob: URL 永远不会到达服务器。
如果签名器退出或挂起。 签名器运行期间,浏览器的每个请求都会停留在 Fetch 阶段,直到签名器添加完标头。如果签名器被终止,请求会以未签名状态发出;此后,cdpilot status 和 cdpilot go 会各输出一行标准错误信息(签名器未运行,请求会以未签名状态发出,请再次运行 cdpilot launch --bot-auth),直到你重新启动签名器或运行 stop。如果签名器冻结(进程已停止或正在调试器中),请求会挂起:运行 cdpilot stop,然后再次运行 launch --bot-auth。cdpilot 仅在进程的命令行为对应端口的签名器、且浏览器是该签名器所附加到的浏览器时,才信任其签名器状态;因此,如果陈旧状态文件中的 pid 被其他程序复用,该状态会被丢弃,绝不会向该进程发送信号。
签名器运行时,空闲关闭仍然有效:签名器会附加到每个页面,因此 cdpilot 不再判断“是否有页面已附加”,而是统计除签名器以外的 CDP 客户端(按套接字所有者统计:macOS 和 Windows 上使用 netstat,Linux 上使用 ss);watch 守护进程或 Playwright 会话会让浏览器保持打开状态。在 Linux 上,ss -tnp 只会显示你自己的进程所拥有的套接字,因此以其他用户身份运行的客户端不会被计入,空闲关闭可能会在该客户端仍在使用浏览器时将浏览器关闭。
隐身模式冲突。 签名表示“我是 Agent”,而隐身模式表示“我不是”。如果同时传入 --bot-auth 和 --stealth/--undetected,或者 cdpilot mode 为 stealth 或 undetected,cdpilot 会输出一行警告并应用 bot-auth。签名器运行时,不会注入隐身脚本或用户代理覆盖项,自适应升级也不会在隐身级别重试。
向 Cloudflare 注册。 目录上线后,请通过 Cloudflare 控制面板中的 Bot Submission Form 提交目录,并将其注册为 已签名的 Agent(代表用户行事的 Agent)或
已验证的机器人;请参阅 Cloudflare 关于
已签名的 Agent和
通过密码学验证的机器人
的文章。使用 Cloudflare 的网站随后会将你的请求识别为来自你的 Agent。未检查 Web Bot Auth 的网站会忽略这些标头。
摩擦阶梯(渐进式反机器人检测)
真实网站不会只甩出一个 CAPTCHA,而是会逐步叠加防御措施。
cdpilot friction 会报告当前触发的阶梯级别,让 Agent 做出恰当响应,而不是靠猜测。共有六个级别,从低到高:
none → rate_limited → soft_captcha → login_wall → otp_sms → hard_block
cdpilot friction # JSON: current rung + recommended response policy
双语(英语 + 土耳其语)DOM 启发式检测。检测**只读,不会绕过任何机制。**响应策略刻意保持保守:
rate_limited→ 自动指数退避并重试soft_captcha→ 交由验证码工具处理login_wall/otp_sms/hard_block→ 标记为需要人工接手,不会自主解决
最后一条是道德边界,而非缺失的功能:cdpilot 不会尝试自行突破登录、OTP/SMS 验证门槛或直接封锁。
MCP 将此功能公开为 browser_friction。
按住不放(PerimeterX / HUMAN 行为挑战)
PerimeterX 的“按住不放”是一种行为挑战,而不是令牌——没有可调用的服务商。唯一的解决方法是真正执行按下 → 按住 → 释放的手势,cdpilot 通过 CDP Input 域模拟该手势:按住约 3–7 秒,时长采用高斯随机化,并在按住期间产生 ±1–2px 的微小抖动。
cdpilot press-hold # auto-find the px-captcha target
cdpilot press-hold "#px-captcha button" # explicit selector
检测到 perimeterx 挑战时,captcha-solve 会自动将请求路由到此处。
MCP 将此功能公开为 browser_press_hold。
验证码求解器插件(v0.6+)
可选集成 2captcha、anti-captcha 和 capmonster。每次求解费用约为 $0.001–0.003。API 密钥存储在 ~/.cdpilot/captcha-providers.json
(chmod 600)中——绝不会提交到 git。
# One-time setup
cdpilot captcha config --provider 2captcha --api-key YOUR_KEY
cdpilot captcha config --provider anticaptcha --api-key YOUR_KEY # fallback
# Enable auto-solve (adaptive layer auto-solves on detect)
cdpilot captcha auto on
# Manual solve (debug / scripting)
cdpilot captcha solve --type recaptcha-v2 --site-key SK --url https://example.com
# returns: {"token": "03AGdBq2...", "duration_ms": 12500, "cost": 0.003, "provider": "2captcha"}
cdpilot captcha solve --type hcaptcha --site-key SK --url URL
cdpilot captcha solve --type turnstile --site-key SK --url URL
cdpilot captcha solve --type funcaptcha --site-key SK --url URL
# Status & balance
cdpilot captcha status # {"configured": [...], "preferred": "2captcha", "auto_enabled": true}
cdpilot captcha balance # {"2captcha": 1.23, "anticaptcha": 0.50}
支持的类型:recaptcha-v2、recaptcha-v3、hcaptcha、turnstile、funcaptcha
令牌通过 CDP 的 Runtime.evaluate 注入,无需浏览器端库。
启用 captcha auto on 后,自适应层会在每次导航后自动检测并求解。未启用时,仍会进行检测,但需要手动求解。
预期基准测试提升(v0.6): reCaptcha 从 2/6 提升至 5+/6,hCaptcha 从 2/3 提升至 3/3
图片 CAPTCHA + 配置档案预热
captcha-solve 用于处理上述令牌求解器无法处理的基于图片的速率限制 CAPTCHA:
cdpilot captcha-solve # auto-detect + route (incl. press-hold)
cdpilot captcha-solve --provider amazon-local # offline OCR (default)
cdpilot captcha-solve --provider capsolver # BYOK image-to-text
cdpilot captcha-solve --provider 2captcha # BYOK image-to-text
- Amazon 经典图片 CAPTCHA(“输入你看到的字符”页面)通过可选的
amazoncaptcha库在本地进行 OCR (pip install amazoncaptcha— 纯 Python + Pillow,MIT 许可证)。未安装时,命令会报告这一情况并正常退出;不会增加硬性依赖。 - BYOK 提供商(
capsolver、2captcha)通过图片转文本 API 工作,使用CAPSOLVER_API_KEY/TWOCAPTCHA_API_KEY。
cdpilot profile warm # age the profile for reCAPTCHA v3 score
profile warm 会浏览一组低风险网站,以积累 Cookie 和历史记录的时间,这会随着时间推移提高 reCAPTCHA v3 的行为评分。此功能有意设计得较慢——请在会话开始前运行,而不要在会话中直接运行。
公开的机器人检测面板,测量时间为 2026-09-27,使用无头 Brave(Chrome 154) (方法和原始结果):
mode | bot.sannysoft.com(31 项) | incolumitas intoli | incolumitas fpscanner | incolumitas new-tests |
|---|---|---|---|---|
regular(无补丁,默认) | 28 项通过 / 3 项失败 | 5/6 | 19 项通过 / 3 项失败 / 1 项警告 | 全部通过 |
stealth | 31 项通过 | 6/6 | 19 项通过 / 1 项失败 / 1 项警告 | 全部通过 |
undetected | 31 项通过 | 6/6 | 19 项通过 / 1 项失败 / 1 项警告 | 全部通过 |
- fpscanner 中剩余的失败项是
'webdriver' in navigator,在所有现代 Chrome 中该表达式都为真;伪造这一项会让 cdpilot 显得与众不同。 regular的失败项都源自HeadlessChrome用户代理。stealth/undetected会在go启动的页面加载时改写它;同一页面中后续单独运行的命令 仍能读取到HeadlessChrome。- new-tests:所有键值均正常;所有等级中
connectionRTT都报告为未知。 - 无法测量 nowsecure.nl 和 areyouheadless(固定的、始终交互的 Turnstile 测试密钥;HTTP 502)。
本页较早公布的数据(sannysoft 24/24、intoli 6/6)是在 2026 年 4 月使用 v0.4.x 测得;现已由上表取代。
可靠性
cdpilot browser [name|auto] # workload-aware browser selection
cdpilot browser install chrome-for-testing # for extension development (see above)
cdpilot health # JSON: alive, port, tabs, browser, today's crashes, idle close
cdpilot health 专为 shell 看门狗设计:
until cdpilot health >/dev/null; do cdpilot launch; sleep 2; done
在 macOS 上显示今天 Brave 的崩溃次数,数据来自 ~/Library/Logs/DiagnosticReports/,
让你能在自动化悄无声息地停滞之前发现性能下降。
自动启动。 如果页面命令(go、content、click、shot 等)发现
浏览器未运行,就会像 cdpilot launch 一样启动浏览器(使用相同的配置文件、
相同的无头/可见设置),然后继续执行,并向 stderr 输出一行:
cdpilot: browser was not running — launched it (CDPILOT_NO_AUTOLAUNCH=1 to disable)。
生命周期、状态和配置命令(launch、stop、close、
close-tab、stop-all、project-stop、session-close、status、health、
tabs、sessions、projects、headless、proxy、browser、extensions、
mcp、serve 等)绝不会启动浏览器。CDPILOT_NO_AUTOLAUNCH=1 会恢复旧版的
"CDP connection error. Is the browser running?" 错误,并以退出码 1 退出。
空闲时自动关闭。 对于由页面命令自动启动,或由 MCP 服务启动(包括
browser_launch)的浏览器,如果 15 分钟内没有 cdpilot 命令或可见页面变化,
就会自动关闭,避免已完成的 Agent 任务继续占用内存。显式执行 cdpilot launch
启动的浏览器会保持打开(你可能正在手动浏览),除非你指定:
cdpilot launch --idle-close 30 或 CDPILOT_IDLE_CLOSE=30。此环境变量也会
设置自动启动后的关闭延迟(浏览器启动时读取;允许小数);0 会关闭空闲自动关闭。
你自行启动的浏览器,或 cdpilot 仅连接到的浏览器,绝不会被关闭。
使用行为包括:除只读检查(status、
health、projects、version)以外的任何 cdpilot 命令(cdpilot health 看门狗循环不会让
浏览器保持运行)、MCP 工具调用、serve 请求、仍连接到页面的 CDP 客户端
(长时间运行的命令、watch、通过 connectOverCDP 运行的 Playwright),以及打开页面的 URL
或标签页集合发生的任何变化(有人导航、新开或关闭标签页)。标题变化不算,因此,
自行改写标题的页面(时钟、未读计数器)无法让浏览器保持运行。cdpilot status 和
cdpilot health 会显示 idle close in 12m 或 idle close off。
实现方式:每条命令都会记录时间戳到 ~/.cdpilot/projects/<id>/last-activity;启动时会
启动一个小型的独立监视进程(每个端口一个;Windows 上不会显示控制台窗口),每 ≤30 秒
检查一次,像 cdpilot stop 一样停止浏览器,在注册表中将其标记为已停止,然后退出;
如果浏览器因其他原因关闭,它也会立即退出。由 serve --api 启动的浏览器由
服务管理,不会自动空闲关闭。
超时。 任何命令都可以使用 --timeout <seconds>,放在命令名称之前或之后;
也可以通过 CDPILOT_TIMEOUT 设置默认值(命令行标志优先;0
表示禁用)。它会限制整个命令的实际运行时间:超时后,cdpilot 会向 stderr 输出
cdpilot: timed out after <N>s (<command>),杀死其启动的子进程,并以退出码 124
退出(与 GNU timeout 相同)。已经运行并注册的浏览器会继续运行。
cdpilot --timeout 10 click "#submit" # before the command...
cdpilot shot page.png --timeout 30 # ...or after it
CDPILOT_TIMEOUT=60 cdpilot run flow.cdp # default for every command (and each script line)
对于 mcp 和 serve,该值不会应用于长期运行的服务本身,而是传递给它运行的每次
工具调用/请求。
会话日志
每条命令(以及每次 MCP 工具调用)都会向本地的项目专属日志追加一行 JSON,因此浏览器任务完成后,就能查到执行过什么以及发现了什么。任何内容都不会离开本机。
cdpilot log # today's commands: time, exit, command, url, result
cdpilot log --md # Markdown report: pages visited, actions, errors, files produced
cdpilot log --json # raw lines (one JSON object per command)
cdpilot log --days 3 # include the last 3 days
cdpilot log --path # where the files are
每行包含 ts、cmd、args、exit、duration_ms、命令执行后的页面 url 和 title(若命令执行前已有这些信息)、约 200 个字符的输出 summary、error 行,以及写入的 files(截图、PDF)。文件存放在 ~/.cdpilot/projects/<project-id>/log/<YYYY-MM-DD>.jsonl。
写入任何内容之前都会进行脱敏:传给 fill、type、smart-fill、smart-select、assert-value 和 dialog prompt 的值都会变成 «redacted:N chars»;密码、令牌、密钥、机密、Cookie、身份验证相关标志和标头的值、看起来像令牌的参数,以及名称包含 token、key、secret、password、auth、code 或 session 的 URL 查询参数和片段值也会如此处理。cookies 和 storage 的输出绝不会写入日志;会记录 eval 的源代码,但超过 40 个字符的字符串字面量会被截断,看起来像机密的字符串会被替换。日志记录尽力而为:不会改变命令的输出或退出代码,写入失败时只会向 stderr 输出一行。设置 CDPILOT_LOG=0 可关闭日志;CDPILOT_LOG_DAYS(默认值为 14)可设置日志保留天数。MCP 服务通过 browser_log 提供此功能。
使用自己的浏览器(人在回路中)
Agent 遇到无法自行通过的 CAPTCHA 或登录页面时,由人来解决,Agent 随后在同一浏览器中继续操作。
最简单的方法不需要 connect。 cdpilot 自带的浏览器是一个正常的可见窗口,除非以无头模式启动(cdpilot headless on /
CHROME_HEADLESS=1)。用户可直接在窗口中解决 CAPTCHA 或登录,之后 Agent 便可继续操作:
cdpilot go https://example.com/dashboard # agent: "captcha detected" / login wall
cdpilot captcha-wait 300 # agent waits while the person solves it
cdpilot go https://example.com/dashboard # agent continues in the same window
该窗口使用 cdpilot 自带的配置文件,因此登录状态会保留,供之后的运行使用。
connect 适用于由你自行启动的浏览器,该浏览器需使用调试端口和你自己的配置文件目录(登录一次即可;它会保留 Cookie):
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9450 --user-data-dir="$HOME/cdpilot-chrome"
# Linux
google-chrome --remote-debugging-port=9450 --user-data-dir="$HOME/cdpilot-chrome"
# Windows
"%ProgramFiles%\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9450 --user-data-dir="%USERPROFILE%\cdpilot-chrome"
cdpilot connect 9450 # or: cdpilot connect ws://127.0.0.1:9450/devtools/browser/<id>
cdpilot connect --auto # or: find it via a DevToolsActivePort file
cdpilot go https://example.com/dashboard
cdpilot disconnect # forget it; the browser keeps running
从 Chrome 136 开始,默认配置文件会忽略 --remote-debugging-port,因此必须使用单独的 --user-data-dir。connect --auto 会读取每个已知配置文件目录中的 DevToolsActivePort 文件(上方命令所用的 ~/cdpilot-chrome、Chrome stable/beta/dev/canary、Chromium、Brave、Vivaldi、Edge),跳过浏览器已关闭或该端口已被替换的浏览器所遗留的文件(文件中的浏览器 ID 必须匹配),并连接到第一个仍在运行的浏览器。它只会通过 HTTP 发起请求;只有在未找到仍在运行的浏览器时,才会发送 WebSocket 探测请求(Chrome 的 chrome://inspect 模式可能会对此弹出权限提示)。
暂不支持:Chrome 的 chrome://inspect/#remote-debugging 开关(Chrome 144+,即日常使用且已登录的配置文件)。在此模式下,Chrome 只会通过 WebSocket 响应(/json/version 和 /json 会返回 404),并且可能要求你允许每个新的调试连接,而 cdpilot 会通过 /json 列出标签页,并为每条命令建立新的连接。connect --auto 会识别此模式,并以退出代码 2 退出,同时给出上方的启动命令,而不是以不完整的方式运行。
cdpilot 对已连接的浏览器所做的操作:
- 页面命令(
go、click、fill、shot、……)会在首次执行页面命令时,在一个新窗口中打开一个供 cdpilot 自用的标签页,该窗口不会获得焦点 (使用Target.createTarget,并设置newWindow+background,因此你的窗口和 标签页会保持不变),之后会继续使用该标签页。close、session-close和空闲会话清理只会关闭此类标签页,即 cdpilot 在本次浏览器运行期间打开的标签页,绝不会关闭最后一个标签页。绝不会在你自己的标签页中导航或输入内容;只有明确指定标签页的命令才会操作它(switch-tab、close-tab <index|id>、CDPILOT_TARGET和multi-eval, 后者会在每个已打开的标签页中运行脚本)。 - 它绝不会关闭或终止浏览器。
close、close --force、stop、stop --smart [--force]、project-stop、stop-all、session-close和 MCPbrowser_close最多只会关闭 cdpilot 自己的标签页(见上文),并打印 “已连接的浏览器仍在运行;运行cdpilot disconnect可断开连接”。空闲自动关闭不会操作该浏览器,tabs --reap不会关闭任何内容,wipe、permission、cookies load和cf-replay会被拒绝(添加--allow-external即可照常加载/重放 Cookie),context close只会销毁由context create创建的上下文,而launch/ MCPbrowser_launch不会启动任何内容。 close-tab是一条显式命令,可以关闭你的标签页:不带参数时关闭当前 (cdpilot)标签页;也可以通过索引或 ID 指定要关闭的标签页。在 Windows 和 Linux 上,关闭最后一个标签页会退出浏览器,因此它不会关闭最后一个标签页。- 它不会向其中注入任何内容:没有隐身补丁或用户代理覆盖(无论
cdpilot mode/stealth如何显示),没有发光效果,没有输入拦截器,没有开发扩展脚本,也不会自动恢复 Cookie。 - 注册信息会一直保留,直到你运行
cdpilot disconnect。如果浏览器 已关闭,页面命令会以状态码 1 退出,并提示“你连接的浏览器已关闭;请重新运行cdpilot connect或运行cdpilot disconnect”,而 cdpilot 绝不会另行启动浏览器。 - 只有在有证据证明浏览器归其所有时,cdpilot 才会将其视为自己的浏览器:它在
launch时记录的浏览器 ID(或者,对于较旧的记录,持有调试端口的运行中记录 PID)。端口被占用并不构成证据,因此遗留的注册表项绝不会导致stop/close操作端口 9222 上属于你自己的 Chrome。
风险:
- 每条 cdpilot 命令,以及任何能够运行 cdpilot 的 Agent,都可以读取并使用该配置文件的 Cookie 和会话(邮件、银行、管理面板)。请使用只登录了任务所需服务的配置文件。
- 只要浏览器在运行,所有本地程序都可以访问调试端口,而不仅仅是 cdpilot。完成后请关闭浏览器。
- 网站更容易检测到自动化行为:cdpilot 不会对已连接的浏览器应用隐身处理。
- cdpilot 的标签页会与你的标签页并列显示在同一个窗口中;当 Agent 指定你的某个标签页时,它仍可能对其执行操作(
switch-tab、close-tab <n>、multi-eval)。
WebMCP 工具(选择启用)
WebMCP 允许页面在 document.modelContext 上注册“工具”:可以通过 registerTool() 命令式注册,也可以通过 <form toolname tooldescription> 声明式注册(输入项由 toolparamdescription 描述)。cdpilot 通过浏览器自身的 API getTools() 和 executeTool() 列出并调用这些工具。在 Chrome 中,该 API 需要通过 chrome://flags/#enable-webmcp-testing 启用(Chromium 146+),因此请使用以下参数启动浏览器:
cdpilot launch --webmcp # saved for this project: later launches (auto-launch too) keep it
cdpilot go https://example.com/shop
cdpilot tools list # name, title, description, annotations, input schema
cdpilot tools list --json
cdpilot tools call add_to_cart '{"sku":"A1","qty":2}'
cdpilot tools call add_to_cart --arg sku=A1 --arg qty=2
cdpilot launch --no-webmcp # turn it off again (applies at the next start)
launch --webmcp会向浏览器的命令行添加--enable-features=WebMCP,并将此模式与隐身模式配置一起保存(项目配置文件中的webmcp.json);CDPILOT_WEBMCP=1|0可覆盖此设置。模式启用时,cdpilot status会显示一行 WebMCP 状态。 Chrome 只会在启动时读取功能标志:已经运行的浏览器会一直使用原有标志,直到执行cdpilot stop。tools list会显示页面及其同源 iframe 中的工具(附带框架 URL),标记表单工具及表单是否会自行提交(toolautosubmit),并显示title和readOnlyHint/consequentialHint/untrustedContentHint注释。不会向页面注入任何内容:列表反映的是浏览器当时的注册表,因此会随重新加载和导航而更新。这两个命令都在 cdpilot 自己的隔离世界中运行(不使用Runtime.enable),因此页面脚本即使包装了getTools()/executeTool(),也无法添加工具、修改结果或查看调用;只有当该隔离世界无法访问document.modelContext时,cdpilot 才会使用页面的主世界,并会在 stderr 中说明。没有工具时,它会说明原因(运行中的浏览器未启用 WebMCP、不是安全上下文、浏览器版本过旧、文档未按源隔离,或页面未注册任何工具),并以 0 退出。tools call会先根据工具的inputSchema检查参数(required、type——true不属于整数——、enum、const、嵌套的properties和items;其他关键字交由页面处理);参数不匹配、工具未知或工具出错时,会以 1 退出。它会传递一个AbortSignal,并在--timeout(默认 20 s)超时后将其中止,随后以 124 退出,并显示timed out after <N>s (--timeout); its execution was aborted。信号会在--timeout的截止时间触发;看门狗会再等待 3 s,以便输出该提示。 没有toolautosubmit的表单工具会等待用户提交表单。 多个框架注册了同名工具时,--frame <url-part>可指定其中一个(完全匹配的框架 URL 优先);未指定时会使用顶层文档中的工具;如果顶层文档没有该工具,调用会停止并列出各个框架。- MCP:仅当项目启用了 WebMCP 模式时(或服务端设置了
CDPILOT_WEBMCP=1),才会列出browser_site_tools和browser_site_tool_call。
安全性:
tools call会运行页面自身的代码,而工具名称、描述和结果都属于页面内容:请将其视为不可信内容。 会话日志会记录参数和结果,并在任何嵌套层级对名称包含 password、token、key、secret、auth 等字样的字段进行脱敏。
扩展与工作站使用
CDPILOT_OFFSCREEN=1 cdpilot launch # headed, but no window on your screen
- 屏幕外模式(
CDPILOT_OFFSCREEN=1)会让浏览器保持有头模式(真实渲染,没有无头浏览器指纹),但会将窗口放置在不会抢夺焦点的位置——适用于在同时使用的工作站上进行自动化操作。 - 多实例池(
CDPILOT_POOL_SIZE)——计划中,尚未发布。 请参阅路线图。 - Docker + Xvfb 测试框架——用于一个单独的私有基准测试仓库(
cdpilot-bench),不属于此软件包。
与 AI Agent 配合使用
cdpilot 专为由 AI Agent 作为工具调用而设计:
Claude Code(MCP)
{
"mcpServers": {
"cdpilot": {
"command": "npx",
"args": ["cdpilot", "mcp"]
}
}
}
任意大模型(工具调用)
{
"name": "browser",
"description": "Control a browser via CDP",
"parameters": {
"command": "go https://example.com"
}
}
Python(子进程)
import subprocess
result = subprocess.run(["npx", "cdpilot", "go", url], capture_output=True, text=True)
print(result.stdout)
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
CDP_PORT | 9222 | CDP 调试端口 |
CHROME_BIN | 自动检测 | 浏览器二进制文件路径 |
CDPILOT_PROFILE | ~/.cdpilot/profile | 隔离的浏览器配置文件 |
BROWSER_SESSION | 自动 | 会话标识符 |
CDPILOT_MODE | regular | 隐身级别覆盖值(regular/stealth/undetected) |
CDPILOT_OFFSCREEN | 0 | 有头模式但在屏幕外渲染——不会有窗口抢占焦点 |
CDPILOT_TIMEOUT | 未设置 | 为每条命令设置默认 --timeout(秒)(命令行标志优先,0 表示禁用);超时后以状态码 124 退出 |
CDPILOT_NO_AUTOLAUNCH | 0 | 1 = 页面命令不会启动浏览器,而是报错并显示旧版“浏览器正在运行吗?”提示 |
CDPILOT_IDLE_CLOSE | 15 | 浏览器 cdpilot 启动后,若没有 cdpilot 命令或页面变更,经过多少分钟后自动关闭(允许小数,0 = 永不关闭;启动时读取)。默认值适用于自动启动和 MCP 启动;显式 CLI launch 不启用此项,除非设置了该变量或指定 --idle-close <min> |
CDPILOT_LOG | 1 | 0 = 不写入会话日志(cdpilot log) |
CDPILOT_LOG_DAYS | 14 | 保留会话日志的天数;每天首次写入时会删除更早日期的文件(0 表示全部保留) |
工作原理
┌─────────────┐ HTTP/WebSocket ┌──────────────┐
│ cdpilot │ ◄──────────────────────► │ Brave/Chrome │
│ (CLI) │ Chrome DevTools │ (CDP mode) │
└─────────────┘ Protocol └──────────────┘
│ │
│ Zero dependencies │ Isolated profile
│ Pure HTTP + WebSocket │ Separate from your
│ single file, stdlib + websockets │ personal browser
└────────────────────────────────────────┘
没有 Puppeteer。没有 Playwright。没有 Selenium。 只有直接进行 CDP 通信。
隐身基准测试 V1
cdpilot 通过一组包含 80 个高难度网页任务的测试进行基准评测,以衡量其应对现代反机器人系统的成功率。Gemini 2.5 Flash 作为控制器驱动 cdpilot;成功是指完整完成任务且未遭拦截。
v0.5.3 结果(当前)
| 类别 | 成功数 / 总数 | 比率 |
|---|---|---|
| 自定义反机器人 | 5 / 5 | 100.0% |
| Temu 滑块 | 1 / 1 | 100.0% |
| hCaptcha | 2 / 3 | 67.0% |
| Cloudflare | 12 / 22 | 55.0% |
| DataDome | 5 / 13 | 38.0% |
| reCaptcha | 2 / 6 | 33.0% |
| Akamai | 1 / 6 | 17.0% |
| PerimeterX | 2 / 18 | 11.0% |
| GeeTest | 0 / 4 | 0.0% |
| Shape | 0 / 1 | 0.0% |
| Kasada | 0 / 1 | 0.0% |
| 总计 | 30 / 80 | 37.5% |
版本历史
| 版本 | 模式 | 总数 | 比率 |
|---|---|---|---|
| v0.5.0 | 基线(关闭隐身 / 关闭自适应) | 30 / 80 | 37.5% |
| v0.5.0 | 仅隐身(开启隐身 / 关闭自适应) | 32 / 80 | 40.0% |
| v0.5.0 | 完整(开启隐身 / 开启自适应) | 26 / 80 | 32.5% |
| v0.5.1 | 完整 — 回归问题修复 | 29 / 80 | 36.25% |
| v0.5.2 | 完整 — 熵自动钩子 | 28 / 80 | 35.0% |
| v0.5.3 | 完整 — 收紧熵作用范围 | 30 / 80 | 37.5% |
| v0.6.0 | + CAPTCHA 求解器 + cookies-auto(回归) | 15 / 80 | 18.75% |
| v0.8.0 | 完整 — cookies 限定安全主机 + 按任务清除(无代理,无 TLS 分支) | 29 / 80 | 36.25% |
| v0.7.0(插槽) | + 命名代理池 | 取决于用户代理 | — |
| v0.8.0(插槽) | + TLS 感知启动器(camoufox/undetected-chrome) | 取决于浏览器选择 | — |
cdpilot 不会做什么: cdpilot 是规避引擎,而不是 CAPTCHA 求解器。我们优先采用结构性隐身(JS 指纹识别、行为熵),以防挑战出现。当 CAPTCHA 阻碍进度且无法绕过时,任务就会失败——这才是对我们成功率的诚实定义。PerimeterX(2/18)、GeeTest(0/4)和 Akamai(1/6)是已知弱项;v0.7+(住宅代理)和 v0.8+(通过 camoufox 修正 TLS 指纹)将直接针对这些问题。
推荐配置
根据 Stealth Bench V1 的结果:
- 速度优先(适用于大多数场景):
cdpilot launch— 使用默认浏览器行为,不应用补丁 - 启用 Stealth(推荐,综合表现最佳):
cdpilot launch && cdpilot stealth on - 完整自适应(适用于特定的验证码密集型工作流):
cdpilot launch && cdpilot stealth on && cdpilot adaptive on
对于 Stealth Bench V1 的任务组合,完整自适应层与基准方案持平(30/80 对 30/80)。仅启用 Stealth(32/80 = 40%)仍是表现最佳的单一变体。请针对你的具体工作负载进行测试并择优选择。
对比
| 特性 | cdpilot | Puppeteer | Playwright | Selenium |
|---|---|---|---|---|
| 安装大小 | 一个 Python 文件 + 一个小型 Node 启动器,无需 node_modules | 400MB+ | 200MB+ | 100MB+ |
| 依赖项 | 0 npm(Python:websockets,自动安装) | 50+ | 30+ | Java + 驱动程序 |
| 设置时间 | 即时 | 数分钟 | 数分钟 | 麻烦 |
| 适用于 AI Agent | 是 | 手动配置 | 手动配置 | 手动配置 |
| 浏览器下载 | 否 | 是(Chromium) | 是(3 个浏览器) | 否 |
| CLI 优先 | 是 | 否(库) | 否(库) | 否 |
| MCP 支持 | 是 | 否 | 否 | 否 |
商业化 / Pro(即将推出)
cdpilot CLI 现在是、将来也始终是免费且开源的(MIT)。
未来的付费产品:
- cdpilot cloud — 远程浏览器实例,无需本地浏览器
- 团队控制面板 — 共享会话、审计日志、使用情况分析
- 优先支持 — 为企业集成提供直接帮助
安全性
- 隔离的浏览器配置文件 — cdpilot 在
~/.cdpilot/profile中运行,与日常使用的浏览器分开。你的 Cookie、密码和历史记录绝不会暴露。 - 禁止任意文件访问 — MCP 截图文件名会经过清理,并限制在截图目录中。路径遍历会被阻止。
- 安全的 CSS 选择器 — 传递给
querySelector的所有选择器都会进行 JSON 转义,以防止注入。 - 不暴露网络 — CDP 仅监听
127.0.0.1。默认情况下无法进行远程连接。 - 无依赖项 — 零 npm/Python 运行时依赖,意味着没有供应链攻击面。
发现漏洞?请直接给维护者发送邮件,而不要创建公开问题。
Cookie 持久化(v0.6+)
按主机缓存 Cookie,并在导航前自动重放。对于存在高成本挑战的网站(Cloudflare、DataDome)尤其有用——通过验证后,通行 Cookie(cf_clearance、__cf_bm)会被缓存,并在下次访问时重放。
# Enable auto-mode — cookies saved/replayed on every navigate
cdpilot cookies auto on
# Manual per-host workflow
cdpilot cookies save --host x.com # cache current session cookies
cdpilot cookies load --host x.com # inject before navigating
cdpilot cookies cf-replay https://x.com # explicit CF clearance injection
# Inspect and clean
cdpilot cookies list # all cached hosts + age + CF flag
cdpilot cookies clear --older-than 7d # prune stale cache
存储位置:~/.cdpilot/cookies/<host>/cookies.json(权限为 chmod 600,绝不会提交到 git)。
加载时会自动筛除已过期的 Cookie。
路线图
唯一内置测试断言的浏览器 MCP。以下是我们已发布的内容和接下来的计划:
已发布
- 70+ 个 CLI 命令(导航、点击、填充、截图、PDF、控制台、网络、视频理解、摩擦阶梯……)
- 用于集成 AI Agent 的 MCP 服务(Claude Code、Cursor 等)
- 10 个内置测试断言 — assert、assert-url、assert-title、assert-count、assert-value、assert-attr、assert-visible/hidden、wait-for、check(批量)、screenshot-diff
-
test运行器 +trace查看器 —cdpilot test [--watch]运行*.cdpt.js文件;cdpilot trace open <run>打开该次运行的时光回溯跟踪查看器 - 无障碍树快照(
a11y-snapshot)— 结构化文本带有 @ref 句柄,Agent 可直接操作,无需视觉模型;在我们测量的四个页面上,其体积比页面原始 HTML 小 1.4–42 倍(2026-09-27)。但它并不总比截图更省:链接密集的页面产生的文本可能比小尺寸截图的成本更高 - 高效利用 Token 的截图 — 元素级裁剪(缩小 13 倍)、JPEG 质量控制、格式选择
- 视觉回退(
describe)— 一次调用即可获取无障碍信息、截图和文本 - 带注释的截图 — 在交互元素上叠加 @N 徽标
- 自动等待 — 基于 MutationObserver,自动等待元素最长 5 秒
-
wait-for-text— 基于文本的自适应等待(子树 + characterData),适用于流式 AI 回复、异步提示和无需选择器的同步 -
eval-batch— 在一次 CDP 往返中运行 N 个 JS 表达式(相比顺序执行eval,速度提升 5–30 倍) -
block— 通过Network.setBlockedURLs阻止请求,并内置预设(图片/字体/广告/媒体);启用后页面加载速度提升 3–10 倍 -
dismiss— 使用启发式方法自动点击 LLM 聊天注册墙(EN+TR 模式库,带有破坏性操作防护) -
adaptive— 在受 CAPTCHA 保护的主机上自动升级到 stealth 模式,并按主机持久记忆(“快速运行,翻越障碍”) -
cookies save/load— 将 Cookie 导出/导入为 JSON(在不同运行之间重放 CF/DataDome 通行状态) -
context池 +CDPILOT_TARGET— 隔离的浏览器上下文,可在单个浏览器中实现真正的并行自动化(Playwright 的并行标签页模式) -
fast/show— 集成计时与视觉切换功能。0.5.0 中默认采用静默/快速模式 - WebSocket 池 +
/jsonTTL 缓存 — 为 MCP/批处理工作负载复用连接,且零性能回退 - 批量命令 — 通过 stdin 传入 JSON 数组,执行多步自动化
- 视觉反馈系统(持续绿色发光、光标、涟漪、按键显示)
- AI 控制警告提示(自动化期间用户进行交互时显示红色警告)
- 多项目浏览器隔离(每个项目都有独立的端口和配置文件)
- 预检向导(首次运行时自动安装依赖项)
- 持久 MCP 发光效果(整个 AI 会话期间保持显示,类似 Claude 的橙色发光效果)
- DevExtension 系统(无需浏览器商店即可注入原生 JS)
- 智能命令 —
smart-click、smart-fill、smart-select— 按可见文本进行交互,无需 CSS 选择器或 LLM。现支持禁用元素防护(不再错误地报告“已点击”禁用按钮)、Shadow DOM 遍历(Lightning、Polymer、lit-element 小组件)、根据区域设置匹配文本(土耳其语 İ/i、德语 ß),以及smart-fill浮动标签支持(通过aria-labelledby和closest标签解析适配 Material / Ant / Chakra) - 视频理解(
watch)— 持续将屏幕录制写入环形缓冲区,让 AI Agent 可查询时间窗口并查看动态内容(动画、光标、滚动),而不只是单张静态帧。支持本地file://和在线视频(YouTube/Vimeo/Twitter 等);不支持 DRM 播放器(Netflix) - 摩擦阶梯(
friction)— 6 级渐进式反机器人检测(none → rate_limited → soft_captcha → login_wall → otp_sms → hard_block),支持 EN+TR 双语,只读;触发速率限制时自动退避,登录/OTP/硬拦截会标记为需要人工接管(不进行自主绕过) - 三级 stealth 模式(
mode regular|stealth|undetected)— 通过单一开关控制指纹表面,并按主机自适应学习等级 - 按住求解器(
press-hold)— 模拟真人按下 → 按住 → 释放的手势(高斯分布 3–7 秒 + 微抖动),用于 PerimeterX/HUMAN 行为挑战;captcha-solve会自动路由至此 - 图像 CAPTCHA + 配置文件预热 — 离线 Amazon 图像 OCR(可选
amazoncaptcha库)+ BYOK 图像转文本(capsolver/2captcha);profile warm通过延长配置文件使用时间来提升 reCAPTCHA v3 评分 - 离屏模式(
CDPILOT_OFFSCREEN)— 在不抢占窗口焦点的情况下进行有头渲染 - 数据提取(
extract)— 以文本、JSON 或列表格式提取结构化 DOM 数据 - 页面观察(
observe)— 列出所有交互元素及其可用操作 - 脚本运行器(
run)— 执行.cdp脚本文件并报告通过/失败结果 - iframe 定位 —
"iframe#card >>> input"/--frame可用于元素命令,支持同源和跨源(进程外)框架;智能命令会自动搜索框架
即将推出
- 多实例池(
CDPILOT_POOL_SIZE)—— N 个独立浏览器进程,按负载最低原则分发 - 会话录制与回放——录制浏览器会话并以确定性方式回放
- 隐身模式(Pro)——仿人类的鼠标操作和打字、防指纹追踪、验证码求解
- cdpilot Cloud——托管式浏览器会话 API、REST + WebSocket MCP 端点
- Chrome 扩展——无需命令行,即可在任何浏览器中使用 cdpilot
- 性能审计——通过 CDP Performance 域检测 Core Web Vitals(LCP、CLS、INP)
- WCAG 无障碍审计——自动生成无障碍合规报告
- Claude Code Skill 模式——除 MCP 外,还可作为
.claude/skills/技能运行
有想法?提交 issue 或提交 PR!
贡献
git clone https://github.com/mehmetnadir/cdpilot.git
cd cdpilot
npm install
npm test
欢迎提交 PR!请先阅读 CONTRIBUTING.md。
许可证
MIT——随意使用。
以 cdpilot 理念打造:一个工具,只做一件事,并把它做好。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。