# PersonaHub 自动化 API

> 通过 PersonaHub 本地 HTTP API 管理 Profile、代理、指纹及网站凭据，启动浏览器并连接 CDP 完成网页自动化。

Source: https://console.getchrovia.com/zh/docs/automation-api

PersonaHub 自动化 API 用于创建和管理 Profile、配置代理与指纹、管理已保存的网站凭据，以及启动和关闭 Profile 浏览器。Profile 在中文界面中称为「身份」。

网页读取、点击、输入、截图等操作需要在启动浏览器后，通过 CDP 或支持 CDP 的自动化工具完成。

## 1. 接入准备

1. 启动 PersonaHub 桌面客户端并登录账号。
2. 在客户端的自动化设置中启用 API，复制 API Key，确认监听端口。
3. 启动 Profile 前，确认浏览器内核已就绪。
4. 使用期间保持客户端运行、账号已登录，并保持网络可用。

API 只能操作当前登录账号的 Profile，创建数量受账号配额限制。

| 项目 | 默认值 |
| --- | --- |
| HTTP 基础地址 | `http://127.0.0.1:43110` |
| 自动化服务 | 默认关闭 |
| 监听地址 | 默认 `127.0.0.1`；允许远程访问后为 `0.0.0.0` |
| 端口范围 | `1`–`65535`，可在设置中修改 |

远程访问时，将 `127.0.0.1` 替换为运行 PersonaHub 的电脑地址。浏览器、调试端口和返回的文件路径均属于运行客户端的电脑。

## 2. 通用约定

### 2.1 鉴权

除 `GET /health` 外，所有请求需携带：

```http
Authorization: Bearer <API_KEY>
```

有请求体时使用：

```http
Content-Type: application/json
```

API Key 不会替代账号登录或扩大账号权限。

### 2.2 请求和响应

- 请求体为 JSON 对象，不能使用数组、字符串或 `null` 作为顶层值。
- 请求体上限为 256 KiB；超限时连接可能直接关闭。
- 本文接口成功时均返回 `200`，包括创建和删除操作。
- 响应为 JSON，并带有 `Cache-Control: no-store`。
- Profile 和凭据的路径 ID 为 UUID，格式不合法时返回 `404`。
- 将路径中的 `:id`、`:passwordId`、`:otpId`、`:passkeyId` 替换为真实 ID。
- 列表接口不提供分页参数。
- `PATCH` 保留未传字段；嵌套字段的规则见下文。不要用 `null` 代替省略字段。

错误响应：

```json
{
  "error": "错误说明",
  "code": "not_found"
}
```

程序应根据 HTTP 状态码和 `code` 处理错误，不依赖 `error` 文案或语言。

## 3. 快速开始

以下命令使用 Bash/zsh 语法。替换 API Key 和已有 Profile 的 UUID 后执行。

```bash
export PERSONA_API_BASE='http://127.0.0.1:43110'
export PERSONA_API_KEY='<API_KEY>'

curl -sS "$PERSONA_API_BASE/health"

curl -sS "$PERSONA_API_BASE/v1/engine" \
  -H "Authorization: Bearer $PERSONA_API_KEY"

curl -sS "$PERSONA_API_BASE/v1/profiles" \
  -H "Authorization: Bearer $PERSONA_API_KEY"

export PROFILE_ID='<PROFILE_UUID>'

curl -sS -X POST "$PERSONA_API_BASE/v1/profiles/$PROFILE_ID/launch" \
  -H "Authorization: Bearer $PERSONA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"startupUrl":"https://example.com","extraArgs":["--remote-debugging-port=9222"]}'
```

启动成功返回：

```json
{"ok": true}
```

这只表示浏览器已启动，不表示网页、网站登录或 CDP 已就绪。等待调试端口可用后查询：

```bash
curl -sS http://127.0.0.1:9222/json/version
```

使用返回的 `webSocketDebuggerUrl`，或自动化工具支持的 CDP HTTP 地址连接浏览器。`43110` 是自动化 API 端口，`9222` 是示例浏览器调试端口，两者不可混用。多个 Profile 同时启用 CDP 时，应分配不同的调试端口。

关闭本次通过 API 启动的浏览器：

```bash
curl -sS -X POST "$PERSONA_API_BASE/v1/profiles/$PROFILE_ID/close" \
  -H "Authorization: Bearer $PERSONA_API_KEY"
```

## 4. 服务状态与账号权益

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| GET | `/health` | 服务存活检查，无需鉴权 | `{ "ok": true }` |
| GET | `/v1/engine` | 浏览器内核状态 | `{ "ready": true, "version": "..." }` |
| GET | `/v1/account/entitlements` | 当前账号权益 | `{ "entitlements": {...} }` |

`/health` 正常不代表账号已登录或浏览器内核已就绪。`/v1/engine` 的 `version` 是浏览器内核版本，不是客户端版本；无法取得版本时为空字符串。`ready` 不代表某个 Profile 已启动或 CDP 可用。

`entitlements` 字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tier` | string | 套餐标识 |
| `maxProfiles` | number | Profile 数量上限 |
| `usedProfiles` | number | 已使用的 Profile 数量 |
| `renewsAt` | string 或 null | 续期时间 |
| `cancelAt` | string 或 null | 取消时间 |
| `status` | string 或 null | 订阅状态 |

## 5. Profile 管理

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| GET | `/v1/profiles` | 获取 Profile 列表 | `{ "profiles": [...] }` |
| POST | `/v1/profiles` | 创建 Profile | `{ "profile": {...} }` |
| GET | `/v1/profiles/:id` | 获取详情 | `{ "profile": {...} }` |
| PATCH | `/v1/profiles/:id` | 更新 Profile | `{ "profile": {...} }` |
| DELETE | `/v1/profiles/:id` | 删除 Profile 及本机对应数据、缓存 | `{ "ok": true }` |

### 5.1 创建与更新字段

| 字段 | 类型 | 创建必填 | 说明 |
| --- | --- | --- | --- |
| `name` | string | 是 | 名称，去除首尾空白后非空，最长 120 字符 |
| `startupUrl` | string | 否 | 默认启动地址，HTTP/HTTPS URL，最长 2048 字符；空字符串表示未设置 |
| `extraArgs` | string | 否 | 保存的启动参数，参数之间以空白分隔，最长 4096 字符；默认空字符串 |
| `proxy` | object | 否 | Profile 代理配置，见下文 |
| `fingerprint` | object | 否 | 指纹配置，见下文 |
| `proxyIpInfo` | object | 否 | 已知代理出口信息，可用于免去自动检测 |
| `acceptProxyChain` | boolean | 否 | 是否接受客户端已配置的代理链，默认 `true` |
| `appearanceLabel` | string | 否 | 浏览器外观标签 |
| `appearanceBackgroundColor` | string | 否 | 外观背景色，例如 `#2563EB` |
| `appearanceForegroundColor` | string | 否 | 外观前景色，例如 `#FFFFFF` |

最小创建请求：

```json
{"name": "自动化 Profile"}
```

创建时未传的配置使用默认值。更新时，`proxy` 和 `fingerprint` 只覆盖传入的子字段；代理检测可能影响时区，见第 5.4 节。

局部更新示例：

```http
PATCH /v1/profiles/:id
```

```json
{
  "name": "自动化 Profile A",
  "startupUrl": "https://example.com",
  "extraArgs": "--remote-debugging-port=9222"
}
```

这里的 `extraArgs` 是字符串，和启动接口中的字符串数组不同。保存的参数不支持 shell 引号分组；单个参数含空格时，请通过启动接口的 `extraArgs` 数组传入。更新 `startupUrl` 或 `extraArgs` 时传空字符串可以清空已保存的值。

### 5.2 代理配置

通过 Profile 的 `proxy` 字段配置代理。

| 字段 | 类型 | 创建默认值 | 说明 |
| --- | --- | --- | --- |
| `protocol` | string | `socks5` | `http`、`https` 或 `socks5` |
| `host` | string | `""` | 代理主机名或 IP；空字符串表示不配置 Profile 专属代理 |
| `port` | number | `1080` | 整数 `1`–`65535` |
| `username` | string | `""` | 代理认证用户名 |
| `password` | string | `""` | 代理认证密码 |
| `bypassList` | string | `localhost;127.0.0.1` | 代理绕过列表，多个规则以分号分隔 |

```json
{
  "name": "美国 Profile",
  "proxy": {
    "protocol": "socks5",
    "host": "proxy.example.com",
    "port": 1080,
    "username": "<PROXY_USERNAME>",
    "password": "<PROXY_PASSWORD>"
  }
}
```

未配置 Profile 专属代理不等于强制直连；实际网络连接仍可能受到客户端代理链或系统代理设置影响。

### 5.3 指纹配置

| 字段 | 类型 | 创建默认值 | 说明 |
| --- | --- | --- | --- |
| `browserVersion` | string | `""` | 报告版本，最长 32 字符；留空或填 `auto` 时自动选择与内核同大版本的最高可用版本 |
| `hardwareConcurrency` | number | 随机 | CPU 线程数，整数 `1`–`256` |
| `cpuPerformance` | number | 随随机组合 | CPU 性能档位，整数 `0`–`4` |
| `deviceMemory` | number | 随机 | 报告内存，可选 `2`、`4`、`8`、`16` 或 `32` GB，不分配真实内存 |
| `speechVoicesMode` | string | `override` | `none` 不覆盖，`override` 完全覆盖，`append_google` 仅追加 Google 语音 |
| `fontAllowlistOverride` | boolean | `true` | 按当前系统应用预设字体白名单 |
| `disableCanvasNoise` | boolean | `false` | 禁用 Canvas 2D 像素读回和图片导出噪声；默认保持开启，不影响 WebGL、WebGPU 或其他噪声，修改后需重启浏览器 |
| `webrtcIpPolicy` | string | `disable_non_proxied_udp` | WebRTC IP 策略 |
| `timezone` | string | `America/New_York` | IANA 时区；代理检测可能提供默认时区 |
| `acceptLanguages` | string | `en-US,en` | 逗号分隔的语言列表 |

每次创建都会随机选择 CPU 线程数 `8/12/16/20/24/32` 和内存 `16/32 GB`；随机组合中，8 线程的性能档位为 `3`，其余为 `4`。显式字段覆盖对应预设，更新时省略则保留原值，启动时不会重新随机。

`cpuPerformance` 档位：`0 = Unknown`、`1 = Low`、`2 = Mid`、`3 = High`、`4 = Ultra`。

`webrtcIpPolicy` 支持：

- `disable_non_proxied_udp`
- `default_public_interface_only`
- `default_public_and_private_interfaces`
- `default`

允许 UDP 的模式可能暴露直连 IP，而非节点 IP。修改后需关闭并重新启动浏览器。

### 5.4 代理出口信息

配置了代理且未提供出口信息时，API 会自动检测。检测失败返回 `proxy_probe_failed`。

如已有检测结果，可以传入 `proxyIpInfo`：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `ip` | string | 是 | 非空的代理出口 IP |
| `country` | string | 否 | 两字母国家或地区代码，例如 `US` |
| `region`、`city` | string | 否 | 地区、城市 |
| `timezone` | string | 否 | IANA 时区 |
| `latitude`、`longitude` | number | 否 | 经纬度 |
| `asn`、`org` | string | 否 | ASN 和网络组织信息 |

- 本次请求未明确提供非空的 `fingerprint.timezone`，且检测结果或 `proxyIpInfo` 带有时区时，会使用该时区。
- 自动检测不会修改 `acceptLanguages`；如需调整语言，请显式传入。

### 5.5 Profile 响应

列表中的每项包含 `id`、`name`、`startupUrl`、`extraArgs`、`createdAt`、`updatedAt` 和可选的 `lastLaunchedAt`。

详情、创建和更新响应另含：

- `proxy`：代理连接配置，包含认证密码。
- `fingerprint`：指纹配置。
- `acceptProxyChain`：是否接受客户端代理链。
- `appearanceLabel`、`appearanceBackgroundColor`、`appearanceForegroundColor`：外观配置。

## 6. 浏览器启动与关闭

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| POST | `/v1/profiles/:id/launch` | 启动 Profile 浏览器 | `{ "ok": true }` |
| POST | `/v1/profiles/:id/command` | 获取启动命令，不启动浏览器 | `{ "executable": "...", "args": [...] }` |
| POST | `/v1/profiles/:id/close` | 关闭通过 `launch` 启动的浏览器 | `{ "ok": true }` |

### 6.1 启动参数

`launch` 和 `command` 接受相同请求体；不需要临时参数时发送 `{}`。

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `startupUrl` | string | 否 | 本次启动地址；不传或传空字符串时使用 Profile 已保存的地址 |
| `extraArgs` | string[] | 否 | 本次附加参数，追加到已保存的启动参数之后 |

```json
{
  "startupUrl": "https://example.com",
  "extraArgs": ["--remote-debugging-port=9222"]
}
```

启动参数依次包含 Profile 已保存参数、客户端全局启动参数及本次 `extraArgs`。清空 Profile 已保存参数不会清除客户端全局参数。

这些参数仅用于本次调用，不修改 Profile 已保存的值。`extraArgs` 不能覆盖 PersonaHub 管理的数据目录和浏览器生命周期参数。

`launch` 成功只代表浏览器已启动。重复调用可能关闭并重新启动该 Profile，请勿用它轮询运行状态。

### 6.2 获取启动命令

`command` 响应字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `executable` | string | 浏览器可执行文件路径 |
| `args` | string[] | 完整启动参数 |

将返回值原样交给进程启动 API，在运行 PersonaHub 的电脑上启动浏览器，不要拼接成 shell 命令或覆盖数据目录。

如使用 `--remote-debugging-pipe`，应选择 `command`，由调用方创建进程并连接调试管道；`launch` 不返回调试管道。

### 6.3 使用限制

- 使用浏览器期间保持 PersonaHub 桌面客户端运行。
- `close` 不管理通过客户端界面启动的浏览器，也不管理调用方根据 `command` 自行启动的进程。
- 没有可关闭的 API 启动记录时，返回 `404`，错误码为 `not_running`。浏览器已自行退出时，首次 `close` 仍可能成功，因此不能用此接口判断运行状态。
- `close` 成功表示已请求关闭，不保证浏览器已退出。
- 不要对同一 Profile 并发启动多个实例。

## 7. 已保存的网站凭据

### 7.1 网站密码

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| GET | `/v1/profiles/:id/passwords` | 获取密码摘要，不含密码 | `{ "credentials": [...] }` |
| POST | `/v1/profiles/:id/passwords` | 保存网站密码 | `{ "ok": true }` |
| GET | `/v1/profiles/:id/passwords/:passwordId` | 获取单条凭据，包含密码 | `{ "credential": {...} }` |
| PATCH | `/v1/profiles/:id/passwords/:passwordId` | 修改网站密码 | `{ "ok": true }` |
| DELETE | `/v1/profiles/:id/passwords/:passwordId` | 删除网站密码 | `{ "ok": true }` |

保存请求：

```json
{
  "origin": "https://example.com",
  "username": "user@example.com",
  "password": "<WEBSITE_PASSWORD>"
}
```

| 字段 | 规则 |
| --- | --- |
| `origin` | 必填，HTTP/HTTPS URL，最长 2048 字符 |
| `username` | 必填，非空，最长 512 字符 |
| `password` | 必填，非空，最长 2048 字符 |

`PATCH` 至少提供上述字段之一，未传字段保留原值，不允许空字符串。`signon_realm` 自动生成，不接受作为请求字段。

摘要包含 `id`、`origin`、`signon_realm`、`username`；单条详情另含 `password`。保存相同网站登录域和用户名时会更新已有条目。保存接口不返回 ID，需要再次查询列表。

修改会在后续启动时提供给浏览器。删除不会修改网站账号，也不会移除运行中浏览器已加载的凭据；后续浏览器同步可能覆盖修改或重新创建已删除条目。

### 7.2 TOTP 动态验证码

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| GET | `/v1/profiles/:id/otp` | 查询条目元数据 | `{ "entries": [...] }` |
| POST | `/v1/profiles/:id/otp` | 保存或更新 TOTP | `{ "entry": {...} }` |
| DELETE | `/v1/profiles/:id/otp/:otpId` | 移除条目 | `{ "ok": true }` |
| GET | `/v1/profiles/:id/otp/:otpId/code` | 获取当前验证码 | `{ "id": "...", "code": "...", "expiresAt": "..." }` |

保存请求字段：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `secret` | string | 是 | Base32 密钥，去除空白并转大写后最长 256 字符；不是 `otpauth://` URL |
| `label` | string | 否 | 最长 120 字符；省略时根据发行方和账号生成，均为空时使用 `Authenticator` |
| `issuer` | string | 否 | 发行方，最长 120 字符，默认空字符串 |
| `accountName` | string | 否 | 账号，最长 180 字符，默认空字符串 |
| `algorithm` | string | 否 | `SHA1`、`SHA256` 或 `SHA512`，默认 `SHA1` |
| `digits` | number | 否 | `6` 或 `8`，默认 `6` |
| `period` | number | 否 | 周期秒数，整数 `15`–`120`，默认 `30` |

列表和保存响应包含 `id`、`label`、`issuer`、`accountName`、`algorithm`、`digits`、`period`，不返回密钥。

同一 Profile 下相同的标准化密钥会更新或恢复已有条目；不同密钥创建新条目。再次保存时，省略的元数据和设置采用默认值，不保留旧值。

验证码响应示例：

```json
{
  "id": "<OTP_UUID>",
  "code": "012345",
  "expiresAt": "2026-09-17T08:00:30.000Z"
}
```

`code` 为字符串，应保留前导零。验证码按运行 PersonaHub 的电脑时钟生成；`expiresAt` 为 UTC ISO 时间。接口不会自动提交验证码；保存或删除条目也不会开启或关闭网站上的两步验证。

### 7.3 Passkey

| 方法 | 路径 | 说明 | 成功响应 |
| --- | --- | --- | --- |
| GET | `/v1/profiles/:id/passkeys` | 获取 Passkey 元数据 | `{ "entries": [...] }` |
| DELETE | `/v1/profiles/:id/passkeys/:passkeyId` | 移除已保存条目 | `{ "ok": true }` |

每项包含 `id`、`rpId`、`userName`、`userDisplayName`，不返回私钥。自动化 API 不提供创建或导入 Passkey 的接口。

删除影响后续启动，不会在网站注销凭据，也不会移除运行中浏览器已加载的副本。在浏览器中使用 Passkey 的套餐要求见 [Passkey 使用指南](https://console.getchrovia.com/zh/docs/passkeys)。

## 8. 常见错误

| HTTP 状态 | `code` | 含义 |
| --- | --- | --- |
| 400 | `body_invalid` | 请求体不是合法 JSON |
| 400 | `body_not_object` | 请求体顶层不是对象 |
| 400 | `input_invalid` | 指纹、网站密码或 TOTP 字段无效 |
| 400 | `profile_name_required` / `profile_name_too_long` | 名称为空或过长 |
| 400 | `startup_url_invalid` / `startup_url_too_long` | 启动地址类型、格式或长度不合法 |
| 400 | `launch_args_too_long` | 保存的启动参数过长 |
| 400 | `extra_args_invalid` | 临时参数不是字符串数组，或包含禁止覆盖的参数 |
| 400 | `proxy_invalid` | 代理配置不是对象 |
| 400 | `protocol_invalid` | 不支持的代理协议 |
| 400 | `proxy_port_invalid` | 代理端口不合法 |
| 400 | `proxy_ip_info_invalid` | 代理出口信息不合法或缺少 IP |
| 400 | `proxy_probe_failed` | 代理检测失败 |
| 400 | `password_account_taken` | 修改后的网站登录域和用户名与其他凭据冲突 |
| 400 | `otp_code_failed` | TOTP 验证码生成失败 |
| 401 | `unauthorized` | API Key 缺失或不正确 |
| 401 | `not_authenticated` | 客户端未登录或登录失效 |
| 403 | `profile_quota_exceeded` | Profile 数量达到账号上限 |
| 404 | `not_found` | 资源或路由不存在，或路径 ID 格式不合法 |
| 404 | `not_running` | 没有可关闭的 API 启动记录 |
| 405 | `method_not_allowed` | 接口不支持该 HTTP 方法 |
| 413 | `body_too_large` | 请求体超过限制；连接可能直接关闭 |
| 500 | `automation_api_error` | 请求处理失败 |
| 503 | `console_session_not_ready` | 桌面客户端会话尚未准备好 |
| 503 | `browser_engine_not_ready` | 浏览器内核尚未就绪 |

## 相关文档

- [创建 Profile](https://console.getchrovia.com/zh/docs/create-profile)
- [启动 Profile 浏览器](https://console.getchrovia.com/zh/docs/launch-profile)
- [启用 CDP](https://console.getchrovia.com/zh/docs/enable-cdp)
- [网站密码管理](https://console.getchrovia.com/zh/docs/password-management)
- [TOTP 使用指南](https://console.getchrovia.com/zh/docs/totp)
- [Passkey 使用指南](https://console.getchrovia.com/zh/docs/passkeys)
