chrome-cdp-live-browser
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseChrome CDP Live Browser Skill
Chrome CDP 实时浏览器 Skill
Skill by ara.so — Daily 2026 Skills collection
Connect your AI agent to a live, already-running Chrome session — no fresh browser, no re-login, no automation framework. This skill uses Chrome DevTools Protocol (CDP) directly to interact with tabs you have open right now.
由ara.so开发的Skill — 2026每日Skill合集
将你的AI Agent连接到已运行的Chrome实时会话——无需启动新浏览器、无需重新登录、无需自动化框架。该Skill直接使用Chrome DevTools Protocol (CDP)与你当前打开的标签页进行交互。
What It Does
功能特性
- Reads and interacts with authenticated pages (Gmail, GitHub, internal tools) without re-authenticating
- Takes screenshots of live tab state
- Evaluates JavaScript in page context
- Clicks elements, types text, navigates URLs
- Extracts accessibility trees and HTML for structured page analysis
- Maintains persistent daemon per tab — Chrome's "Allow debugging" prompt fires once, then stays silent
- 读取并交互已认证页面(Gmail、GitHub、内部工具),无需重新认证
- 捕获实时标签页状态截图
- 在页面上下文执行JavaScript
- 点击元素、输入文本、导航URL
- 提取无障碍树和HTML用于结构化页面分析
- 为每个标签页维持持久化守护进程——Chrome的“允许调试”提示仅触发一次,后续不再弹出
Prerequisites
前置要求
- Node.js 22+
- Chrome, Chromium, Brave, Edge, or Vivaldi
- Remote debugging enabled in Chrome
- Node.js 22+
- Chrome、Chromium、Brave、Edge或Vivaldi浏览器
- Chrome中已启用远程调试
Installation
安装步骤
Enable Remote Debugging in Chrome
在Chrome中启用远程调试
Navigate to and toggle the switch. That's it — no flags, no restart needed.
chrome://inspect/#remote-debugging访问并切换开关即可完成设置——无需配置启动参数,无需重启浏览器。
chrome://inspect/#remote-debuggingInstall as a pi skill
作为pi skill安装
bash
pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1bash
pi install git:github.com/pasky/chrome-cdp-skill@v1.0.1For other agents (Claude Code, Cursor, Amp, etc.)
适配其他Agent(Claude Code、Cursor、Amp等)
Clone the repo and use the directory:
skills/chrome-cdp/bash
git clone https://github.com/pasky/chrome-cdp-skill.git克隆仓库并使用目录:
skills/chrome-cdp/bash
git clone https://github.com/pasky/chrome-cdp-skill.gitPoint your agent's skill loader at skills/chrome-cdp/
将你的Agent的skill加载器指向skills/chrome-cdp/目录
No `npm install` needed — zero runtime dependencies beyond Node.js 22+.
无需执行`npm install`——除Node.js 22+外无任何运行时依赖。Key Commands
核心命令
bash
undefinedbash
undefinedList all open tabs with their targetIds
列出所有打开的标签页及其targetIds
scripts/cdp.mjs list
scripts/cdp.mjs list
Take a screenshot (saves to runtime dir)
捕获截图(保存到运行时目录)
scripts/cdp.mjs shot <target>
scripts/cdp.mjs shot <target>
Get accessibility tree (compact, semantic — best for understanding page structure)
获取无障碍树(简洁、语义化——最适合理解页面结构)
scripts/cdp.mjs snap <target>
scripts/cdp.mjs snap <target>
Get full HTML or scoped to a CSS selector
获取完整HTML或指定CSS选择器范围内的HTML
scripts/cdp.mjs html <target>
scripts/cdp.mjs html <target> ".main-content"
scripts/cdp.mjs html <target>
scripts/cdp.mjs html <target> ".main-content"
Evaluate JavaScript in the page
在页面中执行JavaScript
scripts/cdp.mjs eval <target> "document.title"
scripts/cdp.mjs eval <target> "window.location.href"
scripts/cdp.mjs eval <target> "document.title"
scripts/cdp.mjs eval <target> "window.location.href"
Navigate to a URL and wait for load
导航到指定URL并等待加载完成
scripts/cdp.mjs nav <target> https://example.com
scripts/cdp.mjs nav <target> https://example.com
Click an element by CSS selector
通过CSS选择器点击元素
scripts/cdp.mjs click <target> "button.submit"
scripts/cdp.mjs click <target> "button.submit"
Click at specific pixel coordinates
点击指定像素坐标位置
scripts/cdp.mjs clickxy <target> 320 480
scripts/cdp.mjs clickxy <target> 320 480
Type text at the currently focused element (works in cross-origin iframes)
在当前聚焦的元素中输入文本(支持跨源iframe)
scripts/cdp.mjs type <target> "hello world"
scripts/cdp.mjs type <target> "hello world"
Get network resource timing
获取网络资源计时信息
scripts/cdp.mjs net <target>
scripts/cdp.mjs net <target>
Click "load more" repeatedly until selector disappears
重复点击“加载更多”按钮直到该选择器消失
scripts/cdp.mjs loadall <target> ".load-more-btn"
scripts/cdp.mjs loadall <target> ".load-more-btn"
Raw CDP command passthrough
直接传递原始CDP命令
scripts/cdp.mjs evalraw <target> Runtime.evaluate '{"expression":"1+1"}'
scripts/cdp.mjs evalraw <target> Runtime.evaluate '{"expression":"1+1"}'
Open a new tab (triggers Allow prompt)
打开新标签页(会触发允许调试提示)
scripts/cdp.mjs open https://example.com
scripts/cdp.mjs open https://example.com
Stop daemon for a specific tab, or all daemons
停止指定标签页的守护进程,或停止所有守护进程
scripts/cdp.mjs stop <target>
scripts/cdp.mjs stop
`<target>` is a unique prefix of the `targetId` shown by `list`.scripts/cdp.mjs stop <target>
scripts/cdp.mjs stop
`<target>`是`list`命令输出中`targetId`的唯一前缀。Typical Agent Workflow
典型Agent工作流
1. Discover open tabs
1. 发现已打开的标签页
bash
scripts/cdp.mjs listbash
scripts/cdp.mjs listOutput:
输出示例:
abc123 https://github.com/user/repo GitHub - user/repo
abc123 https://github.com/user/repo GitHub - user/repo
def456 https://mail.google.com Gmail
def456 https://mail.google.com Gmail
ghi789 https://app.internal.co Internal Dashboard
ghi789 https://app.internal.co 内部仪表板
undefinedundefined2. Inspect page structure
2. 检查页面结构
bash
undefinedbash
undefinedAccessibility tree is fastest for understanding layout
无障碍树是理解页面布局最快的方式
scripts/cdp.mjs snap abc123
scripts/cdp.mjs snap abc123
Scoped HTML for a specific component
获取指定组件范围内的HTML
scripts/cdp.mjs html abc123 "#issue-list"
undefinedscripts/cdp.mjs html abc123 "#issue-list"
undefined3. Extract data with JavaScript
3. 使用JavaScript提取数据
javascript
// Using eval to collect structured data from a live page
scripts/cdp.mjs eval abc123 "
JSON.stringify(
Array.from(document.querySelectorAll('.issue-title'))
.map(el => ({ title: el.textContent.trim(), href: el.closest('a')?.href }))
)
"javascript
undefined4. Interact with the page
通过eval命令从实时页面收集结构化数据
bash
undefinedscripts/cdp.mjs eval abc123 "
JSON.stringify(
Array.from(document.querySelectorAll('.issue-title'))
.map(el => ({ title: el.textContent.trim(), href: el.closest('a')?.href }))
)
"
undefinedFill a search box and submit
4. 与页面交互
scripts/cdp.mjs click abc123 "input[name='q']"
scripts/cdp.mjs type abc123 "my search query"
scripts/cdp.mjs click abc123 "button[type='submit']"
bash
undefinedWait for navigation and check result
填充搜索框并提交
scripts/cdp.mjs snap abc123
undefinedscripts/cdp.mjs click abc123 "input[name='q']"
scripts/cdp.mjs type abc123 "我的搜索关键词"
scripts/cdp.mjs click abc123 "button[type='submit']"
5. Screenshot for visual verification
等待导航完成并检查结果
bash
scripts/cdp.mjs shot abc123scripts/cdp.mjs snap abc123
undefinedSaves PNG to runtime dir, path printed to stdout
5. 截图进行视觉验证
undefinedbash
scripts/cdp.mjs shot abc123Configuration
将PNG图片保存到运行时目录,路径会输出到标准输出
Non-standard browser profile location
—
If Chrome stores in a non-default path:
DevToolsActivePortbash
export CDP_PORT_FILE="/path/to/your/chrome/profile/DevToolsActivePort"
scripts/cdp.mjs listDefault search locations (auto-detected):
- macOS:
~/Library/Application Support/Google/Chrome/ - Linux: ,
~/.config/google-chrome/,~/.config/chromium/~/.config/brave-browser/ - Also checks Vivaldi, Edge, Canary variants
undefinedDaemon lifecycle
配置说明
—
非标准浏览器配置文件位置
Daemons auto-exit after 20 minutes of inactivity. You can manually stop them:
bash
scripts/cdp.mjs stop # stop all
scripts/cdp.mjs stop abc123 # stop one tab's daemon如果Chrome的存储在非默认路径:
DevToolsActivePortbash
export CDP_PORT_FILE="/path/to/your/chrome/profile/DevToolsActivePort"
scripts/cdp.mjs list默认自动检测的搜索位置:
- macOS:
~/Library/Application Support/Google/Chrome/ - Linux: ,
~/.config/google-chrome/,~/.config/chromium/~/.config/brave-browser/ - 同时支持检测Vivaldi、Edge、Canary等变体
Integration Patterns
守护进程生命周期
Reading a logged-in page (e.g. GitHub notifications)
—
bash
undefined守护进程在闲置20分钟后会自动退出。你也可以手动停止它们:
bash
scripts/cdp.mjs stop # 停止所有守护进程
scripts/cdp.mjs stop abc123 # 停止指定标签页的守护进程No login needed — uses your existing session
集成模式
—
读取已登录页面(例如GitHub通知)
TARGET=$(scripts/cdp.mjs list | grep github.com | awk '{print $1}' | head -1)
scripts/cdp.mjs eval $TARGET "
JSON.stringify(
Array.from(document.querySelectorAll('.notification-list-item'))
.slice(0, 10)
.map(n => n.querySelector('a')?.textContent?.trim())
)
"
undefinedbash
undefinedScraping a page that requires infinite scroll
无需登录——使用你现有的会话
bash
undefinedTARGET=$(scripts/cdp.mjs list | grep github.com | awk '{print $1}' | head -1)
scripts/cdp.mjs eval $TARGET "
JSON.stringify(
Array.from(document.querySelectorAll('.notification-list-item'))
.slice(0, 10)
.map(n => n.querySelector('a')?.textContent?.trim())
)
"
undefinedClick "load more" until the button disappears, then extract all content
抓取需要无限滚动的页面
scripts/cdp.mjs loadall abc123 "button.load-more"
scripts/cdp.mjs html abc123 ".results-container"
undefinedbash
undefinedRunning a multi-step form automation
重复点击“加载更多”直到按钮消失,然后提取所有内容
bash
TARGET=abc123scripts/cdp.mjs loadall abc123 "button.load-more"
scripts/cdp.mjs html abc123 ".results-container"
undefinedFill form fields
运行多步骤表单自动化
scripts/cdp.mjs click $TARGET "#first-name"
scripts/cdp.mjs type $TARGET "Jane"
scripts/cdp.mjs click $TARGET "#last-name"
scripts/cdp.mjs type $TARGET "Smith"
bash
TARGET=abc123Select a dropdown via JS
填写表单字段
scripts/cdp.mjs eval $TARGET "document.querySelector('#country').value = 'US'"
scripts/cdp.mjs click $TARGET "#first-name"
scripts/cdp.mjs type $TARGET "Jane"
scripts/cdp.mjs click $TARGET "#last-name"
scripts/cdp.mjs type $TARGET "Smith"
Submit
通过JavaScript选择下拉框
scripts/cdp.mjs click $TARGET "button[type='submit']"
scripts/cdp.mjs eval $TARGET "document.querySelector('#country').value = 'US'"
Verify result
提交表单
scripts/cdp.mjs snap $TARGET
undefinedscripts/cdp.mjs click $TARGET "button[type='submit']"
Raw CDP for advanced use cases
验证结果
bash
undefinedscripts/cdp.mjs snap $TARGET
undefinedCapture full page PDF
原始CDP命令用于高级场景
scripts/cdp.mjs evalraw abc123 Page.printToPDF '{}'
bash
undefinedGet all cookies for the page
捕获完整页面PDF
scripts/cdp.mjs evalraw abc123 Network.getCookies '{}'
scripts/cdp.mjs evalraw abc123 Page.printToPDF '{}'
Emulate mobile viewport
获取页面的所有Cookie
scripts/cdp.mjs evalraw abc123 Emulation.setDeviceMetricsOverride
'{"width":375,"height":812,"deviceScaleFactor":3,"mobile":true}'
'{"width":375,"height":812,"deviceScaleFactor":3,"mobile":true}'
undefinedscripts/cdp.mjs evalraw abc123 Network.getCookies '{}'
Troubleshooting
模拟移动端视口
"Cannot connect to Chrome" / no output from list
list—
- Confirm remote debugging is enabled: visit
chrome://inspect/#remote-debugging - Check that exists:
DevToolsActivePortbashls ~/Library/Application\ Support/Google/Chrome/DevToolsActivePort # macOS ls ~/.config/google-chrome/DevToolsActivePort # Linux - Set explicitly if using a non-standard profile
CDP_PORT_FILE
scripts/cdp.mjs evalraw abc123 Emulation.setDeviceMetricsOverride
'{"width":375,"height":812,"deviceScaleFactor":3,"mobile":true}'
'{"width":375,"height":812,"deviceScaleFactor":3,"mobile":true}'
undefined"Allow debugging" prompt keeps appearing
故障排除
—
“无法连接到Chrome” / list
命令无输出
listThis prompt fires once per tab per daemon start. After the first command to a tab, the daemon persists and subsequent commands skip the prompt. If it keeps appearing, the daemon may be crashing — check for Node.js version ( should be 22+).
node --version- 确认已启用远程调试:访问
chrome://inspect/#remote-debugging - 检查文件是否存在:
DevToolsActivePortbashls ~/Library/Application\ Support/Google/Chrome/DevToolsActivePort # macOS ls ~/.config/google-chrome/DevToolsActivePort # Linux - 如果使用非标准配置文件,显式设置环境变量
CDP_PORT_FILE
Timeout with many tabs open
“允许调试”提示持续出现
Unlike tools that re-enumerate all targets on every command, targets tabs by prefix ID directly. If you see slowness, use a more specific target prefix to avoid ambiguity.
chrome-cdp该提示仅在每个标签页的守护进程首次启动时触发一次。首次向标签页发送命令后,守护进程会持续运行,后续命令将跳过该提示。如果提示持续出现,可能是守护进程崩溃——请检查Node.js版本(应显示22+)。
node --versionCommands work but screenshot is blank
打开大量标签页时出现超时
The page may not have finished rendering. Chain an to wait:
evalbash
scripts/cdp.mjs eval abc123 "
new Promise(r => {
if (document.readyState === 'complete') r();
else window.addEventListener('load', r);
})
"
scripts/cdp.mjs shot abc123与每次命令都重新枚举所有目标的工具不同,通过前缀ID直接定位标签页。如果遇到缓慢问题,请使用更具体的目标前缀以避免歧义。
chrome-cdpType command not working in iframes
命令执行成功但截图为空
The command is specifically designed to work across cross-origin iframes — make sure you're using (not a click+eval workaround) for iframe inputs.
typetype页面可能尚未完成渲染。可以添加命令等待页面加载:
evalbash
scripts/cdp.mjs eval abc123 "
new Promise(r => {
if (document.readyState === 'complete') r();
else window.addEventListener('load', r);
})
"
scripts/cdp.mjs shot abc123How It Works Internally
Type命令在iframe中无法工作
- Reads to find Chrome's debugging WebSocket port
DevToolsActivePort - On first access to a , spawns a lightweight Node.js daemon that holds the WebSocket session open
<target> - Commands communicate with the daemon via a local socket
- Daemons auto-clean after 20 minutes idle
- No Puppeteer, no intermediary — raw CDP messages only
This architecture is why it handles 100+ open tabs reliably: target enumeration only touches the specific tab you address, not all tabs at once.
typetype—
内部工作原理
—
- 读取文件以找到Chrome的调试WebSocket端口
DevToolsActivePort - 首次访问时,启动一个轻量级Node.js守护进程来保持WebSocket会话连接
<target> - 命令通过本地套接字与守护进程通信
- 守护进程在闲置20分钟后自动清理
- 无需Puppeteer或中间层——仅使用原始CDP消息
这种架构是它能可靠处理100+个打开标签页的原因:目标枚举仅会触及你指定的标签页,而非所有标签页。