EasyBR 桌面客户端在本机提供 Local API。程序可以通过它查询和管理浏览器环境,启动或关闭指定环境,并取得 Chromium DevTools Protocol(CDP)调试地址,再接入 Selenium、Puppeteer、Playwright 等自动化框架。
本文档描述的是桌面客户端本机接口,默认地址为
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"
}
二、通用约定
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 状态 |
| 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 临时文件 |
| 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"
}
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、目标站点、并发限制和会话节点影响。
七、自动化框架接入
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。
九、接口边界与版本兼容
- 本文只把上方接口作为对外自动化文档维护。
/sql3db/sql3AddBr、/sql3db/sql3GetBr、/sql3db/sql3DelBr属于客户端本地缓存维护接口,不建议业务脚本直接调用。/auto/savecrx、/auto/getAllCrx、/auto/getCRXFiles、/auto/getExtInfo、/auto/chromeStoreDownload、/auto/downloadcrx、/auto/uploadcrx、/auto/sql3DelCrx属于扩展管理内部接口,参数和返回值可能随客户端升级调整,不作为稳定公开契约。/user/getkey、/user/getconfig是 EasyBR 扩展与桌面客户端之间的内部通信接口,不属于用户自动化 API。/user/getProxyTest是代理提取链接的内部预览接口,不作为稳定公开契约;代理连通性请使用/user/checkProxyTest。- 旧接口名继续保留;不要擅自改成
/api/v2、/local-api/v2或更正Brower拼写。 - 客户端升级后如果返回字段增加,调用方应忽略不认识的字段,不应因新增字段报错。
自动化 Demo:
文档最后核对日期:2026-08-06。
先试 EasyBR,再决定是否扩团队或做更深的定制项目
标准版适合先验证多账号环境、代理和数据迁移;如果你需要更深的业务能力,我们也支持浏览器外包、Chromium 定制、贴牌浏览器与 Android 指纹浏览器开发。