EasyBR 桌面客户端在本机提供 Local API。程序可以通过它查询和管理浏览器环境,启动或关闭指定环境,并取得 Chromium DevTools Protocol(CDP)调试地址,再接入 Selenium、Puppeteer、Playwright 等自动化框架。
让 AI 执行从安装到网页任务的完整流程,见《EasyBR AI 操作总指南:功能使用与问题排查》。Mac 安装和登录细节见 Mac 用户教程。本文用于已启动客户端的 Local API 开发和排障。
本文档描述的是桌面客户端本机接口,默认地址为
http://127.0.0.1:3001。它不是 EasyBR 云端业务 API,也不应直接暴露到公网。
一、使用前准备
- 启动 EasyBR 桌面客户端并完成登录。
- 在客户端“系统设置”中确认 Local API 已正常启动。
- 默认端口为
3001;如果客户端显示了其他端口,以客户端实际显示为准。 - 环境数量、每日打开次数等仍受当前账号套餐额度限制。
- 调用环境接口时,不需要在请求中填写网站登录账号和密码;客户端会使用当前登录会话访问云端数据。
快速检查:
curl http://127.0.0.1:3001/auto/status
旧版兼容返回:
{
"code": 0,
"msg": "success"
}
Mac 1.7.13 起仍保留顶层 code: 0、msg: "success",并增加 data,报告正在运行的客户端版本、登录状态和当前账号。详细字段见下文“检查 API、版本与登录状态”。只看顶层成功码不能判断是否已登录。
二、通用约定
2.1 基础地址和请求格式
| 项目 | 说明 |
|---|---|
| 基础地址 | http://127.0.0.1:3001 |
| GET 参数 | URL Query String |
| POST 参数 | JSON 请求体 |
| POST 请求头 | Content-Type: application/json |
| 字符编码 | UTF-8 |
| 超时建议 | 普通接口 15 秒;启动环境 60 秒以上 |
参数并非全部都是字符串:开关字段推荐使用 JSON Boolean,分页字段使用 Number,枚举字段和环境 ID 使用 String。具体以各接口说明为准。
2.2 返回值和错误处理
多数接口返回以下结构:
{
"code": 0,
"msg": "success",
"data": {}
}
code = 0:业务成功。code != 0:业务失败,应读取msg或desc。- Local API 的部分业务失败仍可能返回 HTTP 200,因此不要只判断 HTTP 状态码。
- 网络异常、客户端未启动或端口错误时,请求会直接连接失败。
- 不建议高并发重复启动同一环境。调用方应为同一个
browerid加锁,并对查询接口做适当限速。
2.3 历史拼写兼容
现有接口和字段长期使用 Brower 拼写,例如:
/auto/openBrower/auto/closeBrower/auto/getBrowerListbroweridbrowername
这些名称属于兼容契约。调用时必须保留,不能自行改成 Browser、browserId 或 browserName。
2.4 接口目录
| Method | Path | 用途 |
|---|---|---|
| GET | /auto/status |
检查 Local API;Mac 1.7.13 起同时返回版本与登录状态 |
| GET | /auto/getBrowerList |
分页查询环境列表 |
| GET | /sql3db/sql3GetBrUn |
按 ID 获取完整环境配置 |
| GET | /auto/openedList |
查询当前已打开环境 |
| POST | /auto/openBrower |
启动环境并返回 CDP 地址 |
| POST | /auto/closeBrower |
关闭环境 |
| POST | /auto/addBrowers |
创建或修改环境 |
| POST | /auto/delBrower |
删除环境及本地环境目录 |
| POST | /auto/clearTempFiles |
清理 Selenium/WebDriver 临时文件 |
| POST | /auto/syncCloudProfile |
将指定环境同步至云端 |
| POST | /auto/syncCloudProfiles |
批量将指定环境同步至云端 |
| POST | /auto/restoreCloudProfile |
用云端资料恢复指定本地环境,需先关闭 |
| POST | /auto/restoreCloudProfiles |
批量恢复指定本地环境,需先关闭 |
| GET | /auto/getRandAgent |
生成与系统、内核匹配的 User-Agent |
| GET | /auto/getRandWebGL |
生成与系统匹配的 WebGL 参数 |
| GET | /user/checkProxyTest |
检测 HTTP、HTTPS 或 Socks5 代理出口 |
三、环境查询接口
3.1 检查 API、版本与登录状态
GET /auto/status
curl http://127.0.0.1:3001/auto/status
{
"code": 0,
"msg": "success",
"data": {
"appVersion": "1.7.13",
"loginStatus": "logged_in",
"loggedIn": true,
"username": "用户自己的账号"
}
}
上例为 Mac 1.7.13 起可用的已登录返回。appVersion 是本机当前运行的客户端版本;username 是当前用户自己的账号标识,示例文字不是实际账号。
data 字段 |
类型 | 说明 |
|---|---|---|
appVersion |
String | 正在运行的客户端版本 |
loginStatus |
String | logged_in、logged_out 或 unknown |
loggedIn |
Boolean/null | 与登录状态对应的 true、false 或 null |
username |
String/null | 已确认登录时为当前账号;未登录或无法确认时为 null |
登录状态有三种:
loginStatus |
loggedIn |
username |
调用方下一步 |
|---|---|---|---|
logged_in |
true |
当前账号 | 核对目标账号后继续环境任务 |
logged_out |
false |
null |
在现有客户端完成登录,再重新查询 |
unknown |
null |
null |
等待或查看客户端界面,不能按已登录继续 |
已登录状态由管理端当前实际界面与后台用户信息共同确认。未登录或不确定时不返回上次登录的旧用户名。登录状态探测的总时限为 4 秒,时限内仍无法确认时按 unknown 处理;调用方不要把请求超时、旧缓存或顶层成功码当作登录成功。
这个接口只供运行 EasyBR 的本机访问,不是公网查询账号的接口。调用时不需要提供密码,返回内容不包含 Token、Cookie 或密码。不要把本机地址换成官网域名,也不要将接口暴露到公网。
旧客户端可能只返回顶层 code 和 msg,没有 data。此时只能确认 Local API 可用,登录账号仍须在客户端界面核对。客户端升级增加字段后,调用方应继续兼容原有顶层字段,并忽略不认识的新字段。
3.2 获取环境列表
GET /auto/getBrowerList
Query 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
page |
Number | 是 | 页码,从 1 开始 |
limit |
Number | 是 | 每页数量 |
browername |
String | 否 | 按环境名称筛选,空字符串表示不筛选 |
groupname |
String | 否 | 按分组名称筛选 |
请求示例:
curl "http://127.0.0.1:3001/auto/getBrowerList?page=1&limit=30&browername="
返回示例:
{
"code": 0,
"data": [
{
"browerid": "68fdbf585aedba39cf6cf07b",
"browername": "咸鱼店铺-01",
"groupname": "默认分组",
"kernel": "146",
"proxyType": "2",
"proxyProtocol": "socks5",
"createdate": 1778140800000
}
],
"count": 1,
"records": 0
}
count 是匹配记录数。使用 data[].browerid 调用打开、关闭、修改或删除接口。
3.3 按 ID 获取完整环境配置
GET /sql3db/sql3GetBrUn
该接口会合并云端环境配置与本机保存的 Cookie、账号备注等本地数据。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
browerid |
String | 是 | 环境 ID |
curl "http://127.0.0.1:3001/sql3db/sql3GetBrUn?browerid=68fdbf585aedba39cf6cf07b"
{
"code": 0,
"data": {
"browerid": "68fdbf585aedba39cf6cf07b",
"browername": "咸鱼店铺-01",
"kernel": "146",
"lastSession": "true",
"cloudSync": false
}
}
3.4 获取当前已打开环境
GET /auto/openedList
curl http://127.0.0.1:3001/auto/openedList
{
"code": 0,
"msg": "success",
"data": [
{
"browerid": "68fdbf585aedba39cf6cf07b",
"browername": "咸鱼店铺-01",
"isopen": true
}
]
}
四、启动与关闭接口
4.1 启动环境
POST /auto/openBrower
curl -X POST http://127.0.0.1:3001/auto/openBrower \
-H "Content-Type: application/json" \
-d '{"browerid":"68fdbf585aedba39cf6cf07b"}'
首次启动或内核尚未准备完成时耗时会更长,建议超时设置为 60 秒以上。
成功返回:
{
"code": 0,
"status": 0,
"data": {
"ws": "ws://127.0.0.1:51760/devtools/browser/31de2812-6075-48f3-8070-75873ce1171e",
"http": "http://127.0.0.1:51760",
"driverPath": "/path/to/chromedriver",
"apiurl": "http://127.0.0.1:51760/json/version",
"datadir": "/Users/example/ebdata/UserData/u68fdbf585aedba39cf6cf07b",
"browerid": "68fdbf585aedba39cf6cf07b"
}
}
| 字段 | 说明 |
|---|---|
data.http |
Chromium 调试 HTTP 地址,可读取 /json/version、/json/list |
data.ws |
Browser 级 CDP WebSocket 地址,可供 Puppeteer/Playwright 连接 |
data.driverPath |
当前驱动路径;仅在需要原生 Selenium Driver 时使用 |
data.datadir |
当前环境实际 User Data 目录 |
status = 0 |
本次新启动 |
status = 1 |
环境原本已经打开,返回现有调试地址 |
不要把示例端口写死。每次启动都应使用本次响应中的 http 或 ws。
4.2 关闭环境
POST /auto/closeBrower
curl -X POST http://127.0.0.1:3001/auto/closeBrower \
-H "Content-Type: application/json" \
-d '{"browerid":"68fdbf585aedba39cf6cf07b"}'
{
"code": 0,
"msg": "success"
}
启用环境云存储时,关闭过程可能包含环境数据上传。收到成功响应后,再进行后续的换机恢复或重复打开操作。
五、创建、修改和删除环境
5.1 创建环境
POST /auto/addBrowers
创建时不要传 browerid,服务端会生成 24 位环境 ID。最小可用示例:
curl -X POST http://127.0.0.1:3001/auto/addBrowers \
-H "Content-Type: application/json" \
-d '{
"browername": "API测试环境",
"openmodel": "2",
"kernel": "146",
"osName": "win11",
"siteurl": "https://www.example.com",
"proxyType": "1",
"lastSession": true,
"cloudSync": false
}'
成功返回的 data.browerid 是后续操作所需的环境 ID:
{
"code": 0,
"data": {
"browerid": "68fdbf585aedba39cf6cf07b"
}
}
5.2 修改环境
修改仍使用 POST /auto/addBrowers,但请求体必须包含已有 browerid。
修改接口按完整环境对象保存。为避免未传字段被清空,推荐先调用
/sql3db/sql3GetBrUn获取完整配置,修改目标字段后,再把完整对象提交到/auto/addBrowers。
const base = 'http://127.0.0.1:3001';
const browerid = '68fdbf585aedba39cf6cf07b';
const current = await fetch(
`${base}/sql3db/sql3GetBrUn?browerid=${encodeURIComponent(browerid)}`
).then((res) => res.json());
if (current.code !== 0) throw new Error(current.msg || current.desc || '读取环境失败');
const updated = {
...current.data,
browername: '咸鱼店铺-已更新',
kernel: '146'
};
const result = await fetch(`${base}/auto/addBrowers`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updated)
}).then((res) => res.json());
if (result.code !== 0) throw new Error(result.msg || result.desc || '修改环境失败');
5.3 环境字段说明
基本信息
| 字段 | 推荐类型 | 说明 |
|---|---|---|
browerid |
String | 创建时不传;修改时必传 |
browername |
String | 环境名称,创建时必填 |
GroupID |
String/Number | 分组 ID |
groupname |
String | 分组名称 |
siteurl |
String | 启动时打开的网址 |
crxplug |
String | 扩展列表,多个值使用客户端现有格式分隔 |
openmodel |
String | 1 临时/无痕环境,2 固定环境 |
desc |
String | 环境备注 |
startargs |
String | 额外启动参数,多个参数使用英文或中文逗号分隔 |
内核、会话和云存储
| 字段 | 推荐类型 | 说明 |
|---|---|---|
kernel |
String | 内核主版本,当前可用值为 119、146 |
osName |
String | 系统标识,例如 win11、Windows、MacOS、Linux |
agent |
String | User-Agent;留空时可先调用随机 UA 接口生成 |
lastSession |
Boolean | 是否恢复上次打开的页签和会话 |
cloudSync |
Boolean | 是否允许该环境参与云存储;默认 false,还受账号总开关控制 |
代理设置
| 字段 | 推荐类型 | 说明 |
|---|---|---|
proxyType |
String | 1 不使用代理;2 自定义代理;3 API 提取代理 |
proxyProtocol |
String | http、https 或 socks5 |
prHost |
String | 代理主机 |
prPort |
String | 代理端口 |
prAccount |
String | 代理账号,可为空 |
prPass |
String | 代理密码,可为空 |
prlink |
String | proxyType=3 时的代理提取链接 |
prFreshUrl |
String | 历史兼容字段;当前启动流程未直接读取 |
prGetType |
String | 历史兼容字段;当前启动流程未按该字段分支 |
当前客户端在 proxyType=3 时会在启动环境时请求 prlink,并解析 host:port 或 host:port:account:password。提取接口返回格式不符合要求时,环境可能以无代理状态启动。
自定义 Socks5 示例:
{
"proxyType": "2",
"proxyProtocol": "socks5",
"prHost": "gate.example.com",
"prPort": "9102",
"prAccount": "proxy-user",
"prPass": "proxy-password"
}
Cookie 和本地账号信息
| 字段 | 推荐类型 | 说明 |
|---|---|---|
cookie |
String | Cookie JSON 字符串;不是直接传 JSON 数组 |
initCookie |
Boolean | 启动时是否写入 cookie |
getCookie |
Boolean | 是否由客户端回收 Cookie;不理解该行为时保持 false |
webuser |
String | 本地保存的网站账号备注 |
webpass |
String | 本地保存的网站密码备注 |
storestr |
String | 其他本地存储字段 |
Cookie 字段示例:
{
"cookie": "[{\"name\":\"sessionid\",\"value\":\"example\",\"domain\":\".example.com\",\"path\":\"/\"}]",
"initCookie": true,
"getCookie": false
}
指纹和浏览器能力
下表同时包含当前数据模型字段和历史兼容字段。“直接生效”表示当前桌面启动器会读取并映射该字段;“兼容保存”表示字段会保存到环境数据,但当前启动器没有独立映射逻辑,不能仅凭字段存在就认定对应指纹已经生效。
| 字段 | 推荐类型 | 当前客户端 | 说明 |
|---|---|---|---|
timezone |
Boolean | 直接生效 | 根据代理出口设置时区、经纬度,并同步 WebRTC 公网 IP |
lag |
Boolean | 直接生效 | 根据代理出口自动选择语言 |
lagStr |
String | 直接生效 | 自定义浏览器语言 |
canvas |
String | 直接生效 | 值为 1 时写入 Canvas 噪声配置 |
font |
String | 直接生效 | 值为 1 时写入字体噪声配置 |
webGLFac |
String | 直接生效 | WebGL 厂商;字段名大小写必须保持当前写法 |
webglRend |
String | 直接生效 | WebGL Renderer |
audiocontext |
String | 直接生效 | 值为 1 时写入 WebAudio 噪声配置 |
clientrects |
String | 直接生效 | 值为 1 时写入 ClientRects 噪声配置 |
CPU |
String | 直接生效 | navigator.hardwareConcurrency |
memory |
String | 直接生效 | navigator.deviceMemory |
SSL |
String | 直接生效 | 值为 1 时写入 SSL 指纹配置;字段名必须使用大写 SSL |
screen |
String | 兼容保存 | 分辨率模式字段 |
screendata |
String | 兼容保存 | 自定义分辨率,例如 1920x1080 |
webrtc |
String | 兼容保存 | WebRTC 模式字段;当前自动替换主要由 timezone 代理定位流程完成 |
local |
String | 兼容保存 | 地理位置模式字段 |
webgl |
String | 兼容保存 | WebGL 图像模式开关;实际厂商和 Renderer 读取上方两个字段 |
audiodevice |
String | 兼容保存 | 音频设备模式字段 |
deviceName |
String | 兼容保存 | 设备名称模式 |
deviceNameStr |
String | 兼容保存 | 自定义设备名称 |
macAdd |
String | 兼容保存 | MAC 地址模式 |
macAddStr |
String | 兼容保存 | 自定义 MAC 地址 |
track |
Boolean | 兼容保存 | Do Not Track 字段 |
portScan |
String | 兼容保存 | 端口扫描保护模式 |
scanList |
String | 兼容保存 | 端口扫描相关列表 |
gpuget |
Boolean | 兼容保存 | 硬件加速字段 |
speechvoices |
String | 兼容保存 | Speech Voices 字段 |
未指定的随机指纹细节会由客户端生成 printconfig。除非需要复现完全相同的底层噪声值,不建议自行拼接 printconfig。
5.4 删除环境
POST /auto/delBrower
curl -X POST http://127.0.0.1:3001/auto/delBrower \
-H "Content-Type: application/json" \
-d '{"browerid":"68fdbf585aedba39cf6cf07b"}'
该操作会删除云端环境记录、本机环境数据目录和本地缓存记录。删除前应先关闭环境,并自行确认不再需要该环境数据。
六、辅助接口
6.1 清理自动化临时文件
POST /auto/clearTempFiles
curl -X POST http://127.0.0.1:3001/auto/clearTempFiles \
-H "Content-Type: application/json" \
-d '{}'
{
"code": 0,
"msg": "success",
"data": {
"num": 3,
"file": "/tmp"
}
}
该接口会在系统临时目录中删除名称包含 selenium、webdriver 或 scoped_dir 的文件和目录。不要在其他自动化任务正在运行时调用。
6.2 随机生成 User-Agent
GET /auto/getRandAgent
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
osName |
String | 否 | Windows、MacOS、Linux、Android、iOS;为空默认 Windows |
kernel |
String | 否 | 内核主版本,例如 119 或 146 |
brName |
String | 否 | 浏览器名称筛选 |
curl "http://127.0.0.1:3001/auto/getRandAgent?osName=Windows&kernel=146"
返回值是纯文本 User-Agent,不是 {code, data} JSON:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36
6.3 随机生成 WebGL 参数
GET /auto/getRandWebGL
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
osName |
String | 否 | Windows、MacOS、Linux、Android、iOS;为空默认 Windows |
curl "http://127.0.0.1:3001/auto/getRandWebGL?osName=Windows"
{
"a": "PC",
"b": "Win32",
"c": "Google Inc. (NVIDIA)",
"d": "ANGLE (NVIDIA, NVIDIA GeForce GTX, Direct3D11)"
}
创建环境时使用 c 作为 webGLFac,使用 d 作为 webglRend。
6.4 检测代理出口
GET /user/checkProxyTest
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
proxyProtocol |
String | 是 | http、https 或 socks5 |
prHost |
String | 是 | 代理主机 |
prPort |
Number/String | 是 | 代理端口,范围 1-65535 |
prAccount |
String | 否 | 代理账号 |
prPass |
String | 否 | 代理密码 |
geotype |
String | 否 | 默认 ipinfo;用于选择出口信息源 |
curl --get http://127.0.0.1:3001/user/checkProxyTest \
--data-urlencode "proxyProtocol=socks5" \
--data-urlencode "prHost=gate.example.com" \
--data-urlencode "prPort=9102" \
--data-urlencode "prAccount=proxy-user" \
--data-urlencode "prPass=proxy-password"
成功时返回纯文本,例如:
ip: 203.0.113.10 US Los Angeles
失败时返回:
检测失败,直接打开浏览器也可以检测
代理检测只说明该代理能否完成本次出口查询。实际网页速度还会受代理线路、DNS、目标站点、并发限制和会话节点影响。
6.5 环境云端同步与恢复
这四个接口使用当前客户端会话,只操作请求中明确指定的环境 ID。同步及恢复均要求固定环境(openmodel: "2")且已开启该环境的 cloudSync。不要为了调用接口自动开启其他环境的云端存储。
| Method | Path | JSON 参数 | 行为与前提 |
|---|---|---|---|
| POST | /auto/syncCloudProfile |
{"browerid":"example-env-a"} |
将本机指定环境资料上传;本机环境目录必须存在 |
| POST | /auto/syncCloudProfiles |
{"browerids":["example-env-a","example-env-b"]} |
按去重后的 ID 顺序逐个同步,分别记录成功和失败 |
| POST | /auto/restoreCloudProfile |
{"browerid":"example-env-a"} |
指定环境必须关闭;用可用云端快照恢复本地资料 |
| POST | /auto/restoreCloudProfiles |
{"browerids":["example-env-a","example-env-b"]} |
逐个恢复,每个目标都必须满足固定、云端存储开启和关闭状态 |
ID 均为虚构示例。单个请求的 browerid 不能为空;批量 browerids 必须是非空数组,空白 ID 会被剔除,重复 ID 会去重。批量请求不自动扩大到未指定的环境。
恢复会以云端快照覆盖指定环境中的相应本地资料。 执行前核对用户要求的恢复方向、准确 ID 和目标目录,备份本地数据,确认环境已经正常关闭且云端资料可用。不要将恢复用作一般连接排障,也不要自动对其他环境调用。没有可恢复云端数据或环境仍运行时会失败。
单个接口成功返回 code: 0、msg: "success" 及 data;失败返回 code: -1 和 msg。data 包含云端元数据,具体元数据字段随存储通道而异,调用方应允许额外字段:
| 单个接口 | 除元数据外的结果字段 |
|---|---|
| 同步 | browerid、running、chromiumPid,用于描述目标与客户端识别的运行状态 |
| 恢复 | browerid、targetDir、restoredPaths,描述恢复目标和恢复路径 |
批量接口即使有个别失败,也可能返回顶层 code: 0。以下为虚构的部分失败示例,results 在此只展示部分字段:
{
"code": 0,
"msg": "success",
"data": {
"total": 2,
"successCount": 1,
"failureCount": 1,
"results": [{ "browerid": "example-env-a" }],
"failures": [{ "browerid": "example-env-b", "reason": "请先开启该环境的云端存储" }]
}
}
必须检查 data.successCount、failureCount、results 和 failures,不能仅凭 HTTP 200 或顶层 code: 0 宣布全部成功。批量恢复结果另有 totalSize,为成功结果 size 的合计。请求超时后先检查目标状态和已产生的结果,不盲目重复上传或覆盖恢复。
本节依据客户端现有源码核对补充,本轮没有执行云端上传或恢复写操作,不将云端同步功能列为本轮实测通过项。
七、自动化框架接入
7.1 Node.js:完整打开流程
const API_BASE = 'http://127.0.0.1:3001';
async function request(path, options = {}) {
const response = await fetch(`${API_BASE}${path}`, {
headers: { 'Content-Type': 'application/json', ...(options.headers || {}) },
signal: AbortSignal.timeout(60_000),
...options
});
const result = await response.json();
if (!response.ok || (result.code !== undefined && result.code !== 0)) {
throw new Error(result.msg || result.desc || `HTTP ${response.status}`);
}
return result;
}
async function openByName(browername) {
const query = new URLSearchParams({ page: '1', limit: '30', browername });
const list = await request(`/auto/getBrowerList?${query}`);
const environment = list.data?.find((item) => item.browername === browername);
if (!environment) throw new Error(`未找到环境:${browername}`);
const opened = await request('/auto/openBrower', {
method: 'POST',
body: JSON.stringify({ browerid: environment.browerid })
});
return opened.data;
}
openByName('API测试环境').then(console.log).catch(console.error);
7.2 Playwright
const { chromium } = require('playwright');
const opened = await openByName('API测试环境');
const browser = await chromium.connectOverCDP(opened.http);
const context = browser.contexts()[0];
const pages = context.pages();
const page = pages[0] || await context.newPage();
await page.goto('https://www.example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
// 不要直接结束 Chromium 进程;通过 Local API 关闭,确保正常执行环境收尾和云同步。
await request('/auto/closeBrower', {
method: 'POST',
body: JSON.stringify({ browerid: opened.browerid })
});
7.3 Puppeteer
const puppeteer = require('puppeteer-core');
const opened = await openByName('API测试环境');
const browser = await puppeteer.connect({
browserWSEndpoint: opened.ws,
defaultViewport: null
});
const pages = await browser.pages();
const page = pages[0] || await browser.newPage();
await page.goto('https://www.example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());
await browser.disconnect();
await request('/auto/closeBrower', {
method: 'POST',
body: JSON.stringify({ browerid: opened.browerid })
});
7.4 Selenium
推荐使用 /auto/openBrower 返回的 http 提取调试端口,然后附加到已启动的 Chromium。不要让 Selenium 再启动一个新的普通 Chrome。
Python 示例:
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
API_BASE = "http://127.0.0.1:3001"
BROWER_ID = "68fdbf585aedba39cf6cf07b"
result = requests.post(
f"{API_BASE}/auto/openBrower",
json={"browerid": BROWER_ID},
timeout=60,
).json()
if result.get("code") != 0:
raise RuntimeError(result.get("msg") or result.get("desc") or str(result))
debugger_address = result["data"]["http"].replace("http://", "")
options = Options()
options.add_experimental_option("debuggerAddress", debugger_address)
driver = webdriver.Chrome(options=options)
driver.get("https://www.example.com")
print(driver.title)
# 通过 Local API 关闭,确保正常执行环境收尾和云同步。
requests.post(
f"{API_BASE}/auto/closeBrower",
json={"browerid": BROWER_ID},
timeout=60,
).raise_for_status()
Selenium Driver 的主版本必须与环境内核匹配。119 内核使用 119 对应驱动,146 内核使用 146 对应驱动;如无必要,优先使用 Playwright/Puppeteer 的 CDP 连接方式。
八、常见问题
8.1 无法连接 127.0.0.1:3001
- 确认 EasyBR 桌面客户端已经启动。
- 检查系统设置里显示的 Local API 端口。
- 检查端口是否被其他进程占用。
- Local API 只应在本机访问,不要把
127.0.0.1替换成官网域名。
8.2 打开环境返回失败
- 确认
browerid属于当前登录账号或已分配给当前子账号。 - 确认账号环境额度、每日打开次数没有用完。
- 确认所选 119/146 内核已经安装完成。
- 环境使用代理时,先检查代理主机、端口、协议和账号密码。
8.3 已经打开的环境重复调用
接口会返回现有环境的调试地址,并通过 status = 1 表示环境原本已经打开。调用方应复用该地址,不要并发重复启动。
8.4 Playwright 或 Puppeteer 连接失败
- 必须使用本次
/auto/openBrower返回的http或ws。 - 先访问
${http}/json/version,确认调试端口仍可用。 - 环境关闭后,旧的 CDP 地址立即失效。
- 使用
puppeteer-core时不要指定另一个 Chrome 可执行文件。
8.5 路径中为什么可能带 u
历史版本的环境目录可能是 UserData/u{browerid},新旧版本在备份还原时会兼容匹配。API 调用始终使用不带 u 的原始 browerid,不要把本地目录名前缀拼进环境 ID。
8.6 status 成功但登录状态不是 logged_in
- 顶层
code = 0代表状态请求成功,不代表已经登录。 - Mac 1.7.13 起,
logged_out表示需要在客户端登录;unknown表示当前无法确认,先查看界面或等待后再查询。 - 未登录或不确定时
username为null,不要用之前缓存的用户名补齐。 - 旧客户端没有
data时,以客户端实际登录界面和账号为准。
九、接口边界与版本兼容
- 本文只把上方接口作为对外自动化文档维护。
/sql3db/sql3AddBr、/sql3db/sql3GetBr、/sql3db/sql3DelBr属于客户端本地缓存维护接口,不建议业务脚本直接调用。/auto/savecrx、/auto/getAllCrx、/auto/getCRXFiles、/auto/getExtInfo、/auto/chromeStoreDownload、/auto/downloadcrx、/auto/uploadcrx、/auto/sql3DelCrx属于扩展管理内部接口,参数和返回值可能随客户端升级调整,不作为稳定公开契约。- EasyBR 扩展与桌面客户端之间的内部授权和握手接口不属于用户自动化 API,不作为公开调用入口。
/user/getProxyTest是代理提取链接的内部预览接口,不作为稳定公开契约;代理连通性请使用/user/checkProxyTest。- 旧接口名继续保留;不要擅自改成
/api/v2、/local-api/v2或更正Brower拼写。 - 客户端升级后如果返回字段增加,调用方应忽略不认识的字段,不应因新增字段报错。
自动化 Demo:
文档最后核对日期:2026-10-21。
先试 EasyBR,再决定是否扩团队或做更深的定制项目
标准版适合先验证多账号环境、代理和数据迁移;如果你需要更深的业务能力,我们也支持浏览器外包、Chromium 定制、贴牌浏览器与 Android 指纹浏览器开发。