🚀 快速安装

复制以下命令并运行,立即安装此 Skill:

npx skills add https://skills.sh/aradotso/trending-skills/chrome-cdp-live-browser

💡 提示:需要 Node.js 和 NPM

chrome-cdp: 面向 AI 代理的实时 Chrome 会话

技能来自 ara.so — 每日 2026 技能合集。

chrome-cdp 通过 Chrome DevTools 协议(CDP)将你的 AI 代理直接连接到正在运行的 Chrome 浏览器。与启动全新隔离浏览器的浏览器自动化工具不同,它连接到你已经打开的标签页——保留你的登录状态、Cookie 和当前页面状态。

功能

  • 实时会话访问 — 读取并与你已登录的标签页进行交互
  • 持久化守护进程 — 每个标签页一个 WebSocket 守护进程;“允许调试”提示仅出现一次,不会每次命令都弹出
  • 无需 npm 安装 — 只需 Node.js 22+
  • 支持 100+ 标签页 — 可靠处理大量打开的标签页
  • 支持跨域 iframetype 命令即使在跨域 iframe 内也能正常工作

安装

作为 pi 技能安装

pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1

手动安装(适用于 Amp、Claude Code、Cursor、Codex 等)

git clone https://github.com/pasky/chrome-cdp-skill
# 将 skills/chrome-cdp/ 目录复制到你的代理加载上下文的任何位置

在 Chrome 中启用远程调试

  1. 打开 Chrome 并导航到:chrome://inspect/#remote-debugging
  2. 打开“启用远程调试”开关

就这样。无需额外标志,无需重启 Chrome。

该脚本可自动检测 macOS、Linux 和 Windows 上的 Chrome、Chromium、Brave、Edge 和 Vivaldi。对于非标准安装:

export CDP_PORT_FILE=/path/to/DevToolsActivePort

主要命令

所有命令都使用 scripts/cdp.mjs 作为入口点。<target>list 命令显示的 targetId 的唯一前缀。

列出打开的标签页

node scripts/cdp.mjs list
# 输出示例:
# A1B2C3  https://github.com/pasky/chrome-cdp-skill  chrome-cdp-skill
# D4E5F6  https://mail.google.com/mail/u/0/           Gmail

截取标签页截图

node scripts/cdp.mjs shot A1B2
# 将截图保存到运行时目录,并打印文件路径

无障碍树(语义快照)

node scripts/cdp.mjs snap A1B2
# 返回紧凑的语义化无障碍树 — 最适合理解页面结构

完整 HTML 或作用域内 HTML

node scripts/cdp.mjs html A1B2                    # 完整页面 HTML
node scripts/cdp.mjs html A1B2 ".main-content"    # 限制在 CSS 选择器范围内
node scripts/cdp.mjs html A1B2 "#article-body"    # 限制在 ID 范围内

执行 JavaScript

node scripts/cdp.mjs eval A1B2 "document.title"
node scripts/cdp.mjs eval A1B2 "window.location.href"
node scripts/cdp.mjs eval A1B2 "document.querySelectorAll('a').length"

导航到 URL

node scripts/cdp.mjs nav A1B2 https://example.com
# 导航并等待页面加载完成

网络资源计时

node scripts/cdp.mjs net A1B2
# 显示当前页面的网络资源计时信息

点击元素

node scripts/cdp.mjs click A1B2 "button.submit"
node scripts/cdp.mjs click A1B2 "#login-btn"
node scripts/cdp.mjs click A1B2 "[data-testid='confirm']"

在坐标处点击

node scripts/cdp.mjs clickxy A1B2 320 480
# 在 CSS 像素坐标 (x=320, y=480) 处点击

输入文本

node scripts/cdp.mjs type A1B2 "Hello, world!"
# 在当前聚焦的元素上输入 — 在跨域 iframe 中也能工作

加载更多(点击直到消失)

node scripts/cdp.mjs loadall A1B2 "button.load-more"
# 持续点击选择器,直到它从 DOM 中消失

打开新标签页

node scripts/cdp.mjs open
node scripts/cdp.mjs open https://example.com
# 注意:会触发 Chrome 的“允许”提示

停止守护进程

node scripts/cdp.mjs stop          # 停止所有守护进程
node scripts/cdp.mjs stop A1B2     # 停止特定标签页的守护进程

原始 CDP 命令透传

node scripts/cdp.mjs evalraw A1B2 "Page.getFrameTree"
node scripts/cdp.mjs evalraw A1B2 "Runtime.evaluate" '{"expression":"1+1"}'

常见模式

模式:读取已登录的页面

# 列出标签页找到你的目标
node scripts/cdp.mjs list

# 获取无障碍树以获得语义视图
node scripts/cdp.mjs snap D4E5

# 或获取特定部分的作用域 HTML
node scripts/cdp.mjs html D4E5 ".email-list"

模式:填写并提交表单

# 点击输入框
node scripts/cdp.mjs click A1B2 "input[name='search']"

# 输入文本
node scripts/cdp.mjs type A1B2 "我的搜索查询"

# 点击提交按钮
node scripts/cdp.mjs click A1B2 "button[type='submit']"

# 截图验证结果
node scripts/cdp.mjs shot A1B2

模式:使用 JavaScript 提取数据

# 获取页面所有链接的 href
node scripts/cdp.mjs eval A1B2 "Array.from(document.querySelectorAll('a')).map(a => a.href)"

# 获取特定元素的文本内容
node scripts/cdp.mjs eval A1B2 "document.querySelector('.price').textContent.trim()"

# 将表格数据作为 JSON 获取
node scripts/cdp.mjs eval A1B2 "
  Array.from(document.querySelectorAll('table tr')).map(row =>
    Array.from(row.querySelectorAll('td,th')).map(cell => cell.textContent.trim())
  )
"

模式:导航并等待

# 导航并立即读取页面
node scripts/cdp.mjs nav A1B2 https://news.ycombinator.com
node scripts/cdp.mjs snap A1B2

模式:分页内容

# 持续加载内容直到“加载更多”按钮消失
node scripts/cdp.mjs loadall A1B2 "button[data-action='load-more']"

# 然后提取所有加载的内容
node scripts/cdp.mjs eval A1B2 "document.querySelectorAll('.item').length"

模式:脚本集成(Node.js)

import { execFile } from 'node:child_process';
import { promisify } from 'node:util';

const exec = promisify(execFile);
const CDP = (...args) => exec('node', ['scripts/cdp.mjs', ...args]);

async function getPageTitle(tabPrefix) {
  const { stdout } = await CDP('eval', tabPrefix, 'document.title');
  return stdout.trim();
}

async function takeScreenshot(tabPrefix) {
  const { stdout } = await CDP('shot', tabPrefix);
  return stdout.trim(); // 返回文件路径
}

async function navigateAndSnap(tabPrefix, url) {
  await CDP('nav', tabPrefix, url);
  const { stdout } = await CDP('snap', tabPrefix);
  return stdout;
}

// 使用示例
const tabs = (await CDP('list')).stdout;
console.log(tabs);

配置

环境变量 用途
CDP_PORT_FILE 非标准浏览器安装时的 DevToolsActivePort 文件路径

守护进程在20 分钟无活动后会自动退出——正常使用中无需手动清理。

故障排除

“允许调试”提示反复出现

如果守护进程没有持久化,就会发生这种情况。确保你使用相同的 scripts/cdp.mjs 入口点——它会自动管理守护进程生命周期。如果你在会话中途切换了工具,运行 stop 并让守护进程重新启动。

未检测到浏览器

如果自动检测失败,找到你的 DevToolsActivePort 文件并设置环境变量:

# macOS Chrome 示例
export CDP_PORT_FILE="$HOME/Library/Application Support/Google/Chrome/Default/DevToolsActivePort"

# Linux Chrome 示例
export CDP_PORT_FILE="$HOME/.config/google-chrome/Default/DevToolsActivePort"

未找到目标 / 前缀不明确

再次运行 list——当标签页关闭或重新打开时,标签页 ID 会改变。如果多个标签页共享相同的前缀字符,请使用更长的前缀。

远程调试开关不可见

确保你在 chrome://inspect/#remote-debugging(而不仅仅是 chrome://inspect/)。开关在页面的右上角。

Node.js 版本错误

此项目需要 Node.js 22+。使用 node --version 检查,如果需要升级,可通过 nvm 或你的包管理器进行升级。

截图为空白或尺寸错误

截图反映实际渲染的视口。如果标签页在后台窗口,或者操作系统启用了显示缩放,clickxy 的像素坐标可能需要调整。使用 snapeval 检查 DOM 状态,而不是仅仅依赖截图。

架构说明

  • 无 Puppeteer、无 Playwright、无中间层 — 纯 CDP WebSocket
  • 每个标签页一个持久化守护进程(首次访问时自动启动)
  • 守护进程重用正是支持 100+ 标签页可靠工作的原因(没有目标枚举超时问题)
  • type 直接使用 CDP Input 域,绕过 iframe 跨域限制

📄 原始文档

完整文档(英文):

https://skills.sh/aradotso/trending-skills/chrome-cdp-live-browser

💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。