PersonaHub 自动化 API
通过 PersonaHub 本地 HTTP API 管理 Profile、代理、指纹及网站凭据,启动浏览器并连接 CDP 完成网页自动化。
PersonaHub 自动化 API 用于创建和管理 Profile、配置代理与指纹、管理已保存的网站凭据,以及启动和关闭 Profile 浏览器。Profile 在中文界面中称为「身份」。
网页读取、点击、输入、截图等操作需要在启动浏览器后,通过 CDP 或支持 CDP 的自动化工具完成。
1. 接入准备
- 启动 PersonaHub 桌面客户端并登录账号。
- 在客户端的自动化设置中启用 API,复制 API Key,确认监听端口。
- 启动 Profile 前,确认浏览器内核已就绪。
- 使用期间保持客户端运行、账号已登录,并保持网络可用。
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 外,所有请求需携带:
Authorization: Bearer <API_KEY>有请求体时使用:
Content-Type: application/jsonAPI Key 不会替代账号登录或扩大账号权限。
2.2 请求和响应
- 请求体为 JSON 对象,不能使用数组、字符串或
null作为顶层值。 - 请求体上限为 256 KiB;超限时连接可能直接关闭。
- 本文接口成功时均返回
200,包括创建和删除操作。 - 响应为 JSON,并带有
Cache-Control: no-store。 - Profile 和凭据的路径 ID 为 UUID,格式不合法时返回
404。 - 将路径中的
:id、:passwordId、:otpId、:passkeyId替换为真实 ID。 - 列表接口不提供分页参数。
PATCH保留未传字段;嵌套字段的规则见下文。不要用null代替省略字段。
错误响应:
{
"error": "错误说明",
"code": "not_found"
}程序应根据 HTTP 状态码和 code 处理错误,不依赖 error 文案或语言。
3. 快速开始
以下命令使用 Bash/zsh 语法。替换 API Key 和已有 Profile 的 UUID 后执行。
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"]}'启动成功返回:
{"ok": true}这只表示浏览器已启动,不表示网页、网站登录或 CDP 已就绪。等待调试端口可用后查询:
curl -sS http://127.0.0.1:9222/json/version使用返回的 webSocketDebuggerUrl,或自动化工具支持的 CDP HTTP 地址连接浏览器。43110 是自动化 API 端口,9222 是示例浏览器调试端口,两者不可混用。多个 Profile 同时启用 CDP 时,应分配不同的调试端口。
关闭本次通过 API 启动的浏览器:
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 |
最小创建请求:
{"name": "自动化 Profile"}创建时未传的配置使用默认值。更新时,proxy 和 fingerprint 只覆盖传入的子字段;代理检测可能影响时区,见第 5.4 节。
局部更新示例:
PATCH /v1/profiles/:id{
"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 | 代理绕过列表,多个规则以分号分隔 |
{
"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_udpdefault_public_interface_onlydefault_public_and_private_interfacesdefault
允许 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[] | 否 | 本次附加参数,追加到已保存的启动参数之后 |
{
"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 } |
保存请求:
{
"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 下相同的标准化密钥会更新或恢复已有条目;不同密钥创建新条目。再次保存时,省略的元数据和设置采用默认值,不保留旧值。
验证码响应示例:
{
"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 使用指南。
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 | 浏览器内核尚未就绪 |