---
name: netabrowser-cli
description: >
  Neta 反风控+拟人化浏览器自动化 CLI。养号、电商自动化、AI 探索复杂网页时使用。
  比 playwright-cli 更难被反风控识别（fingerprint-chromium 内核 + patchright 反自动化 +
  贝塞尔曲线鼠标轨迹）。100 账号矩阵养号场景首选。所有操作通过 scripts/nb.sh
  （或 nb.cmd）调用，不需要 HTTP/curl。
license: MIT
metadata:
  version: "2.0"
  category: browser-automation
---

# netabrowser-cli

通过 CLI wrapper 操作常驻浏览器 daemon。daemon 持有 chromium 实例 + 登录态 +
session profile，CLI 是连 daemon 的薄客户端。AI 全程只用 `scripts/nb.sh <cmd>`，
**永远不用 curl 或 HTTP**。

## 快速验证环境

每次开始任务前先验证 daemon 是否启动：

```bash
bash scripts/nb.sh list
```

期望返回 `{ok: true, ...}` 或会话列表。如果连接失败 → backend 没启动，告知用户。

### Chromium 自动下载

`nb.sh` / `nb.cmd` 每次启动都会先跑 `scripts/ensure-chromium.cjs`：

- `packages/netabrowser-cli/chromium/win64/chrome.exe` 已存在 → 秒过。
- 缺失 → 自动从默认 URL 下载 zip（约 170MiB），解压到 `packages/netabrowser-cli/chromium/win64/`，归一化为 397MB 的 Chromium 产物。
- 覆盖：
  - `NETA_CHROMIUM_PATH` 指定已有 `chrome.exe` 绝对路径 → 直接复用，**不会自动下载到别处**（缺失时会报错提醒，避免误下）。
  - `NETA_CHROMIUM_URL` 指定自定义 zip 下载地址（内网镜像/CDN）。
- 解压：Windows 走 PowerShell `Expand-Archive`，Linux/macOS 走 `unzip`（失败回落 `tar`）。

第一次执行任何 `nb` 命令时会看到 `[ensure-chromium] downloading ...` 日志，耐心等完即可。

---

## When to use vs playwright-cli vs patchwright-cli

| Skill | 适用场景 |
|---|---|
| **netabrowser-cli**（本）| 国内反风控严的站（小红书/抖音/淘宝/拼多多/微博）+ 多账号矩阵 + 养号 |
| **patchwright-cli** | 国外 Cloudflare/DataDome 等反爬保护 |
| **playwright-cli** | 测试、无反风控的站 |

**目标是中国电商/社交站点 → 用本 skill。**

---

## 拟人化 vs 效率的选择规则

**用户明确要求"拟人化"/"移动鼠标"/"模拟人工操作"时**：必须用 `snapshot → click/hover` 操作页面元素，不要用 `goto` 直跳 URL。拟人化的价值在于让反风控系统看到真实的鼠标轨迹和点击行为。

**用户只要求"查看/获取信息"没提拟人化时**：优先用 `goto` 直跳目标 URL，更快更稳定。

**典型拟人化流程**（用户要求拟人操作时）：
```bash
bash scripts/nb.sh open https://www.taobao.com --session=tb-main --headed
bash scripts/nb.sh snapshot --session=tb-main          # 找到"已买到"的 ref
bash scripts/nb.sh hover e123 --session=tb-main         # 拟人化 hover 触发下拉
bash scripts/nb.sh wait --session=tb-main --timeout=1000
bash scripts/nb.sh snapshot --session=tb-main          # 重新 snapshot 找下拉项
bash scripts/nb.sh click e456 --session=tb-main         # 拟人化点击
bash scripts/nb.sh wait --session=tb-main --load-state=networkidle
bash scripts/nb.sh snapshot --session=tb-main          # 读取结果
```

**典型效率流程**（只要结果时）：
```bash
bash scripts/nb.sh open https://www.taobao.com --session=tb-main --headed
bash scripts/nb.sh goto https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm --session=tb-main
bash scripts/nb.sh wait --session=tb-main --load-state=networkidle
bash scripts/nb.sh snapshot --session=tb-main
```

---

## 核心工作流

```
nb.sh open    → 启动会话（同名 session 自动恢复登录态）
nb.sh snapshot → 拿 ARIA 树（YAML 格式，含 ref）
nb.sh click/fill/hover [ref]  → 拟人化操作
nb.sh wait    → 等元素/页面状态
nb.sh close   → 关闭（profile 持久化保留）
```

### 最简任务模板

```bash
# 1. 打开（同名 session 复用 profile，登录态自动恢复）
bash scripts/nb.sh open https://www.taobao.com --session=tb-main --headed

# 2. 看页面结构（输出是 ARIA YAML，每个交互元素带 [ref=eN]）
bash scripts/nb.sh snapshot --session=tb-main

# 3. 操作（用 snapshot 中的 ref）
bash scripts/nb.sh click e123 --session=tb-main
bash scripts/nb.sh fill e45 "搜索关键词" --session=tb-main
bash scripts/nb.sh press Enter --session=tb-main

# 4. 等加载完
bash scripts/nb.sh wait --session=tb-main --load-state=networkidle

# 5. 完事关闭（profile 留着下次复用）
bash scripts/nb.sh close --session=tb-main
```

---

## ⚠️ 关键陷阱（不读这段会浪费 token）

### 1. 同名 sessionName 自动复用登录态

profile 目录在 `.netabrowser-data/profiles/<sessionName>/`，cookie/localStorage 在 close 后保留。**每个账号固定一个 sessionName**（如 `taobao-main`），下次 open 自动恢复登录。**不要每次换 sessionName**——会重新登录。

### 2. 首页"立即登录"≠ 没登录

淘宝/拼多多/京东等 SPA 首页加载完后**异步**读 cookie 渲染用户名，snapshot 拍得太早会看到"立即登录"。**正确判断方式：**

- snapshot 里有"已买到"/"我的淘宝"/"我的订单"等只有登录后才出现的链接 → 已登录
- 直接点"已买到"，看跳转到订单页还是登录页 → 实际验证

**不要看到"立即登录"就向用户要账号密码。**

### 3. 头部 hover 触发的链接（淘宝"已买到"等）

淘宝头部"已买到"是 hover 触发的下拉菜单项，单纯 click 不跳转。两种解法：

```bash
# 方法 A：先 hover 触发下拉，再 click
bash scripts/nb.sh hover e123 --session=tb-main      # hover 父菜单
bash scripts/nb.sh wait --session=tb-main --timeout=1000
bash scripts/nb.sh snapshot --session=tb-main         # 重新 snapshot 找下拉项
bash scripts/nb.sh click e456 --session=tb-main

# 方法 B（更快）：直接 goto 目标 URL
bash scripts/nb.sh goto https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm --session=tb-main
```

常用直达 URL：
- 淘宝已购：`https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm`（注意是 `buyertrade` 不是 `buyer.trade`）
- 拼多多订单：`https://mobile.yangkeduo.com/orders.html`
- 京东订单：`https://order.jd.com/center/list.action`

### 4. 何时停止重试（重要）

遇到以下错误**立即停止**，告知用户而不是反复重试：

| 错误 | 含义 | 行动 |
|---|---|---|
| `net::ERR_NAME_NOT_RESOLVED` | DNS 失败 | 报告用户，可能是网络/代理问题 |
| `net::ERR_TIMED_OUT` 连续 2 次 | 站点不可达 | 报告用户 |
| `Ref 'eN' has no bounding box` 同 ref 2 次 | 元素消失或变化 | 重新 snapshot 找新 ref |
| 进入 `chrome-error://` 错误页 | 浏览器内部错误 | 报告用户检查代理/网络 |

**不要：**
- 用不同 URL 瞎试
- snapshot 看到一样内容超过 2 次说明操作没生效，停下分析
- 看到 chrome-error 就反复 reload

---

## Commands

### 会话管理
- `open <url> --session=NAME [--proxy=URL] [--fingerprint-seed=N] [--profile-dir=NAME] [--headed] [--priority=low|normal|high] [--queue]` 启动会话
- `close --session=NAME` 关闭（profile 保留供下次复用）
- `list` 列出所有活跃会话

**代理必须在 open 时指定**，不能给已有 session 追加代理。如果需要换代理，先 close 再 open：
```bash
bash scripts/nb.sh close --session=tb-main
bash scripts/nb.sh open https://www.taobao.com --session=tb-main --headed --proxy=socks5://user:pass@host:port
```

**代理协议必须匹配**：SOCKS5 代理用 `socks5://`，HTTP 代理用 `http://`。写错协议会 400/超时。

**⚠️ 走代理 + headed 时必须延长 bash 工具 timeout**：默认 bash timeout 是 30s，但走代理首次打开浏览器需要 30-60s。**调用 bash 工具时务必传 `timeout: 60000`（毫秒）**——这是 bash 工具的参数（不是 nb.sh 的 --timeout）：
```
// AI 调 bash 工具时这样传：
{ "command": "bash scripts/nb.sh open ... --proxy=socks5://...", "timeout": 60000 }
```
不传 timeout 默认 30s 会被 NetaClaw kill 掉，导致 ECONNRESET。

### 检查
- `snapshot --session=NAME` 获取页面 ARIA 树（YAML 格式，含 ref）
- `screenshot --session=NAME [--full-page] [--out=path]` 截图

### 交互（默认拟人化 mode=full）
- `click <ref> --session=NAME [--mode=full|fast|off]` 点击（含 visible+scrollIntoView 检查）
- `hover <ref> --session=NAME [--mode=...]` 悬停（触发 hover 菜单等）
- `fill <ref> <value> --session=NAME` focus + 清空 + 拟人化输入
- `type <text> --session=NAME` 在已 focused 输入框打字
- `press <key> --session=NAME` 按键（Enter/Tab/Escape/Control+A 等）
- `select <ref> <value> --session=NAME` 选择 `<select>` 的某个 option
- `check <ref> --session=NAME [--uncheck]` 复选框勾选/取消
- `scroll <deltaY> --session=NAME [--mode=...]` 滚动（正数向下）

### 导航 + 等待
- `goto <url> --session=NAME` 跳转
- `wait --session=NAME [--ref=eN] [--state=visible|hidden] [--load-state=networkidle] [--timeout=ms]` 等待

### 状态持久化
- `cookie-list --session=NAME [--domain=DOM]` 获取 cookies
- `state-save --session=NAME [--output=PATH]` 保存完整登录态（默认 `<dataDir>/states/<session>.json`）
- `state-load --session=NAME --input=PATH` 恢复

### 全局选项
- `--raw` 输出单行 JSON（便于管道处理）
- `NETA_BROWSER_HUMANIZE_MODE=full|fast|off` 环境变量设定本会话默认 mode

---

## 拟人化档位

| `--mode` | 单命令开销 | 适用场景 |
|---|---|---|
| **full**（默认）| 2-5s | 养号、敏感操作、AI 探索复杂页面 |
| **fast** | 0.3-0.7s | 批量发布、批量评论 |
| **off** | <100ms | 测试、CI |

养号场景每号约 30 操作 × 5s ≈ 2.5min。100 号串行 ≈ 4 小时。批量任务用 `--mode=fast`。

---

## 详细参考文档

- [拟人化档位详解](references/humanization.md)
- [指纹参数（fingerprintSeed 何时用）](references/fingerprint.md)
- [代理配置](references/proxy.md)
- [典型场景示例](references/examples.md)
