开放接口文档

启元指纹浏览器 · 本地客户端开放 API · v2.0

认证流程

只需在启动客户端时传入 --run_mode=api --app_id=xxx --app_secret=xxx, 客户端自动完成身份认证,后续所有接口调用均无需额外传递凭证。
AppID 和 AppSecret 从「开发者中心」页面获取。

接入方式

开放接口基于 HTTP 协议,客户端启动后服务默认监听在 http://127.0.0.1:9001(可通过 --port 参数修改)。无需建立长连接,直接发送 HTTP 请求即可。

启动命令

Qiyuan.exe --run_mode=api --port=9001 --app_id=your_app_id --app_secret=your_app_secret

请求说明

快速验证

# 查询环境列表(curl 示例)
curl "http://127.0.0.1:9001/open/env/list?page=1&page_size=10"

环境接口

GET /open/env/list 查询环境列表

Query 参数

字段类型必填说明
pagenumber可选页码,默认 1
page_sizenumber可选每页数量,默认 20,最大 100
keywordstring可选按环境名称模糊搜索

响应 data

{
  "total": 100,
  "page": 1,
  "page_size": 20,
  "total_pages": 5,
  "items": [
    {
      "code": "a1b2c3d4...",         // string  环境唯一标识,后续操作均使用此字段
      "name": "测试账号-01",          // string  环境名称
      "browser_version": "138.0.7204.184", // string  内核版本号,null 表示未配置
      "platform": "Win32",          // string  Win32 / MacIntel / Linux x86_64
      "user_agent": "Mozilla/5.0 ...", // string  User-Agent 字符串
      "proxy_ip_code": "1716523...", // string  绑定代理的唯一标识,未绑定为 null
      "remark": "备注信息",          // string  备注
      "tag_ids": [1, 2],             // number[]  标签 ID 列表
      "open_home_page": true,        // boolean  是否打开首页
      "status": "stopped",          // string  running | stopped
      "debug_port": null,           // number  CDP 调试端口,running 时有值,否则 null
      "create_time": "2024-01-01T00:00:00",
      "update_time": "2024-06-01T12:00:00"
    }
  ]
}
POST /open/env/create 新增环境

基础信息字段

字段类型必填默认值说明
namestring必填环境名称
platformstring可选Win32操作系统。可选值:Win32 / MacIntel / Linux x86_64
browser_versionstring可选145.0.7632.109(最新)完整内核版本号。不填自动取最新版本。可选值:145.0.7632.109 / 139.0.7258.67 / 138.0.7204.184
user_agentstring可选自动生成User-Agent。不填时根据 platform + browser_version 自动生成(UA 随版本变化)
proxy_ip_codestring可选绑定代理的唯一标识(来自 GET /open/proxy/list 的 code 字段)
open_home_pageboolean可选false是否打开首页
enable_tabsboolean可选false是否启用多标签页
tabsstring可选""标签页 URL,多个用换行分隔(enable_tabs=true 时生效)
sync_user_infoboolean可选false是否开启云端用户信息同步(账号数据云备份)
cookiestring可选""初始 Cookie 内容
launch_argsstring可选""额外 Chrome 启动参数,空格分隔,如 --disable-gpu --no-sandbox
remarkstring可选""备注
tag_idsnumber[]可选[]标签 ID 列表

指纹字段

所有指纹字段均为可选,未传时使用后端默认值。

字段类型默认值说明 / 可选值
webrtcstringdisabledip 基于IP  |  real 真实  |  disabled 禁用  |  transform_google 转发
webglstringrealreal 真实  |  custom 自定义(需同时提供 webgl_vendorwebgl_renderer
webgl_vendorstringwebgl=custom 时必填。厂商名,如 Intel Inc. / NVIDIA Corporation / AMD / Apple Inc.
webgl_rendererstringwebgl=custom 时必填。渲染器名,如 Intel(R) UHD Graphics 630 / NVIDIA GeForce RTX 4090
webgpustringbaseglbasegl 基于WebGL  |  real 真实  |  custom 自定义(需提供 webgpu_vendor/architecture/device/description)
webgpu_vendorstringwebgpu=custom 时使用,如 intel / nvidia / amd / apple
webgpu_architecturestringcommon-shader-cores / rdna-3 / apple-gpu
webgpu_devicestringintegrated-gpu / discrete-gpu
webgpu_descriptionstringNVIDIA GeForce RTX 4090 / Intel Iris Xe Graphics
timezonestringipip 基于IP  |  real 真实  |  custom 自定义(需提供 timezone_value
timezone_valuestringtimezone=custom 时使用,IANA 时区格式,如 Asia/Shanghai / America/New_York / Europe/London
geo_locationstringipip 基于IP  |  real 真实  |  custom 自定义(需提供 longitudelatitude
longitudestringgeo_location=custom 时使用,经度,如 116.3
latitudestringgeo_location=custom 时使用,纬度,如 39.9
languagestringipip 基于IP  |  real 真实  |  custom 自定义(需提供 languages 数组)
languagesstring[]language=custom 时使用,语言代码数组,如 ["zh-CN","en-US"]。可用值:zh-CN / zh-TW / en-US / en-GB / ja-JP / ko-KR / fr-FR / de-DE / es-ES / pt-BR / ru-RU 等
ui_languagestringlanguagelanguage 跟随语言  |  real 真实  |  custom 自定义(需提供 ui_language_value
ui_language_valuestringui_language=custom 时使用,单个语言代码,如 zh-CN
screen_resolutionstringrealreal 真实  |  custom 自定义(需提供 screen_resolution_value
screen_resolution_valuestringscreen_resolution=custom 时使用,格式 宽|高,可选:1920|1080 / 2560|1440 / 3840|2160 / 1366|768 / 1440|900 / 1536|864 / 1280|720 / 2560|1080
fontstringrandomdisabled 关闭(值固定为0) |  random 随机(服务端生成 -2~2 整数偏移量)
canvasstringrandomdisabled 关闭  |  random 随机(服务端生成 0~1 浮点噪点,2位小数)
audiostringrandomdisabled 关闭  |  random 随机(服务端生成 0~99 整数噪点)
client_rectsstringrandomdisabled 关闭  |  random 随机(服务端生成 0~0.00001 浮点偏移,6位小数)
speech_voicesbooleantruetrue 开启  |  false 关闭语音合成设备伪装
media_devicesstringrandomdisabled 关闭(null) |  random 随机(服务端生成5个随机媒体设备ID)
cpu_coresstringrealreal 使用真实值  |  2 / 4 / 6 / 8 / 10 / 12 / 16 / 20 / 24 / 32
memory_gbstringrealreal 使用真实值  |  2 / 4 / 8 / 16 / 32 / 64 / 128(单位 GB)
tlsstringenableddisabled 关闭  |  enabled 启用(不传 tls_features 则默认启用全部特征)
tls_featuresstring[]tls=enabled 时可选,不填则启用全部。可选值(多选)::!aPSK 禁用PSK认证 / :!kRSA 禁用RSA密钥交换 / :!ECDSA 禁用ECDSA证书 / :!ECDSA+SHA1 / :!3DES 禁用3DES加密

响应 data

{
  "code": "a1b2c3..."  // string  新建环境的唯一标识(后续所有操作使用此字段)
}

示例

# 最简调用(版本默认最新,UA 自动生成,指纹全部随机)
curl -X POST http://127.0.0.1:9001/open/env/create \
  -H "Content-Type: application/json" \
  -d '{"name": "账号01"}'

# 完整指纹示例
curl -X POST http://127.0.0.1:9001/open/env/create \
  -H "Content-Type: application/json" \
  -d '{
    "name": "账号02",
    "platform": "Win32",
    "browser_version": "145.0.7632.109",
    "proxy_ip_code": "PROXY_CODE",
    "webrtc": "disabled",
    "webgl": "custom",
    "webgl_vendor": "NVIDIA Corporation",
    "webgl_renderer": "NVIDIA GeForce RTX 4090",
    "timezone": "custom",
    "timezone_value": "Asia/Shanghai",
    "geo_location": "custom",
    "longitude": "116.3",
    "latitude": "39.9",
    "language": "custom",
    "languages": ["zh-CN", "en-US"],
    "cpu_cores": "8",
    "memory_gb": "16"
  }'
POST /open/env/update 修改环境(只传需要修改的字段)

支持与 POST /open/env/create 相同的所有字段(code 必填,其余字段只传需要修改的)。未传的字段保持不变。

必填字段

字段类型说明
codestring环境唯一标识

可修改字段

与新增环境入参完全一致(除 name 不再必填),包括所有基础信息字段和指纹字段。

特别说明:若修改了 platformbrowser_version 但未传 user_agent,系统自动重新生成匹配的 UA。

响应

{ "success": true }

示例

# 只修改备注
curl -X POST http://127.0.0.1:9001/open/env/update \
  -H "Content-Type: application/json" \
  -d '{"code": "ENV_CODE", "remark": "新备注"}'

# 切换代理并修改 WebRTC 策略
curl -X POST http://127.0.0.1:9001/open/env/update \
  -H "Content-Type: application/json" \
  -d '{"code": "ENV_CODE", "proxy_ip_code": "NEW_PROXY_CODE", "webrtc": "disabled"}'
POST /open/env/randomize_fingerprint 随机刷新指纹

一键随机重新生成环境的指纹数据,逻辑与客户端界面的"随机指纹"按钮完全一致。WebGL/WebGPU 按平台随机,font/canvas/audio/client_rects/media_devices 全部重新随机,时区/地理位置/语言保持基于IP策略。

Body 参数

字段类型必填说明
codestring必填环境唯一标识

响应 data

{
  "webgl_vendor":   "NVIDIA Corporation",   // 本次随机的 WebGL 厂商
  "webgl_renderer": "NVIDIA GeForce RTX 4090", // 本次随机的 WebGL 渲染器
  "webgpu_value":   "nvidia|common-shader-cores|discrete-gpu|NVIDIA GeForce RTX 4090",
  "font":           -1,           // -2~2 整数偏移
  "canvas":         0.73,         // 0~1 浮点噪点
  "audio":          42,           // 0~99 整数噪点
  "client_rects":   0.000007,     // 0~0.00001 浮点偏移
  "speech_voices":  true,
  "media_devices":  ["a3f2...", "..."]  // 5个随机设备ID
}

示例

curl -X POST http://127.0.0.1:9001/open/env/randomize_fingerprint \
  -H "Content-Type: application/json" \
  -d '{"code": "ENV_CODE"}'
POST /open/env/delete 删除环境

Body 参数

字段类型必填说明
codestring必填环境唯一标识

响应

{ "success": true }
POST /open/env/open 打开浏览器(自动同步扩展、分配调试端口)

Body 参数

字段类型必填说明
codestring必填环境唯一标识
headlessboolean可选是否无头模式,默认 false。设为 true 时浏览器不显示窗口,适合自动化场景
argsstring[]可选追加给 Chrome 的额外启动参数,如 ["--kiosk", "--blink-settings=imagesEnabled=false"]

响应 data

{
  "pid": 12345,         // number  浏览器进程 PID
  "debug_port": 19222   // number  CDP 调试端口(19222-19999 范围内唯一分配)
}

通过调试端口接入自动化框架

# Playwright (Python)
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp('http://127.0.0.1:19222')

# Selenium (Python)
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option('debuggerAddress', '127.0.0.1:19222')
driver = webdriver.Chrome(options=options)

每次 POST /open/env/open 都会分配唯一调试端口,浏览器关闭后端口自动释放并可被复用。

POST /open/env/close 关闭浏览器

Body 参数

字段类型必填说明
codestring必填环境唯一标识

响应

{ "success": true }  // 浏览器未运行时返回 success: false
GET /open/env/status 获取运行状态

Query 参数

字段类型必填说明
codestring必填环境唯一标识

响应 data

{
  "code": "a1b2c3...",   // string  环境唯一标识
  "status": "running",   // string  running | stopped
  "pid": 12345,          // number  进程 PID,stopped 时为 null
  "debug_port": 19222   // number  CDP 调试端口,stopped 时为 null
}
POST /open/env/clear_cache 清空浏览器缓存

Body 参数

字段类型必填说明
codestring必填环境唯一标识

响应

{ "success": true }

清空操作会删除本地 %appdata%\qiyuan\user_data\{code} 目录,若该环境开启了云同步则同时删除服务器备份。

代理接口

GET /open/proxy/list 查询代理列表

Query 参数

字段类型必填说明
pagenumber可选页码,默认 1
page_sizenumber可选每页数量,默认 20,最大 100
keywordstring可选按名称或地址模糊搜索

响应 data

{
  "total": 50,
  "page": 1,
  "page_size": 20,
  "total_pages": 3,
  "items": [
    {
      "code": "1716523200abc",    // string  代理唯一标识(用于修改 / 删除 / 绑定到环境)
      "proxy_name": "美国-01",    // string  代理名称
      "proxy_type": "socks5",    // string  http | https | socks5
      "proxy_addr": "1.2.3.4",    // string  代理服务器地址
      "proxy_port": 1080,         // number  代理端口
      "username": "user",         // string  认证用户名,无则 null
      "create_time": "2024-01-01T00:00:00",
      "update_time": "2024-06-01T12:00:00"
    }
  ]
}
POST /open/proxy/create 新增代理

Body 参数

字段类型必填说明
proxy_namestring必填代理名称
proxy_typestring必填代理类型:http / https / socks5
proxy_addrstring必填代理服务器地址(IP 或域名)
proxy_portnumber必填代理端口(1-65535)
usernamestring可选认证用户名
passwordstring可选认证密码

响应 data

{
  "code": "1716523200abc"    // string  新建代理的唯一标识(用于绑定到环境)
}
POST /open/proxy/update 修改代理

Body 参数

字段类型必填说明
codestring必填代理唯一标识
proxy_namestring可选新的代理名称
proxy_typestring可选新的代理类型
proxy_addrstring可选新的代理地址
proxy_portnumber可选新的代理端口
usernamestring可选新的认证用户名
passwordstring可选新的认证密码

响应

{ "success": true }
POST /open/proxy/delete 删除代理

Body 参数

字段类型必填说明
codestring必填代理唯一标识

响应

{ "success": true }

统一响应格式

所有接口均以 HTTP 200 返回,响应 Body 为 JSON:

// 成功
{ "success": true, "data": { /* 业务数据 */ } }

// 失败
{ "success": false, "error": "错误描述" }

部分接口成功时不返回 data 字段(如 delete、close),只需判断 success 即可。

使用示例

# 依赖: pip install requests playwright
# playwright install chromium
import requests

BASE = "http://127.0.0.1:9001"

def get(path, **params):
    r = requests.get(BASE + path, params=params)
    r.raise_for_status()
    return r.json()

def post(path, **body):
    r = requests.post(BASE + path, json=body)
    r.raise_for_status()
    return r.json()

# ── 新增代理 ──────────────────────────────────────────────────────────────
print("[代理] 正在新增代理...")
res = post("/open/proxy/create",
    proxy_name="美国住宅-01", proxy_type="socks5",
    proxy_addr="1.2.3.4",   proxy_port=1080,
    username="user",         password="pass",
)
print("[代理] 结果:", res)
proxy_code = res["data"]["code"]
print(f"[代理] code={proxy_code}")

# ── 新增环境(指纹字段不传则自动随机)────────────────────────────────────
print("[环境] 正在新增环境...")
res = post("/open/env/create",
    name="账号-01",
    browser_version="138.0.7204.184",  # 推荐显式传入;不传则自动取最新,需先在管理界面下载对应版本
    # proxy_ip_code=proxy_code,  # 如需绑定代理取消注释
    timezone="custom",     timezone_value="Asia/Shanghai",
    geo_location="custom", longitude="116.3", latitude="39.9",
    language="custom",     languages=["zh-CN", "en-US"],
    cpu_cores="8", memory_gb="16",
)
print("[环境] 结果:", res)
env_code = res["data"]["code"]
print(f"[环境] code={env_code}")

# ── 刷新指纹 ───────────────────────────────────────────────────────────────
print("[指纹] 正在随机刷新指纹...")
res = post("/open/env/randomize_fingerprint", code=env_code)
print("[指纹] 结果:", res["data"])

# ── 打开浏览器(headless=False 显示窗口)─────────────────────────────────
print("[浏览器] 正在打开浏览器...")
res = post("/open/env/open", code=env_code, headless=False)
print("[浏览器] 结果:", res)
debug_port = res["data"]["debug_port"]
print(f"[浏览器] 调试端口={debug_port}")

# ── 接入 Playwright ────────────────────────────────────────────────────────
print("[Playwright] 正在连接...")
try:
    from playwright.sync_api import sync_playwright
    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(f"http://127.0.0.1:{debug_port}")
        page = browser.contexts[0].new_page()
        page.goto("https://www.baidu.com")
        title = page.title()
        print(f"[Playwright] 页面标题={title}")

except Exception as e:
    print(f"[错误] Playwright 执行失败: {str(e)}")
    raise

finally:
    print(f"[批量] 获取浏览器状态 {env_code}...")
    r = get("/open/env/status", code=env_code)
    print(f"状态结果={r}")
    print("[关闭] 正在执行兜底关闭...")
    post("/open/env/close", code=env_code)
    print("[关闭] 完成")

# ── 批量查询环境列表 ───────────────────────────────────────────────────────
print("[批量] 查询环境列表...")
res = get("/open/env/list", page=1, page_size=10)
for env in res["data"]["items"]:
    print(f"环境结果={env}")
// 依赖: npm install playwright  (Node 18+ 内置 fetch,无需额外安装)
const BASE = "http://127.0.0.1:9001";

const get = async (path, params = {}) => {
  const qs = new URLSearchParams(params).toString();
  const r = await fetch(`${BASE}${path}${qs ? "?" + qs : ""}`);
  return r.json();
};

const post = async (path, body = {}) => {
  const r = await fetch(BASE + path, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  return r.json();
};

(async () => {
  // ── 新增代理 ──────────────────────────────────────────────────────────
  console.log("[代理] 正在新增代理...");
  let res = await post("/open/proxy/create", {
    proxy_name: "美国住宅-01", proxy_type: "socks5",
    proxy_addr: "1.2.3.4",   proxy_port: 1080,
    username: "user",         password: "pass",
  });
  console.log("[代理] 结果:", res);
  const proxyCode = res.data.code;

  // ── 新增环境 ──────────────────────────────────────────────────────────
  console.log("[环境] 正在新增环境...");
  res = await post("/open/env/create", {
    name: "账号-01",
    // proxy_ip_code: proxyCode,  // 如需绑定代理取消注释
    timezone: "custom",     timezone_value: "Asia/Shanghai",
    geo_location: "custom", longitude: "116.3", latitude: "39.9",
    language: "custom",     languages: ["zh-CN", "en-US"],
    cpu_cores: "8", memory_gb: "16",
  });
  console.log("[环境] 结果:", res);
  const envCode = res.data.code;

  // ── 刷新指纹 ──────────────────────────────────────────────────────────
  console.log("[指纹] 正在随机刷新指纹...");
  res = await post("/open/env/randomize_fingerprint", { code: envCode });
  console.log("[指纹] 结果:", res.data);

  // ── 打开浏览器 ────────────────────────────────────────────────────────
  console.log("[浏览器] 正在打开浏览器...");
  res = await post("/open/env/open", { code: envCode, headless: true });
  console.log("[浏览器] 结果:", res);
  const debugPort = res.data.debug_port;

  // ── 接入 Playwright ───────────────────────────────────────
  const { chromium } = require("playwright");
  let browser = null;
  try {
    browser = await chromium.connectOverCDP(`http://127.0.0.1:${debugPort}`);
    const page = browser.contexts()[0].pages()[0];
    await page.goto("https://www.example.com");
    console.log("[Playwright] 页面标题=", await page.title());
  } catch (err) {
    console.error("[Playwright] 执行失败:", err.message);
    throw err;
  } finally {
    if (browser) await browser.close().catch(() => {});
    await post("/open/env/close", { code: envCode }).catch(() => {});
    console.log("[关闭] 完成");
  }
})();
// 依赖: JDK 11+(内置 java.net.http.HttpClient)
//   org.json:json:20231013
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;

public class QiyuanDemo {

    static final String BASE = "http://127.0.0.1:9001";
    static final HttpClient client = HttpClient.newHttpClient();

    static JSONObject get(String path) throws Exception {
        var req = HttpRequest.newBuilder()
            .uri(URI.create(BASE + path))
            .GET().build();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        return new JSONObject(resp.body());
    }

    static JSONObject post(String path, JSONObject body) throws Exception {
        var req = HttpRequest.newBuilder()
            .uri(URI.create(BASE + path))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(body.toString()))
            .build();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        return new JSONObject(resp.body());
    }

    public static void main(String[] args) throws Exception {

        // ── 新增代理 ──────────────────────────────────────────────────
        System.out.println("[代理] 正在新增代理...");
        JSONObject proxyRes = post("/open/proxy/create", new JSONObject()
            .put("proxy_name", "美国住宅-01").put("proxy_type", "socks5")
            .put("proxy_addr", "1.2.3.4").put("proxy_port", 1080)
            .put("username", "user").put("password", "pass"));
        System.out.println("[代理] 结果: " + proxyRes);
        String proxyCode = proxyRes.getJSONObject("data").getString("code");

        // ── 新增环境 ──────────────────────────────────────────────────
        System.out.println("[环境] 正在新增环境...");
        JSONObject envRes = post("/open/env/create", new JSONObject()
            .put("name", "账号-01")
            // .put("proxy_ip_code", proxyCode)  // 如需绑定代理取消注释
            .put("timezone", "custom").put("timezone_value", "Asia/Shanghai")
            .put("geo_location", "custom").put("longitude", "116.3").put("latitude", "39.9")
            .put("language", "custom").put("languages", new org.json.JSONArray().put("zh-CN").put("en-US"))
            .put("cpu_cores", "8").put("memory_gb", "16"));
        System.out.println("[环境] 结果: " + envRes);
        String envCode = envRes.getJSONObject("data").getString("code");

        // ── 刷新指纹 ──────────────────────────────────────────────────
        System.out.println("[指纹] 正在随机刷新指纹...");
        JSONObject fpRes = post("/open/env/randomize_fingerprint",
            new JSONObject().put("code", envCode));
        System.out.println("[指纹] 结果: " + fpRes.opt("data"));

        // ── 打开浏览器 ────────────────────────────────────────────────
        System.out.println("[浏览器] 正在打开浏览器...");
        JSONObject openRes = post("/open/env/open", new JSONObject()
            .put("code", envCode).put("headless", true));
        System.out.println("[浏览器] 结果: " + openRes);
        int debugPort = openRes.getJSONObject("data").getInt("debug_port");
        System.out.println("[浏览器] 调试端口=" + debugPort);

        // ── 接入 Playwright (com.microsoft.playwright) ────────────────
        // Playwright pw = Playwright.create();
        // Browser browser = pw.chromium()
        //     .connectOverCDP("http://127.0.0.1:" + debugPort);
        // Page page = browser.contexts().get(0).newPage();
        // page.navigate("https://www.example.com");
        // System.out.println("[Playwright] 标题=" + page.title());

        // ── 关闭浏览器 ────────────────────────────────────────────────
        System.out.println("[关闭] 正在关闭浏览器...");
        post("/open/env/close", new JSONObject().put("code", envCode));
        System.out.println("[关闭] 完成");
    }
}
启元指纹浏览器开放平台 · 如有问题请联系技术支持