chrome-cdp-live-browser

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Chrome 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
chrome://inspect/#remote-debugging
and toggle the switch. That's it — no flags, no restart needed.
访问
chrome://inspect/#remote-debugging
并切换开关即可完成设置——无需配置启动参数,无需重启浏览器。

Install as a pi skill

作为pi skill安装

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

For other agents (Claude Code, Cursor, Amp, etc.)

适配其他Agent(Claude Code、Cursor、Amp等)

Clone the repo and use the
skills/chrome-cdp/
directory:
bash
git clone https://github.com/pasky/chrome-cdp-skill.git
克隆仓库并使用
skills/chrome-cdp/
目录:
bash
git clone https://github.com/pasky/chrome-cdp-skill.git

Point 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
undefined
bash
undefined

List 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 list
bash
scripts/cdp.mjs list

Output:

输出示例:

abc123 https://github.com/user/repo GitHub - user/repo

abc123 https://github.com/user/repo GitHub - user/repo

ghi789 https://app.internal.co Internal Dashboard

ghi789 https://app.internal.co 内部仪表板

undefined
undefined

2. Inspect page structure

2. 检查页面结构

bash
undefined
bash
undefined

Accessibility 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"
undefined
scripts/cdp.mjs html abc123 "#issue-list"
undefined

3. 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
undefined

4. Interact with the page

通过eval命令从实时页面收集结构化数据

bash
undefined
scripts/cdp.mjs eval abc123 " JSON.stringify( Array.from(document.querySelectorAll('.issue-title')) .map(el => ({ title: el.textContent.trim(), href: el.closest('a')?.href })) ) "
undefined

Fill 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
undefined

Wait for navigation and check result

填充搜索框并提交

scripts/cdp.mjs snap abc123
undefined
scripts/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 abc123
scripts/cdp.mjs snap abc123
undefined

Saves PNG to runtime dir, path printed to stdout

5. 截图进行视觉验证

undefined
bash
scripts/cdp.mjs shot abc123

Configuration

将PNG图片保存到运行时目录,路径会输出到标准输出

Non-standard browser profile location

If Chrome stores
DevToolsActivePort
in a non-default path:
bash
export CDP_PORT_FILE="/path/to/your/chrome/profile/DevToolsActivePort"
scripts/cdp.mjs list
Default 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
undefined

Daemon 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的
DevToolsActivePort
存储在非默认路径:
bash
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()) ) "
undefined
bash
undefined

Scraping a page that requires infinite scroll

无需登录——使用你现有的会话

bash
undefined
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()) ) "
undefined

Click "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"
undefined
bash
undefined

Running a multi-step form automation

重复点击“加载更多”直到按钮消失,然后提取所有内容

bash
TARGET=abc123
scripts/cdp.mjs loadall abc123 "button.load-more" scripts/cdp.mjs html abc123 ".results-container"
undefined

Fill 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=abc123

Select 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
undefined
scripts/cdp.mjs click $TARGET "button[type='submit']"

Raw CDP for advanced use cases

验证结果

bash
undefined
scripts/cdp.mjs snap $TARGET
undefined

Capture full page PDF

原始CDP命令用于高级场景

scripts/cdp.mjs evalraw abc123 Page.printToPDF '{}'
bash
undefined

Get 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}'
undefined
scripts/cdp.mjs evalraw abc123 Network.getCookies '{}'

Troubleshooting

模拟移动端视口

"Cannot connect to Chrome" / no output from
list

  1. Confirm remote debugging is enabled: visit
    chrome://inspect/#remote-debugging
  2. Check that
    DevToolsActivePort
    exists:
    bash
    ls ~/Library/Application\ Support/Google/Chrome/DevToolsActivePort   # macOS
    ls ~/.config/google-chrome/DevToolsActivePort                        # Linux
  3. Set
    CDP_PORT_FILE
    explicitly if using a non-standard profile
scripts/cdp.mjs evalraw abc123 Emulation.setDeviceMetricsOverride
'{"width":375,"height":812,"deviceScaleFactor":3,"mobile":true}'
undefined

"Allow debugging" prompt keeps appearing

故障排除

“无法连接到Chrome” /
list
命令无输出

This 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 (
node --version
should be 22+).
  1. 确认已启用远程调试:访问
    chrome://inspect/#remote-debugging
  2. 检查
    DevToolsActivePort
    文件是否存在:
    bash
    ls ~/Library/Application\ Support/Google/Chrome/DevToolsActivePort   # macOS
    ls ~/.config/google-chrome/DevToolsActivePort                        # Linux
  3. 如果使用非标准配置文件,显式设置
    CDP_PORT_FILE
    环境变量

Timeout with many tabs open

“允许调试”提示持续出现

Unlike tools that re-enumerate all targets on every command,
chrome-cdp
targets tabs by prefix ID directly. If you see slowness, use a more specific target prefix to avoid ambiguity.
该提示仅在每个标签页的守护进程首次启动时触发一次。首次向标签页发送命令后,守护进程会持续运行,后续命令将跳过该提示。如果提示持续出现,可能是守护进程崩溃——请检查Node.js版本(
node --version
应显示22+)。

Commands work but screenshot is blank

打开大量标签页时出现超时

The page may not have finished rendering. Chain an
eval
to wait:
bash
scripts/cdp.mjs eval abc123 "
  new Promise(r => {
    if (document.readyState === 'complete') r();
    else window.addEventListener('load', r);
  })
"
scripts/cdp.mjs shot abc123
与每次命令都重新枚举所有目标的工具不同,
chrome-cdp
通过前缀ID直接定位标签页。如果遇到缓慢问题,请使用更具体的目标前缀以避免歧义。

Type command not working in iframes

命令执行成功但截图为空

The
type
command is specifically designed to work across cross-origin iframes — make sure you're using
type
(not a click+eval workaround) for iframe inputs.
页面可能尚未完成渲染。可以添加
eval
命令等待页面加载:
bash
scripts/cdp.mjs eval abc123 "
  new Promise(r => {
    if (document.readyState === 'complete') r();
    else window.addEventListener('load', r);
  })
"
scripts/cdp.mjs shot abc123

How It Works Internally

Type命令在iframe中无法工作

  1. Reads
    DevToolsActivePort
    to find Chrome's debugging WebSocket port
  2. On first access to a
    <target>
    , spawns a lightweight Node.js daemon that holds the WebSocket session open
  3. Commands communicate with the daemon via a local socket
  4. Daemons auto-clean after 20 minutes idle
  5. 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.
type
命令专门设计用于跨源iframe——确保你使用
type
命令(而非点击+eval的替代方案)来操作iframe中的输入框。

内部工作原理

  1. 读取
    DevToolsActivePort
    文件以找到Chrome的调试WebSocket端口
  2. 首次访问
    <target>
    时,启动一个轻量级Node.js守护进程来保持WebSocket会话连接
  3. 命令通过本地套接字与守护进程通信
  4. 守护进程在闲置20分钟后自动清理
  5. 无需Puppeteer或中间层——仅使用原始CDP消息
这种架构是它能可靠处理100+个打开标签页的原因:目标枚举仅会触及你指定的标签页,而非所有标签页。