Skip to content

候鸟 ApiServer Rules 知识包

这是本栏目最核心的内容。将以下 Rules 知识包注入到 Cursor 或 Antigravity 中,AI 模型就能完整掌握候鸟 ApiServer 的所有接口、错误码和附录参数,从此写脚本再也不会"胡编乱造"。


IMPORTANT

候鸟自动化运行核心建议: 在运行自动化脚本时,请务必在候鸟客户端设置中将运行模式切换为 “本地模式”

  • 性能提升:本地模式不再进行网络数据同步(上传/下载环境数据),可将自动化启动与脚本执行效率提升 数十倍
  • 安全提示:请务必养成日常备份本地数据的习惯。您的核心业务数据(环境、指纹、Cookie 等)均存储在 MBDATA 目录中,请定期对该文件夹进行异地备份。

如何使用

Cursor 用户

  1. 在您的候鸟脚本项目根目录,新建文件:.cursor/rules/mbbrowser.mdc
  2. 将下方全部内容复制粘贴进该文件,保存
  3. 重启 Cursor 对话(或新建一个 Chat)
  4. 此后每次对话,AI 都自动带着这份知识

Antigravity 用户

Antigravity(Google 的 agent-first IDE)有自己的规则体系,使用独立的 .agent/rules/ 目录。

步骤如下:

  1. 在项目根目录(workspace 或 git root)新建文件夹:.agent/rules/
    (如果已存在,直接用)

  2. 在该文件夹中新建文件:mbbrowser.md(扩展名必须是 .md,纯 Markdown 格式)

  3. 将“候鸟 ApiServer 完整 Rules 知识包”中的规范、接口细节、代码模板等复制粘贴进该文件,保存。

  4. 重启 Antigravity 或重新打开项目 → Agent 会自动加载 .agent/rules/ 下的所有 .md 文件,并注入到 system prompt 中(workspace 级别生效)。

示例文件结构:

your-project/
└── .agent/
    └── rules/
        └── mbbrowser.md   ← 这里放你的规范内容

额外提示:

  • 全文同步:如果你同时用 Cursor,可双路径维护:.cursor/rules/mbbrowser.mdc(Cursor 用 .mdc)+ .agent/rules/mbbrowser.md(Antigravity 用 .md)。
  • 字符限制:规则文件大小上限约 12,000 字符;如果内容太多,建议拆分成多个 .md 文件。
  • 全局生效:如果想全局生效(所有项目),可放 ~/.gemini/GEMINI.md

候鸟 ApiServer 完整 Rules 知识包

以下内容,请完整复制,替换到上面提到的文件中。

markdown
# 候鸟浏览器 (MBBrowser) + ApiServer 完整开发规范

## 一、产品简介

> [!IMPORTANT]
> **提速秘籍**:在大规模自动化运行前,请确保候鸟客户端已开启 **“本地模式”**。该模式下由于不再进行云端数据同步,环境开启速度可提升数十倍。请务必定期手动备份 **`MBDATA`** 业务数据库文件夹。

候鸟浏览器(MBBrowser)是专业指纹防关联浏览器,用于多账号环境隔离管理。
每个"环境"(Session)拥有独立的:浏览器指纹、代理IP、Cookie、User-Agent、时区、语言。
ApiServer(apiserver.exe)是候鸟浏览器对外暴露的本地 HTTP API 服务,让脚本可程序化操控浏览器环境。

## 二、ApiServer 启动方式

```bash
apiserver.exe --port=8186 \
  --account=your_email@qq.com \
  --app_id=YOUR_APP_ID \
  --app_key=YOUR_APP_KEY \
  --hide=off \
  --return=on \
  --logs=on
```

参数说明:
- port: 监听端口,默认 8186
- account: 候鸟登录账号(邮箱)
- app_id: 从候鸟客户端"个人中心 → API设置"获取
- app_key: 从候鸟客户端"个人中心 → API设置"获取
- hide=off: 浏览器有头模式(调试时建议),hide=on 后台无头模式
- return=on: 接口返回数据显示在控制台
- logs=on: JSON 数据写入日志文件

启动成功后,API 地址为 http://127.0.0.1:8186

## 三、通信规范

- 所有接口均为 HTTP POST 请求
- Content-Type: application/json
- Base URL: http://127.0.0.1:8186
- 成功时 code=0,失败时 code 为负数,message 包含错误信息

标准响应格式:
```json
{
  "message": "Success",
  "code": 0,
  "data": { ... }
}
```

## 四、账号认证

### 4.1 账号登录(切换账号时使用)
POST /login
```json
{
  "APP_ID": "7e147176e1d756eb03c0e18e7b640c23",
  "APP_KEY": "YOUR_APP_KEY",
  "Account": "test01@qq.com",
  "return": "on",
  "logs": "on",
  "hide": "off"
}
```
参数说明:
- return: on/off,是否将返回数据/状态显示在控制台界面。
- logs: on/off,是否将返回数据/状态明文写入 API_LOG 目录。
- hide: on/off,是否以全自动模式启动(on 会屏蔽主面板,off 会显示主面板)。
成功返回:{"msg": "Login Success", "status": 0, "data": "Login Aaccount: test01@qq.com"}
注意:ApiServer 启动时已携带认证信息,一般无需额外调用此接口。

### 4.2 退出 ApiServer
POST /api/v1/quit
无请求参数,成功后 ApiServer 关闭,返回 code=0。

## 五、核心接口:环境生命周期管理

### 5.1 打开环境(最核心接口)
POST /api/v1/browser/start
【最大请求频率:不限,但建议 --interval-seconds 控制间隔】

请求参数:
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f"],
  "isHeadless": false,
  "args": [
    "--disable-extensions",
    "--blink-settings=imagesEnabled=false",
    "--interval-seconds=2"
  ]
}
```

重要说明:
- Session_ID 是数组类型,支持同时启动多个环境
- isHeadless=false 为有头模式(可看到窗口),默认 true
- --interval-seconds 控制多个环境之间的启动间隔(秒)
- --blink-settings=imagesEnabled=false 禁止加载图片(加速)
- --disable-extensions 禁用浏览器插件(脚本自动化时常用)

成功响应关键字段:
```json
{
  "message": "Success",
  "code": 0,
  "data": {
    "listid": [{
      "Session_Name": "商用业务环境一",
      "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
      "Group_Name": "default",
      "Actived_script_id": "O73808cb37bd63f5f7d92415e736e999",
      "Actiived_script_name": "这是一个脚本例子",
      "Weblogin_Account_Count": "4",
      "Weblogin_Account_name": "aaa@163.com, aaa1@163.com",
      "Plugins_Count": "4",
      "template_id": "123456",
      "template_name": "抖音国际版",
      "browser_Path": "D:\\mbbrowser\\Chromium_x64\\chromium.exe",
      "browser_CDP_Port": 46973,
      "MBData_Path": "C:\\MBDATA\\xxx",
      "Public_ip": "8.208.80.219",
      "Internel_ip": "192.168.225.69",
      "isDynamicIp": false,
      "StartPage": "about:blank",
      "proxyType": "socks5",
      "proxy_ip": "127.0.0.1",
      "proxy_port": "1080",
      "isHeadless": "true",
      "webdriver": "C:\\Users\\Admin\\houniao\\Driver\\100\\chromedriver.exe",
      "status": 0
    }],
    "total": 1
  }
}
```

【极其重要】各框架正确接入方式:

Python Playwright:
```python
port = env_data["browser_CDP_Port"]
ws_endpoint = f"ws://127.0.0.1:{port}/json/version"
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.connect_over_cdp(ws_endpoint)
context = browser.contexts[0]          # 必须取已有 context!不能 new_context()
page = context.pages[0] if context.pages else context.new_page()
```

JavaScript Playwright:
```javascript
const { chromium } = require('playwright');
const port = envData.browser_CDP_Port;
const wsEndpoint = `ws://127.0.0.1:${port}/json/version`;
const browser = await chromium.connectOverCDP(wsEndpoint);
const context = browser.contexts()[0];  // 必须取已有 context!
const page = context.pages()[0] || await context.newPage();
```

Python Selenium:
```python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
options = Options()
# debuggerAddress 是 "IP:PORT" 格式,不带 ws://
options.add_experimental_option("debuggerAddress", f"127.0.0.1:{env_data['browser_CDP_Port']}")
service = Service(executable_path=env_data['webdriver'])
driver = webdriver.Chrome(service=service, options=options)
```

JavaScript Puppeteer:
```javascript
const puppeteer = require('puppeteer');
const port = envData.browser_CDP_Port;
const wsEndpoint = `ws://127.0.0.1:${port}/json/version`;
const browser = await puppeteer.connect({
  browserWSEndpoint: wsEndpoint,
  defaultViewport: null
});
```

Java Playwright:
```java
import com.microsoft.playwright.*;
int port = (int) envData.get("browser_CDP_Port");
String wsEndpoint = "ws://127.0.0.1:" + port + "/json/version";
Playwright pw = Playwright.create();
Browser browser = pw.chromium().connectOverCDP(wsEndpoint);
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().isEmpty() ? context.newPage() : context.pages().get(0);
```

### 5.2 关闭环境
POST /api/v1/browser/stop
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f"
}
```
注意:Session_ID 在此接口为字符串(非数组)。
成功返回:{"message": "Success", "code": 0, "data": {"action": "StopSession_ID", "status": 0}}

### 5.3 强制终止环境
POST /api/v1/browser/kill
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f"
}
```
注:在用部分浏览器插件扩展后,普通的 stop 会导致浏览器在后台驻留运行,因此建议使用强制终止(kill)接口彻底结束进程。
成功返回:{"message": "Successfully terminated", "code": 0, "data": {"action": "StopSession_ID", "status": 0}}

### 5.4 查看环境运行状态
POST /api/v1/browser/status
```json
{
  "Session_ID": ["4e6d0dca26ef42be9bc4472779d2550f"],
  "Actived_Type": 0
}
```
Actived_Type:0=返回所有状态,1=仅返回运行中的,2=仅返回未运行的
返回 Session_Actived=1 表示运行中,0 表示未运行。
详细返回字段包括:Session_ProcessID、Session_StartTime、Session_Headless、Session_Args。

## 六、环境信息查询接口

### 6.1 获取环境列表(支持多维度过滤)
POST /api/v1/session/listid

支持过滤参数(全部可选):
- Session_Name:按环境名称筛选
- Session_GroupName:按分组名称筛选
- Session_CreateTime_Start / End:按创建时间范围筛选
- Session_UpdateTime_Start / End:按最近使用时间筛选
- Session_Recv=1:返回我收到的分享环境
- Session_Recv_Account:返回指定账号分享给我的环境
- Session_Sent=1:返回我分享出去的环境
- Session_Sent_Account:返回分享给指定账号的环境
- Proxy_Ip:按代理IP筛选
- Proxy_Type:按代理类型筛选(数组,如 ["socks5"])
- Comment:按备注关键字筛选
- Session_ISWebAccount=1:筛选有网页账号的环境
- Session_WebAccounts:筛选有指定网页账号的环境
- Session_ISPlugins=1:筛选有插件的环境
- Session_Plugins_id:筛选有指定插件ID的环境
- Session_ISAutoScript=1:筛选有脚本的环境
- Session_AutoScript_id:筛选有指定脚本ID的环境
- CurrentPage:页码(默认1)
- ListNum:每页条数(默认50,最多500)

成功返回:
```json
{
  "code": 0,
  "data": {
    "listid": ["373808cb37bd63f5f7d92415e736e85f", "705cc4c139e69b729a2fd277f30e1863"],
    "total": 2
  }
}
```

注意:不传任何参数时,默认按 UpdateTime 倒序返回最近 50 条环境ID。

### 6.2 查询指定环境ID的配置数据
POST /api/v1/session/id_container
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f"],
  "Session_container_type": 1
}
```
Session_container_type:
  1 = 返回环境完整内容(包含 browser_CDP_Port、webdriver、所有指纹信息)
  2 = 返回环境精简内容(基本信息 + 代理信息)
  3 = 返回包含 plugin/script 的精简内容

完整返回字段包括:Session_Name、Session_ID、Group_Name、Actived_script_id、
Weblogin_Account_Count、Plugins_Count、template_id、template_name、
browser_Path、browser_CDP_Port、MBData_Path、Public_ip、Internel_ip、
isDynamicIp、StartPage、System、Resolution、UserAgent、proxyType、
proxy_ip、proxy_port、webdriver、updatetime、createtime、item_version、
UnActived_script_list(未激活脚本列表)等。

## 七、环境创建与更新接口

### 7.1 创建环境
POST /api/v1/session/create
【最大请求频率:40次/分钟】
创建环境,支持配置基本要求和代理信息,创建成功返回环境 ID。
```json
{
  "Session_Name": "20230223",
  "Session_Desc": "THIS_IS_A_TEST",
  "Session_Group": "NEWGROUP",
  "Proxy_Type": "HTTP",
  "Proxy_Ip": "127.0.0.1",
  "Proxy_Port": "1080",
  "Proxy_Username": "TEST",
  "Proxy_Password": "TEST",
  "TimeZone": "US/Alaska -09:000",
  "Cookie": "thisisaCOOKIE",
  "Automatic_Configure": 1,
  "Disable_video": 0,
  "Disable_img": 0
}
```
重要参数 `Automatic_Configure`
- `0`(推荐):快速创建环境,零耗时等待(自动依据候鸟商业库匹配指纹,无需验证代理)。
- `1`:包含代理IP验证模式。自动通过给定代理去匹配信息,创建耗时极长(需将代码请求检测超时设为 68 秒以上)。
成功返回:{"message": "Added Success", "code": 0, "data": {"Session_Id": "xxx"}}

### 7.2 更新环境基本信息
POST /api/v1/session/update
【最大请求频率:40次/分钟】
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Session_Name": "商业环境一",
  "Session_Desc": "环境描述",
  "Session_Group": "环境所属分组",
  "Cookie": "JSON格式cookie文本",
  "Disable_video": 0,
  "Disable_img": 0,
  "HomePage_url": "https://www.example.com"
}
```
成功返回:{"message": "Update Session Success", "code": 0, "data": {"Session_Id": "xxx"}}

### 7.3 更新环境代理
POST /api/v1/session/proxy/update
【最大请求频率:50次/分钟】
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Proxy_Type": "HTTP",
  "Proxy_Ip": "127.0.0.2",
  "Proxy_Port": 1234,
  "Proxy_Username": "abcdefg",
  "Proxy_Password": "123456",
  "StaticIP_Type": 1,
  "Is_CheckProxy": 0,
  "Static_PublicIP": "10.0.0.1",
  "Static_PrivateIP": "192.168.1.1",
  "LanguageCode": "En-US;en;q=0.9",
  "TimeZone": "US/Alaska -09:000",
  "CountryCode": "US",
  "CityCode": [],
  "RegionCode": []
}
```
支持的代理类型:HTTP、HTTPS、SSH、SOCKS4、SOCKS4A、SOCKS5、
Oxylabsauto、Lumauto、Luminati_HTTP、Luminati_HTTPS、smartproxy、noproxy(无代理直连)
成功返回:{"message": "Update Session Proxy Success", "code": 0, "data": {"Session_Id": "xxx"}}

### 7.4 更新环境高级指纹参数
POST /api/v1/session/adv_setting
【最大请求频率:40次/分钟】
```json
{
  "Session_ID": "cf77e3cb4a2bd3b7b69b48809eb5475b",
  "SystemOS": "Windows",
  "Session_Resolution": "1920x1080",
  "Session_UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
  "LanguageCode": "En-US;en;q=0.9",
  "TimeZone": "US/Eastern -05:000",
  "CountryCode": "US",
  "IS_WEBRTC": 1,
  "FingerPrint_Setting": "1,1,1,1",
  "Lock_Browser_windows_size": 1,
  "Disable_video": 0,
  "Disable_img": 0,
  "Static_PublicIP": "xxx.xxx.xxx.xxx",
  "Static_PrivateIP": "xxx.xxx.xxx.xxx"
}
```
FingerPrint_Setting 格式:Lwav,FontCode,Dns,Canvas(各位1=有效,0=无效)
SystemOS 支持值:参见附录系统表

### 7.5 删除环境
POST /api/v1/session/delete
支持批量删除环境。注意:一次性最高支持删除环境 2000 个。
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f", "7579a099e6"],
  "Is_Delete_All": 0
}
```
参数 `Is_Delete_All`:当值为 1 时,忽略 Session_ID,全局清空所有环境。
成功返回示例:{"msg": "Session Delete Finished.", "code": -12, "data": {"Delete_Session_Success": "373...", "Delete_Session_Failed": "757..."}}

### 7.6 清除环境本地缓存
POST /api/v1/session/BrowserCache-clean
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f"],
  "Is_Clean_Cookies": 1
}
```
Is_Clean_Cookies=1:仅清除 Cookie,其他缓存不清除。
成功返回字段含:Clean_SessionID_Success 和 Clean_SessionID_Failed。

## 八、Cookie 管理

### 8.1 导入 Cookie(从文件)
POST /api/v1/session/import-cookie
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Cookie_File": "C:\\cookies\\account1.txt"
}
```
Cookie_File 支持 .txt(Netscape格式)和 .json 格式文件路径。
成功:code=0,失败:code=-13(导入失败:Cookie格式不合法)

### 8.2 导出 Cookie(到文件)
POST /api/v1/session/export-cookie
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Export_Cookie_File": "C:\\cookies\\export.json"
}
```
文件扩展名为 .json 则导出 JSON 格式,否则导出 Netscape 文本格式。
成功:code=0,失败:code=-14(导出失败:Cookie内容为空)

## 九、插件管理

### 9.1 列出账号下所有已安装插件
POST /api/v1/plugin/list
无请求参数(空JSON即可)。
返回 Plugin_list 数组,每项含 Plugin_Name、Plugin_Id、Plugin_Ver。

### 9.2 查询指定环境的插件列表
POST /api/v1/session/id_plugin_list
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f"]
}
```
返回每个环境的 Plugins_Count 和 Plugin_list 详情。

### 9.3 安装插件到指定环境
POST /api/v1/session/plugin_install
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Plugin_ID": ["ncennffkjdiamlpmcbajkmaiiiddgioo", "f994d8e641ce7006acfa36c901829ff2"],
  "Plugin_ver": "1.0.0"
}
```
Plugin_ver 可选,默认安装最新版本。

### 9.4 删除环境中的插件
POST /api/v1/session/plugin_delete
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Plugin_ID": ["ncennffkjdiamlpmcbajkmaiiiddgioo"]
}
```
每次仅针对单个环境,一次支持删除多个插件。
成功返回含:Delete_Plugin_Success 和 Delete_Plugin_Failed 字段。

## 十、自动化脚本管理

### 10.1 查询环境中的所有脚本
POST /api/v1/session/id_script_list
```json
{
  "Session_ID": ["373808cb37bd63f5f7d92415e736e85f"]
}
```
返回:Actived_script_id(激活脚本ID)、Actiived_script_name、Script_Count、
UnActived_script_list(未激活脚本数组:含 ID、Name、is_encode)。

### 10.2 从脚本库分配脚本到环境
POST /api/v1/session/id_script_add
【需要候鸟客户端版本 4.6.16.132+】
```json
{
  "Script_ID": ["7579a099e6fcee76fd1272ccdc30c1cc"],
  "Session_ID": "914a9b97c6787a231ed2ab25e02ad5c9"
}
```
Script_ID 数组最多 100 个,Session_ID 每次仅支持单个环境。

### 10.3 激活脚本(切换环境激活脚本)
POST /api/v1/session/id_script_active
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Active_Script_ID": "O73808cb37bd63f5f7d92415e736e999"
}
```
将环境中已存在的脚本设为激活状态。

### 10.4 将脚本设置为非激活状态
POST /api/v1/session/id_script_Deactivate
【需要候鸟客户端版本 6.6.2.190+】
```json
{
  "Session_ID": "373808cb37bd63f5f7d92415e736e85f",
  "Script_ID": "O73808cb37bd63f5f7d92415e736e999"
}
```

### 10.5 从环境移除脚本
POST /api/v1/session/id_script_Delete
【需要候鸟客户端版本 6.6.2.190+】
```json
{
  "Session_ID": "914a9b97c6787a231ed2ab25e02ad5c9",
  "Script_ID": ["373808cb37bd63f5f7d92415e736e85f", "705cc4c139e69b729a2fd277f30e1863"]
}
```
注意:只能移除"未激活"状态的脚本;Script_ID 为数组。

## 十一、分组管理

### 11.1 获取分组列表
POST /api/v1/group/list
可选参数:Session_ID(指定环境ID)或 Session_Name(环境名称)返回所属分组。
不传参数则返回账号下所有分组名称。
返回:{"Group_Name_List": "我的分组一, 我的分组二, 我的分组三"}

### 11.2 新建分组
POST /api/v1/group/create
```json
{
  "Group_Name": "新分组名称"
}
```
分组名称不能与已有分组重复。

### 11.3 删除分组
POST /api/v1/group/del
批量删除指定环境分组。删除前需确保该分组下环境已清空或已被转移。
```json
{
  "Group_Name": ["新分组名称", "另一个分组"]
}
```
成功返回:{"msg": "Group Delete Success", "code": 0, "data": true}

### 11.4 将环境转移到另一个分组
POST /api/v1/group/move_session
```json
{
  "Session_ID": ["ce4c125179fbe98ba362384115a6f82c", "ba404bdda87bdf5a7c5ecff2a4a260ea"],
  "Orgin_Group_Name": "我的分组一",
  "Target_Group_Name": "我的分组二"
}
```
返回每个环境的转移结果,status=0 表示成功。

## 十二、工具接口

### 12.1 获取随机 User-Agent
POST /api/v1/session/random-user-agent
```json
{
  "SYSTEM": "Windows",
  "Version": "104"
}
```
SYSTEM 可选值:Windows、Android、iPhone
MobileModel(当 SYSTEM 为 Android 或 iPhone 时必填):
  如 "iPhone 13 Pro"、"google Pixel 4"、"samsung Galaxy Note8"
Version:浏览器版本号(95-106之间的整数字符串)
返回:{"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."}

### 12.2 获取成员列表(团队版)
POST /members
请求参数:`{"Account": "test01@qq.com"}`
用于获取和此帐户相关联的主帐号与子帐号数据(返回:`"data": "test01@qq.com:0"`,0=主账户,1=子账户)。

## 十三、完整错误码表

### CODE 错误码(请求级别)
```
0      成功
-1     登录失败 / App_ID 或 App_KEY 非法
-2     登录失败 / 连接候鸟服务器超时(curl 状态码)
-3     当前登录帐户套餐已过期
-4     Login_Expire(登录过期)
-5     Login_ServerError / 服务器访问错误
-6     Login_MbSvrError / 启动 mbservice 失败
-7     Login_Uping / 有上传正在进行,需等待完成才能登录
-8     Login_Occupy / 有其他实例已占用登录
-9     数据同步失败:超时
-10    数据处理失败:数据损坏导致无法加载
-11    数据处理失败:当前目录没有写权限
-12    登录失败 / App_ID 处于在线状态
-13    删除环境失败(或导入Cookie失败)
-14    导入 COOKIE 失败:COOKIE 格式不合法
-15    导出 COOKIE 失败:COOKIE 内容为空
-101   创建/更新环境失败:环境名称超长
-102   创建/更新环境失败:环境描述超长
-103   创建/更新环境失败:分组不存在
-104   创建/更新环境失败:代理服务器填入值不合法
-105   创建/更新环境失败:代理检测失败,无效代理
-106   创建/更新环境失败:初始化时区失败
-107   创建/更新环境失败:操作系统名称填写错误
-108   创建/更新环境失败:环境分辨率填写错误
-109   创建/更新环境失败:USERAGENT 未填入有效值
-110   创建/更新环境失败:环境默认语言未填入有效值
-111   创建/更新环境失败:FingerPrint_Setting 填入值非法
-112   创建/更新环境失败:导入 COOKIE 文件内容不合法
-10000 未知异常
```

### Status 错误码(打开环境时 status 字段)
```
0      成功
-1     初始化数据失败
-2     启动浏览器内核失败
-3     当前浏览器环境:插件下载失败
-4     当前浏览器环境:插件加载失败
-5     当前浏览器环境:自动化脚本下载失败
-6     当前浏览器环境:自动化脚本加载失败
-7     当前浏览器环境:已经运行
-8     当前浏览器环境:已经加入运行队列
-9     当前浏览器环境:初始化 CDP 失败
-10    当前浏览器环境:初始化 Service 失败
-11    当前浏览器环境:CDP 监听失败
-12    当前浏览器环境:DP 退出
-13    当前浏览器环境:连接失败
-14    当前浏览器环境:初始化环境失败
-15    当前浏览器环境:GetShortPathName 失败
-16    当前浏览器环境:申请内存失败
-17    当前浏览器环境:登录退出
-18    当前浏览器环境:未收到响应信息
-19    当前浏览器环境:关闭失败
-20    Headless 打开项无法用 stop 关闭,建议使用 kill 关闭
-21    当前浏览器环境:强制关闭失败
-22    未找到指定的环境 SessionId
-5010  POST 串请求的目标 API URL 中有非法字符
-10000 未知错误
```

### CURL 代理检测错误码(更新/创建代理时 Is_CheckProxy=1 可能触发)
```
0    CURLE_OK  成功
5    CURLE_COULDNT_RESOLVE_PROXY   无法解析代理服务器
6    CURLE_COULDNT_RESOLVE_HOST    无法解析主机名
7    CURLE_COULDNT_CONNECT         无法连接到远程服务器
28   CURLE_OPERATION_TIMEDOUT      操作超时
35   CURLE_SSL_CONNECT_ERROR       SSL 连接错误
52   CURLE_GOT_NOTHING             未收到任何数据
56   CURLE_RECV_ERROR              接收错误
60   CURLE_PEER_FAILED_VERIFICATION 对端验证失败
```

## 十四、附录:参数合法值表

### 14.1 SystemOS 操作系统合法值
以下值可用于 adv_setting 和 create 接口的 SystemOS 参数:
Windows | iPhone | iPad | MacIntel | Android | Linux aarch64 | Linux armv7l | Linux armv8l | Linux i686 | Linux x86_64

### 14.2 国家码(CountryCode)完整表
常用国家码(创建/更新代理时使用 CountryCode 字段):
```
US=美国  CN=中国内地  GB=英国  DE=德国  FR=法国  JP=日本  KR=韩国
HK=中国香港  TW=中国台湾  MO=中国澳门  SG=新加坡  AU=澳大利亚
CA=加拿大  RU=俄罗斯  BR=巴西  IN=印度  MX=墨西哥  ID=印度尼西亚
TH=泰国  VN=越南  MY=马来西亚  PH=菲律宾  PK=巴基斯坦  BD=孟加拉
TR=土耳其  SA=沙特阿拉伯  AE=阿联酋  IL=以色列  ZA=南非  EG=埃及
IT=意大利  ES=西班牙  NL=荷兰  PL=波兰  SE=瑞典  NO=挪威  CH=瑞士
AT=奥地利  BE=比利时  PT=葡萄牙  CZ=捷克  UA=乌克兰  AR=阿根廷
CL=智利  CO=哥伦比亚  PE=秘鲁  VE=委内瑞拉  NG=尼日利亚  KE=肯尼亚
```
完整列表包含180+个国家,使用时传入两位大写字母代码。

### 14.3 语言代码(LanguageCode)常用值
格式通常为 "语言代码;q=优先级",例如:
```
中文(简体):zh-CN;zh;q=0.9
中文(繁体):zh-TW;zh;q=0.9
英语(美国):en-US;en;q=0.9
英语(英国):en-GB;en;q=0.9
日语:        ja;q=0.9
韩语:        ko;q=0.9
法语:        fr-FR;fr;q=0.9
德语:        de-DE;de;q=0.9
西班牙语:    es-US;es;q=0.9
俄语:        ru;q=0.9
泰语:        th;q=0.9
越南语:      vi;q=0.9
印度尼西亚语:id;q=0.9
马来语:      ms;q=0.9
阿拉伯语:    ar;q=0.9
葡萄牙语:    pt-BR;pt;q=0.9
意大利语:    it-IT;it;q=0.9
荷兰语:      nl;q=0.9
波兰语:      pl;q=0.9
土耳其语:    tr;q=0.9
```
注意:传参时第一个语言必须支持渲染(参照语言文档的"是否支持渲染"列)。

### 14.4 常用分辨率(Session_Resolution)
```
PC 常用分辨率:
1920x1080  1440x900  1366x768  1280x720  1280x1024
2560x1440  2560x1600  3840x2160(4K)
1600x900  1024x768  1920x1200  1680x1050  1080x1920

移动端常用分辨率:
375x667(iPhone 6/7/8)  375x812(iPhone X)  390x844(iPhone 12)
412x892(Pixel 3)  360x640(通用安卓)  375x750(iPhone高清)
414x896(iPhone XR)  393x852(iPhone 14)
```

### 14.5 时区(TimeZone)列表
时区需要传入精准值。完整 500+ 个时区因篇幅限制未全部列出,但支持的标准格式如 `Etc/GMT+12` 或具体名称。
常见示例:
```
"Etc/GMT+12" 到 "Etc/GMT-14"
"America/New_York"(东部) "America/Chicago"(中部) "America/Denver"(山地) "America/Los_Angeles"(太平洋)
"Europe/London"  "Europe/Paris"  "Europe/Berlin"  "Europe/Moscow"
"Asia/Shanghai"  "Asia/Tokyo"  "Asia/Singapore" "Asia/Seoul"
"Australia/Sydney" "Pacific/Auckland" "Pacific/Fiji"
```

## 十五、开发注意事项

1. Session_ID 类型注意:
   - /api/v1/browser/start:Session_ID 是数组
   - /api/v1/browser/stop:Session_ID 是字符串
   - /api/v1/session/update:Session_ID 是字符串
   - /api/v1/session/import-cookie:Session_ID 是字符串
   - /api/v1/session/id_container:Session_ID 是数组
   - /api/v1/session/proxy/update:Session_ID 是字符串

2. Playwright 接管 context:
   必须用 browser.contexts[0](Python)或 browser.contexts()[0](JS),
   绝对不能用 browser.new_context(),否则会丢失所有 Cookie 和登录状态。

3. Selenium 用 debuggerAddress 不用 ws:
   格式是 "127.0.0.1:PORT"(不带 ws://、不带 /json/version)。

4. Puppeteer 用 browserWSEndpoint:
   格式是 "ws://127.0.0.1:PORT/json/version"(带 ws:// 协议头)。

5. 多线程安全:每个线程使用独立的 sync_playwright() 实例,不要共享。

6. 并发控制:建议每批不超过 20 个环境,根据本机内存调整。

7. 状态码检查:每次 start 后检查 data.listid[0].status,非 0 即失败。

8. 代理验证:start 接口返回的 Public_ip 可用于验证代理是否生效。

9. 创建环境时分辨率/语言/时区必须使用附录中的合法值,否则返回 -106/-107/-108/-110 错误。

10. cookie 导入接口:Cookie_File 是本地文件路径,非 Cookie 字符串内容。
    如果需要写入 Cookie 字符串,应使用 update 接口的 Cookie 字段。

## 十六、完整 Python 脚本模板

```python
"""
候鸟浏览器 + Playwright Python 自动化脚本模板
"""
import requests
import threading
from playwright.sync_api import sync_playwright

APISERVER_URL = "http://127.0.0.1:8186"

def start_env(session_id: str, headless: bool = False) -> dict | None:
    """开启候鸟环境,返回 listid[0] 数据"""
    try:
        resp = requests.post(
            f"{APISERVER_URL}/api/v1/browser/start",
            json={
                "Session_ID": [session_id],
                "isHeadless": headless,
                "args": ["--blink-settings=imagesEnabled=false", "--interval-seconds=2"]
            },
            timeout=30
        )
        data = resp.json()
        if data["code"] == 0 and data["data"]["listid"]:
            env = data["data"]["listid"][0]
            if env["status"] == 0:
                return env
            print(f"[{session_id[:8]}] 打开失败 status={env['status']}")
    except Exception as e:
        print(f"[{session_id[:8]}] ApiServer 错误: {e}")
    return None

def stop_env(session_id: str):
    """关闭候鸟环境"""
    try:
        requests.post(
            f"{APISERVER_URL}/api/v1/browser/stop",
            json={"Session_ID": session_id},    # stop 用字符串!
            timeout=10
        )
    except Exception:
        pass

def get_all_sessions(group_name: str = None) -> list[str]:
    """获取所有环境ID(支持按分组筛选,支持翻页)"""
    all_ids = []
    page = 1
    while True:
        params = {"CurrentPage": page, "ListNum": 500}
        if group_name:
            params["Session_GroupName"] = group_name
        resp = requests.post(f"{APISERVER_URL}/api/v1/session/listid", json=params, timeout=15)
        data = resp.json()
        if data["code"] != 0:
            break
        batch = data["data"]["listid"]
        all_ids.extend(batch)
        if len(all_ids) >= data["data"]["total"]:
            break
        page += 1
    return all_ids

def connect_playwright(env_data: dict):
    """用 Playwright 接管候鸟浏览器"""
    port = env_data["browser_CDP_Port"]
    ws_endpoint = f"ws://127.0.0.1:{port}/json/version"
    pw = sync_playwright().start()
    browser = pw.chromium.connect_over_cdp(ws_endpoint)
    context = browser.contexts[0]      # 必须取已有 context!
    page = context.pages[0] if context.pages else context.new_page()
    return pw, browser, page

def do_task(session_id: str):
    """单账号任务函数"""
    try:
        env_data = start_env(session_id)
        if not env_data:
            print(f"[{session_id[:8]}] 开启失败,跳过")
            return
        
        pw, browser, page = connect_playwright(env_data)

        # ========= 在这里写您的业务逻辑 =========
        page.goto("https://example.com")
        print(f"[{session_id[:8]}] 公网IP={env_data['Public_ip']} 标题={page.title()}")
        # =========================================

        browser.close()
        pw.stop()
    except Exception as e:
        print(f"[{session_id[:8]}] 异常: {e}")
    finally:
        stop_env(session_id)

# 批量并发运行
if __name__ == "__main__":
    SESSION_IDS = get_all_sessions(group_name="亚马逊店铺")
    print(f"共 {len(SESSION_IDS)} 个环境")
    threads = [threading.Thread(target=do_task, args=(sid,)) for sid in SESSION_IDS]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print("✅ 全部完成!")
```

知识包配置验证

配置完成后,在 Cursor Chat 里输入:

用候鸟 ApiServer 写一个 Python 脚本,获取分组"测试分组"下所有环境ID,
并发开启(最多 10 并发),每个环境用 Playwright 访问 https://example.com,
截图后关闭。有完整的错误处理。

如果 AI 正确使用了以下内容,说明知识包注入成功:

  • POST /api/v1/session/listid 获取环境列表
  • POST /api/v1/browser/start Session_ID 为数组
  • browser.contexts[0] 取已有 context,而非 new_context
  • POST /api/v1/browser/stop Session_ID 为字符串

TIP

知识包配置好了?下一步:候鸟 Skills 提示词包 提供现成的场景化模板,口述需求即可生成脚本!