mcpField
B
browser-harness

browser-harness

github.com/davidondrej生产力4.2k200 次安装今天更新
代码仓库

关于 browser-harness

browser-harness 是通过 CDP 控制浏览器的技能,可连接用户正在运行的 Chrome 和现有会话。它为 Agent 提供交互式浏览、认证内容提取及视觉验证的操作指引。

主要功能

  1. 01通过 CDP 控制浏览器
  2. 02基于截图交互与检查
  3. 03提取需认证的页面内容
  4. 04使用远程浏览器会话
  5. 05复用交互操作指引

适用场景

  1. 01完成需登录的网站流程
  2. 02提取登录墙后的页面内容
  3. 03验证界面操作后的页面状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davidondrej/skills --skill browser-harness

安装后在 Claude Code 中输入/browser-harness确认已加载。

附带文件references/install.md

详细介绍

browser-harness

通过 CDP 直接控制浏览器。针对特定任务的编辑,请使用 agent-workspace/agent_helpers.py。有关设置、安装或连接问题,请阅读 install.md。

**先检查路由:**如果任务不需要交互(无需点击、登录或填写表单),你只想获取页面内容,请改用 DeepAPI POST /v1/scrape/website,而不要驱动浏览器——请参阅 deepapi 技能。任务需要真实浏览器时,请使用 browser-harness:例如需要交互、处理依赖大量 JavaScript 的流程、使用已登录会话或进行视觉验证。

默认不启用域名技能(agent-workspace/domain-skills/ 下由社区贡献的各站点操作指南)。设置 BH_DOMAIN_SKILLS=1 即可启用;请参阅底部章节。

如果设置了 BH_DOMAIN_SKILLS=1,且任务针对特定网站,请先阅读匹配的 agent-workspace/domain-skills/<site>/ 目录中的每个文件,再设计操作方案。

用法

browser-harness -c '
new_tab("https://docs.browser-use.com")
wait_for_load()
print(page_info())
'
  • 作为 browser-harness 调用——它已加入 $PATH。无需 cd,也无需 uv run。
  • 首次导航应使用 new_tab(url),而不是 goto_url(url)——goto 会在用户当前活动标签页中运行,覆盖用户正在进行的操作。

工具调用格式

browser-harness -c '
# any python. helpers pre-imported. daemon auto-starts.
'

run.py 会在执行前调用 ensure_daemon()——除非你有意为之,否则无需手动启动或停止。

远程浏览器

可为并行子 Agent 使用远程浏览器(每个子 Agent 通过不同的 BU_NAME 获取独立浏览器),也可在无头服务器上使用。必须设置 BROWSER_USE_API_KEY。start_remote_daemon、list_cloud_profiles、list_local_profiles、sync_local_profile 均已预先导入。

监督这些子 Agent 时,每次检查后都要向用户发送一条非常简短的状态消息:说明它们正在做什么,以及进展是否顺利。

Claude Code cmux 提示:Claude 完成后,可能会预填一条预测的下一条用户消息;该草稿来自 Claude,并非用户发言。

browser-harness -c '
start_remote_daemon("work")                               # default — clean browser, no profile
# start_remote_daemon("work", profileName="my-work")      # reuse a cloud profile (already logged in)
# start_remote_daemon("work", profileId="<uuid>")         # same, but by UUID
# start_remote_daemon("work", proxyCountryCode="de", timeout=120)   # DE proxy, 2-hour timeout
# start_remote_daemon("work", proxyCountryCode=None)      # disable the Browser Use proxy
'

BU_NAME=work browser-harness -c '
new_tab("https://example.com")
print(page_info())
'

start_remote_daemon 会打印 liveUrl,并在检测到图形界面时自动在本地浏览器中打开,以便用户实时查看。无头服务器只会打印 URL——请将其分享给用户。守护进程会在关闭时向云端浏览器发送 PATCH 请求以停止运行,从而保留配置文件状态。远程守护进程运行期间会持续计费,直到超时。

配置文件(仅包含 Cookie 的登录状态)详见 interaction-skills/profile-sync.md——其中介绍了 list_cloud_profiles()、通过对话询问“使用哪个配置文件?”的模式,以及用于上传本地 Chrome 配置文件的 sync_local_profile()。

交互技能

如果你在导航时遇到某种具体操作机制的困难,请查看 interaction-skills/ 中的辅助工具。这些技能涵盖可复用的 UI 操作机制,例如对话框、标签页、下拉菜单、iframe 和上传。可用的交互技能包括:

  • connection.md
  • cookies.md
  • cross-origin-iframes.md
  • dialogs.md
  • downloads.md
  • drag-and-drop.md
  • dropdowns.md
  • iframes.md
  • network-requests.md
  • print-as-pdf.md
  • profile-sync.md
  • screenshots.md
  • scrolling.md
  • shadow-dom.md
  • tabs.md
  • uploads.md
  • viewport.md

实际可行的方法

  • 截图优先:使用 capture_screenshot() 快速了解当前页面、查找可见目标,并决定是否需要点击、使用选择器或继续导航。
  • 点击:capture_screenshot() → 读取图像上的像素位置 → click_at_xy(x, y) → capture_screenshot() 进行验证。抑制「先定位,再点击」的 Playwright 习惯反射——不要使用 getBoundingClientRect,也不要搜寻选择器。仅当目标没有可见几何信息(隐藏输入框、0×0 节点)时才使用 DOM。命中测试在 Chrome 的浏览器进程中进行,因此点击可穿过 iframe / shadow DOM / 跨域内容,无需额外操作。
  • 批量 HTTP 请求:使用 http_get(url) + ThreadPoolExecutor。静态页面无需浏览器(2.8 秒处理 249 个 Netflix 页面)。
  • goto 后:使用 wait_for_load()。
  • 标签页错误或过时:使用 ensure_real_tab()。当前标签页过时或属于内部页面时使用它;守护进程也会在下次调用时自动从过时会话中恢复。
  • 验证:print(page_info()) 是最简单的「是否正常运行?」检查,但默认应通过截图验证可见操作是否确实生效。
  • DOM 读取:当截图显示坐标并非合适工具时,使用 js(...) 进行检查和提取。
  • iframe 网站(Azure blades、Salesforce):click_at_xy(x, y) 可以穿透;仅当坐标点击并非合适工具时,才使用 iframe DOM 操作。
  • 身份验证墙:被重定向到登录页面时,停止操作并询问用户。不要根据截图输入凭据。
  • 对于辅助函数未覆盖的操作:使用原始 CDP 调用 cdp("Domain.method", params)。

设计约束

  • 默认使用坐标点击。Input.dispatchMouseEvent 在合成器层级穿过 iframe / shadow DOM / 跨域内容。
  • 连接到用户正在运行的 Chrome。不要启动自己的浏览器。
  • cdp-use 仅用于 CDPClient.send_raw。优先使用原始 CDP 字符串,而非类型化封装。
  • run.py 保持精简。不要添加 argparse、子命令或额外的控制层。
  • 核心辅助函数保持简短。针对特定任务新增的辅助函数放在 agent-workspace/agent_helpers.py 中;守护进程/引导程序和远程会话管理放在核心包中。
  • 不要添加管理层。不要添加重试框架、会话管理器、守护进程监督程序、配置系统或日志框架。

Hermes Agent 集成

以可编辑模式安装在 ~/Developer/browser-harness:uv tool install -e .。二进制文件位于 ~/.local/bin/browser-harness。技能位于 ~/.hermes/skills/browser-harness/。

Frontmatter 注意事项: 上游 SKILL.md 的 frontmatter 中包含 name: browser,这会与 Hermes 内置的 browser 工具集冲突。复制到 ~/.hermes/skills/ 时,请将 frontmatter 中的名称改为 name: browser-harness,否则 Hermes 会遮蔽自身的浏览器工具,或与其冲突。

Brave Browser: 与 Chrome 的工作方式完全相同。在 brave://inspect/#remote-debugging 中启用远程调试(勾选同一个复选框)。该工具会自动发现 Brave 的配置目录。

已验证的经过身份验证的内容提取模式

browser-harness 会连接到用户实际使用且已登录的浏览器,非常适合从登录墙后的网站提取内容;在这些网站上,web_extract 或 Hermes 内置的 browser_navigate 会失效(例如 X/Twitter 文章、LinkedIn 和付费墙网站)。

模式:

browser-harness -c '
new_tab("https://x.com/user/status/123456")
wait_for_load()
import time
time.sleep(5)  # let JS-heavy pages render
text = js("""
    const article = document.querySelector("article");
    if (article) return article.innerText;
    return document.body.innerText;
""")
with open("/tmp/extracted.txt", "w") as f:
    f.write(text)
print("Written", len(text), "chars")
'
  • 写入临时文件,避免大型文本的 Shell 转义问题
  • 对 JavaScript 密集型单页应用(SPA)适当使用 time.sleep() 等待(X 和 LinkedIn 需要 3-5 秒)
  • X/Twitter 文章会以内嵌方式呈现——只需通过 DOM 滚动/提取内容,无需额外点击
  • 对于很长的页面,使用带 innerText 的 js(...) 可抓取全部内容,包括首屏以下的内容

Hermes Agent 集成

以可编辑模式安装在 ~/Developer/browser-harness:uv tool install -e .。二进制文件位于 ~/.local/bin/browser-harness。技能位于 ~/.hermes/skills/browser-harness/。

**Frontmatter 注意事项:**上游的 SKILL.md 在 frontmatter 中使用 name: browser,这会与 Hermes 内置的 browser 工具集冲突。复制到 ~/.hermes/skills/ 时,请将 frontmatter 中的名称改为 name: browser-harness。

**Brave Browser:**使用方式与 Chrome 完全相同。在 brave://inspect/#remote-debugging 中启用远程调试(使用相同的复选框)。该工具会自动发现 Brave 的配置文件目录。

已验证的身份验证内容提取模式

browser-harness 会连接到用户正在使用且会话已激活的真实浏览器,非常适合处理需要登录的网站;在这类网站上,web_extract 或 Hermes 内置的 browser_navigate 会失败(如 X/Twitter 文章、LinkedIn、付费墙网站)。

browser-harness -c '
new_tab("https://x.com/user/status/123456")
wait_for_load()
import time
time.sleep(5)  # let JS-heavy pages render
text = js("""
    const article = document.querySelector("article");
    if (article) return article.innerText;
    return document.body.innerText;
""")
with open("/tmp/extracted.txt", "w") as f:
    f.write(text)
print("Written", len(text), "chars")
'
  • 写入临时文件,以避免处理大段文本时的 shell 转义问题
  • 对 JavaScript 密集型单页应用使用 time.sleep() 并留出充足时间(X、LinkedIn 需要 3-5s)
  • X/Twitter 文章会内嵌渲染,只需通过 DOM 滚动或提取内容,无需额外点击
  • 使用带有 innerText 的 js(...) 可抓取所有内容,包括首屏以下的内容

注意事项(实测)

  • Brave Browser 使用 brave://inspect/#remote-debugging,而不是 chrome://inspect/...。该工具会自动发现 Brave 的数据目录。
  • 提取需要登录才能访问的内容(如 X/Twitter 文章)时:使用 new_tab(url) 导航,调用 wait_for_load(),然后通过 js("document.querySelector('article').innerText") 提取。写入临时文件可避免 shell 转义:with open('/tmp/out.txt', 'w') as f: f.write(text)。用户现有的浏览器会话会自动处理身份验证。
  • Omnibox 弹出窗口是假页面目标。需要真实标签页时,请过滤 chrome://omnibox-popup... 及其他内部页面。
  • CDP 目标顺序与 Chrome 可见的标签栏顺序不一致。如果用户指的是“我能看到的第一个/第二个标签页”,请使用 UI 自动化;Target.activateTarget 只能显示已知目标。
  • 默认守护进程会话可能会失效。ensure_real_tab() 会重新连接到真实页面。
  • Browser Use API 在线路上使用 camelCase。cdpUrl、proxyCountryCode 等均如此。
  • 远程 cdpUrl 使用 HTTPS,而不是 ws。通过 /json/version 获取 WebSocket URL。
  • 使用 PATCH /browsers/{id} + {"action":"stop"} 停止云浏览器。
  • 每次执行有意义的操作后,都应重新截图,再判断操作是否成功。通过图像检查状态变化、打开的菜单、页面导航、可见错误,以及页面是否处于预期状态。
  • 使用截图来探索页面。这通常是找到下一个点击目标、发现隐藏阻碍,以及判断是否值得编写选择器的最快方式。
  • 优先使用合成器级操作,而不是框架技巧。先尝试截图、坐标点击和原始按键输入,再添加特定于 DOM 的变通方法。
  • 如果需要特定于框架的 DOM 技巧,请先查看 interaction-skills/。下拉菜单、对话框、iframe、Shadow DOM 和表单相关指南都应放在那里。

领域技能(选择启用)

仅在 BH_DOMAIN_SKILLS=1 时生效。否则请忽略——agent-workspace/domain-skills/ 处于休眠状态,goto_url 不会显示技能文件。

启用后,在自行设计方法之前,先搜索 agent-workspace/domain-skills/<host>/。goto_url 会返回已导航主机对应的最多 10 个技能文件名。

如果发现任何不显而易见的信息——如私有 API、稳定选择器、框架特性、URL 模式、隐藏的等待条件或特定于网站的陷阱——请向 agent-workspace/domain-skills/<site>/ 提交 PR。记录网站的持久性结构(地图,而不是日记)。不要写入像素坐标(布局变化会导致失效)、任务叙述或机密信息——该目录是公开的。

评论

支持 Markdown