本页内容
创建并启动,停止后保留
可单独创建并保存档案,也可通过一个请求创建并启动云浏览器。source 区分 manual 和 launch 来源;两种档案停止后均保留配置,可查询、再次启动或显式删除,与临时 /cdp/sessions 分开管理。API Key 每次启动须携带自定义代理;starting/running/stopping 共用用户运行额度。确认停止释放运行额度,保存数量不减少。
POST /cloud-browsers/launch 创建档案并等待 running 后返回 201。runtime.connectUrl 可直接打开交互界面,Location 则是详情 API 地址。关闭查看器不会停止计费。每次 launch 都新建档案,无幂等键;失败时查询返回的 id,并有界重试停止,不能自动重复 launch。
打开交互式云浏览器
runtime.status 为 starting、running、stopping 或 stopped;starting/stopping 仍占额度。runtimeKind 为 neko 或 worker_cdp。活动会话带 sessionId、expiresAt;只有 running 才可能带 connectUrl,可直接打开对应实例的交互界面,需使用档案所有者账号登录。neko 链接指向 API 域 /cloud-browser-runtime/{sessionId}/,不返回 cdpBaseUrl;固定 usr/pwd 参数是公共查看器协议值,访问权限仍由会话 Cookie 校验,不使用只读 cast 模式。worker_cdp 使用 CDP Studio,可返回带临时令牌的 cdpBaseUrl。请使用返回地址,勿自行拼接或向 URL 添加 API Key、Cookie、代理凭据。地址缺失时先查询真实状态。
认证与资源归属
列表、创建、创建并启动、详情、启动和关闭支持 X-API-Key: <API_KEY> 或 Authorization: Bearer <SESSION_JWT>,也支持会话 Cookie。Bearer 必须是登录会话 JWT,不能填写 API Key。只能操作认证用户自己的资源;PATCH、DELETE 配置、查看器和 join-token 仍仅支持会话认证。
会话认证启动还必须传 apiKeyId,指定同一用户拥有且有效、未过期的 API Key。X-API-Key 会自动选择该 Key;若同时传 apiKeyId,必须一致。不要把 API Key 或代理凭据放入前端代码、URL 或日志;所有示例均使用占位凭据。
JSON 响应包含 traceId,响应头 X-Trace-Id 也提供同一追踪标识。错误包含 error,部分包含 code;请结合 HTTP 状态与稳定的 code 处理错误。
API 与页面的代理规则
使用 X-API-Key 时,每次启动请求都必须在顶层显式传入有效 proxy 对象,即使创建时已保存代理也不能省略。仅传 countryCode 或 source=web 不能替代代理。会话认证(包括 JWT Bearer)下,页面可使用有效自定义代理,或明确选择 countryCode(两位地区码,GLOBAL 表示随机地区);会话启动可复用已保存的明确选择。两个入口都不允许无代理运行。
proxy.server 必须是 http:// 或 socks5:// URL,显式包含 1–65535 端口,不能内嵌凭据、路径、查询参数或片段;也支持 protocol + host + port 拆分格式。无认证代理同时省略 username 和 password,需要认证时两者都必须非空。空代理或非法代理会被拒绝。proxy 和 countryCode 不能同传,否则返回 400 COUNTRY_PROXY_CONFLICT。启动覆盖只影响本次运行,不修改保存配置。
动态代理分配失败会拒绝启动,自定义代理失败同样不会回退直连。请修复代理,或待服务恢复后重试;不要通过移除代理绕过错误。
curl --fail-with-body -sS -X POST "https://api.adscrawl.net/cloud-browsers/<CLOUD_BROWSER_ID>/start" \
-H "Authorization: Bearer <SESSION_JWT>" \
-H "Content-Type: application/json" \
-d '{"apiKeyId":"<API_KEY_ID>","countryCode":"GLOBAL"}'保存数量与运行额度
GET /cloud-browsers 返回 limit(可保存配置数)、runningLimit(当前用户同时运行上限)和 runningCount(该用户所有 starting、running、stopping 云浏览器会话数,跨分页、跨 API Key 统计)。已保存但未运行的配置不占运行名额。页面和 API 共用运行额度,临时 Remote CDP 会话另行计算。
用户运行额度默认 1。未配置(NULL)或负数按 1 处理;0 禁止新启动;正整数表示上限。额度实时读取、无缓存。下调不会主动关闭现有会话,只会限制后续启动,直到有可用名额。启动时原子预占,启动失败、关闭完成或异常回收后释放;stopping 仍占用名额。
超过运行额度返回 409 CLOUD_BROWSER_CONCURRENCY_LIMIT;保存配置数达到上限则返回 409 Cloud Browser limit reached,两者不同。启动仍要求付费套餐且余额至少 1 credit。云浏览器从成功启动到停止按已开始的分钟计费,每分钟 1 credit,不足一分钟按一分钟计算;重复停止通知不会重复计费。
提高用户额度不会同时提高每 API Key 的 CDP 上限或全局运行容量;仍可能遇到 429 CDP sessions per API key limit reached 或 503 CDP session capacity exhausted。
创建 → 启动 → 查询 → 关闭
创建仅保存配置并返回 id。启动需单独请求,同步等待运行时确认后才返回 200 running。查询时按响应原样展示 runtime.status:starting → running → stopping → stopped。关闭的 202 表示尚未完成,应轮询详情直到 stopped。对已活动的配置重复启动返回 409;对已停止的配置重复关闭返回 200,runtime.status=stopped。
以下流程需要 bash、curl 和 jq。请替换为自己的测试凭据及可达代理。轮询最多等待约两分钟;超时不代表实例已关闭,请保留配置 id,按需再次查询或关闭。下方 JSON 为响应结构示例,并非在线接口执行结果。
set -euo pipefail
export ADSCRAWL_API_KEY="<API_KEY>"
API_BASE="https://api.adscrawl.net"
# 1. Save a profile; this does not start a browser.
created=$(curl --fail-with-body -sS -X POST "$API_BASE/cloud-browsers" \
-H "X-API-Key: $ADSCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"remark":"API example","browserSettings":{"viewport":{"width":1440,"height":900}}}')
CLOUD_BROWSER_ID=$(printf '%s' "$created" | jq -er '.id')
# 2. Send proxy again on EVERY start. Replace placeholder credentials.
curl --fail-with-body -sS -X POST "$API_BASE/cloud-browsers/$CLOUD_BROWSER_ID/start" \
-H "X-API-Key: $ADSCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"proxy":{"server":"http://proxy.example.com:8080","username":"<PROXY_USERNAME>","password":"<PROXY_PASSWORD>"}}'
# 3. Read the actual state, with a bounded wait for running/stopped.
wait_for_state() {
local expected="$1" state attempt
for attempt in {1..60}; do
state=$(curl --fail-with-body -sS "$API_BASE/cloud-browsers/$CLOUD_BROWSER_ID" \
-H "X-API-Key: $ADSCRAWL_API_KEY" | jq -er '.runtime.status') || return 1
printf 'runtime.status=%s\n' "$state"
if [ "$state" = "$expected" ]; then return 0; fi
case "$state" in
starting|running|stopping|stopped) ;;
*) return 1 ;;
esac
if [ "$expected" = running ] && [ "$state" != starting ]; then return 1; fi
sleep 2
done
return 1
}
if ! wait_for_state running; then
printf '%s\n' 'Browser not ready; requesting stop for cleanup.' >&2
fi
# 4. Inspect account-wide limits (not just the current page).
curl --fail-with-body -sS "$API_BASE/cloud-browsers?page=1&pageSize=10" \
-H "X-API-Key: $ADSCRAWL_API_KEY" | jq '{limit,runningLimit,runningCount}'
# 5. A 202 response means stopping, not stopped. Confirm via detail.
curl --fail-with-body -sS -X POST "$API_BASE/cloud-browsers/$CLOUD_BROWSER_ID/stop" \
-H "X-API-Key: $ADSCRAWL_API_KEY"
wait_for_state stopped/cloud-browsers云浏览器列表与额度
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
查询参数
| 字段 | 类型 | 说明 |
|---|---|---|
page | integer | 默认 1,最大 10000;非法值或非正数使用默认值。 |
pageSize | integer | 默认且最大 10;非法值或非正数使用默认值。 |
响应
- 200
application/jsonlimit 是套餐允许保存的档案数量;runningLimit 是用户同时运行上限;runningCount 统计该用户所有档案的 starting、running、stopping,会跨分页、API Key 和页面共享,不包含临时 /cdp/sessions。users.cloud_browser_running_limit 为 NULL 或负数时默认 1,0 禁止新启动,正数为上限。列表和每次启动实时读取;下调不会主动关闭已有实例。全局容量仍单独限制,不叠加临时 CDP 的每 Key 并发限制。- 200
application/jsonruntime.status 为 starting、running、stopping 或 stopped;starting/stopping 仍占额度。runtimeKind 为 neko 或 worker_cdp。活动会话带 sessionId、expiresAt;只有 running 才可能带 connectUrl,可直接打开对应实例的交互界面,需使用档案所有者账号登录。neko 链接指向 API 域 /cloud-browser-runtime/{sessionId}/,不返回 cdpBaseUrl;固定 usr/pwd 参数是公共查看器协议值,访问权限仍由会话 Cookie 校验,不使用只读 cast 模式。worker_cdp 使用 CDP Studio,可返回带临时令牌的 cdpBaseUrl。请使用返回地址,勿自行拼接或向 URL 添加 API Key、Cookie、代理凭据。地址缺失时先查询真实状态。- 401
application/json鉴权缺失、无效或已过期。- 503
application/jsonCDP_WORKER_UNAVAILABLE,或无 code 的 Cloud browser runtime is unavailable。原节点记录丢失、bootId 改变或暂时失联都不能证明已停止;保留会话和运行额度,连接地址可能省略。- 500
application/jsonInternal error:服务内部错误。
请求示例
curl --fail-with-body --silent --show-error --max-time 65 \
-X GET 'https://api.adscrawl.net/cloud-browsers?page=1&pageSize=10' \
-H 'x-api-key: <api-key>'响应示例
{
"ok": true,
"data": [
{
"id": "<browser-id>",
"source": "manual",
"deleteOnStop": false,
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
},
"proxyDisplayIp": null,
"proxyDisplayRegion": null,
"lastOpenedAt": null,
"updatedAt": "2026-09-07T08:00:00.000Z",
"runtime": {
"runtimeKind": "neko",
"status": "stopped"
}
}
],
"pagination": {
"page": 1,
"pageSize": 10,
"total": 1,
"totalPages": 1
},
"limit": 10,
"runningLimit": 1,
"runningCount": 0
}/cloud-browsers创建云浏览器配置
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
content-type必填 | application/json | 请求体为一个 JSON 对象,最大 1 MiB。 |
请求体
| 字段 | 类型 | 说明 |
|---|---|---|
remark | string | 可选备注;trim 后最多 255 个 Unicode 字符。 |
browserSettings | object | 可选持久配置,例如 viewport、locale、timezoneId、proxy 或 countryCode、cookies 和 fingerprint。省略时为 {},传入时必须为对象。创建仅保存配置,不启动实例;保存代理也不能替代 API Key 下次启动时的顶层 proxy。预置 cookies 须为数组,服务端加密保存,所有者读取时回填。 |
响应
- 201
application/json返回 {ok: true, id},档案处于 stopped,未占运行额度。免费套餐最多保存 1 个档案;实际保存上限见列表 limit。完整流程示例见请求示例的 Node.js 标签。- 400
application/json空 body、null、数组、标量或非法字段类型;remark 超长、Invalid cookies、INVALID_PROXY、INVALID_COUNTRY_CODE 或 COUNTRY_PROXY_CONFLICT。{} 是有效创建请求。- 401
application/json鉴权缺失、无效或已过期。- 409
application/jsonCloud Browser limit reached:已达保存数量 limit,无 code;与运行额度错误不同。- 500
application/jsonInternal error:服务内部错误。
请求示例
curl --fail-with-body --silent --show-error --max-time 65 \
-X POST 'https://api.adscrawl.net/cloud-browsers' \
-H 'x-api-key: <api-key>' \
-H 'content-type: application/json' \
--data '{
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
}
}'{
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
}
}// Node.js 20+, save as .mjs. Replace proxy placeholders before running.
const baseUrl = "https://api.adscrawl.net";
const apiKey = process.env.ADSCRAWL_API_KEY;
if (!apiKey) throw new Error("ADSCRAWL_API_KEY is required");
const proxy = {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
};
async function request(method, path, body, timeoutMs = 65000) {
const res = await fetch(baseUrl + path, {
method,
headers: { "x-api-key": apiKey, "content-type": "application/json" },
body: body === undefined ? undefined : JSON.stringify(body),
signal: AbortSignal.timeout(timeoutMs),
});
const data = await res.json();
if (!res.ok) {
const error = new Error(data.error || "HTTP " + res.status);
error.status = res.status;
error.code = data.code;
error.id = data.id;
throw error;
}
return data;
}
async function stopAndWait(id) {
const path = "/cloud-browsers/" + encodeURIComponent(id);
// At most 30 attempts, 2 seconds apart; each request times out after 10 seconds.
for (let attempt = 0; attempt < 30; attempt++) {
try {
const stopped = await request("POST", path + "/stop", undefined, 10000);
if (stopped.runtime.status === "stopped") return;
const current = await request("GET", path, undefined, 10000);
if (current.runtime.status === "stopped") return;
} catch (error) {
if (error.code !== "CDP_SESSION_STARTING" &&
!(error.status >= 500) && error.name !== "TimeoutError") throw error;
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
throw new Error("Stop unconfirmed; quota is still reserved. Retry stop for " + id);
}
const { id } = await request("POST", "/cloud-browsers", {
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
}
});
try {
// Include a valid proxy again on EVERY start, even for an existing profile.
await request("POST", "/cloud-browsers/" + encodeURIComponent(id) + "/start", { proxy });
const current = await request("GET", "/cloud-browsers/" + encodeURIComponent(id));
console.log({ id, source: current.source, status: current.runtime.status, connectUrl: current.runtime.connectUrl });
// Open connectUrl in a browser signed in as the profile owner before continuing.
const { limit, runningLimit, runningCount } = await request("GET", "/cloud-browsers");
console.log({ limit, runningLimit, runningCount });
} finally {
// Also attempt cleanup after a failed start: a runtime may still need recovery.
await stopAndWait(id);
}
console.log("Stopped; the saved profile remains", id);响应示例
{
"ok": true,
"id": "<browser-id>"
}/cloud-browsers/launch创建并启动云浏览器
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
content-type必填 | application/json | 请求体为一个 JSON 对象,最大 1 MiB。 |
请求体
| 字段 | 类型 | 说明 |
|---|---|---|
proxy必填 | object | 所有鉴权方式每次必传。 API Key 每次启动必须显式传顶层有效 proxy;历史 browserSettings.proxy、上次运行代理、countryCode 或伪造 source 都不能替代。仅接受 http 或 socks5:{server: "http://proxy.example.com:8080"} 或 {protocol: "socks5", host: "proxy.example.com", port: 1080}。端口为 1-65535 的整数或整数字符串;server 必须含端口,不含 URL 凭据、查询或片段,不能同时传 host。username/password 可选但须成对非空字符串,不能写在 URL 内。代理失败不得回退直连。 |
tabs | (string | {url: string, active?: boolean})[] | 默认 [],不注入标签页,保留 Runtime 初始页面。最多 8 项;仅 HTTP(S) URL,每项最多 16384 bytes,禁止 URL 凭据、控制字符或首尾空白。active 默认 false,最多一个 true;未指定活动项时激活第一项。 |
cookies | cookie[] | 默认 [],无预置 Cookie。最多 10000 条,整个请求最大 1 MiB。name/domain 为非空 string;value 为 string,默认空;path 默认 /;secure/httpOnly/session 为 boolean;expires 为 Unix 秒;sameSite 为 Strict/Lax/None。支持已有 Cookie 快照兼容字段;过滤过期项,拒绝未知字段和非法类型。Cookie 独立加密保存,所有者可读取。 |
fingerprint | object | 默认 webRtc=forward,其余 webGl、webGpu、webGlImage、canvas、audioContext、clientRects、speechVoices、fonts、hardware、doNotTrack 均为 random。部分传入时补齐默认值;字段允许值与组合限制同启动接口。hardwareConcurrency/deviceMemory 可选整数 1-64,运行 seed 由服务端生成。 |
apiKeyId会话/Bearer 鉴权时 | string (UUID) | 会话/Bearer 需指定本人有效 Key;API Key 鉴权时自动使用当前 Key,若传入必须匹配。 |
响应
- 201
application/json返回 {ok: true, id, source: launch, deleteOnStop: false, runtime} 与 Location: /cloud-browsers/<id>,仅确认 running 后成功。runtime.connectUrl 是可直接打开的交互界面链接;Location 是查询接口地址。source 仅区分来源。手动停止、到期停止或启动失败确认回收后,保留档案配置及 Cookie/标签快照,仍计入保存额度,可查询、再次启动或显式删除。关闭查看器不会停止浏览器。- 201
application/jsonruntime.status 为 starting、running、stopping 或 stopped;starting/stopping 仍占额度。runtimeKind 为 neko 或 worker_cdp。活动会话带 sessionId、expiresAt;只有 running 才可能带 connectUrl,可直接打开对应实例的交互界面,需使用档案所有者账号登录。neko 链接指向 API 域 /cloud-browser-runtime/{sessionId}/,不返回 cdpBaseUrl;固定 usr/pwd 参数是公共查看器协议值,访问权限仍由会话 Cookie 校验,不使用只读 cast 模式。worker_cdp 使用 CDP Studio,可返回带临时令牌的 cdpBaseUrl。请使用返回地址,勿自行拼接或向 URL 添加 API Key、Cookie、代理凭据。地址缺失时先查询真实状态。- 201
application/json沿用付费套餐、保存 limit、用户 runningLimit 和全局容量,starting/running/stopping 占运行额度。成功启动到确认停止每开始分钟 1 credit。确认 stopped 后释放运行额度;保存数量不减少,显式 DELETE /cloud-browsers/{id} 才删除档案。此接口仅支持已启用的 Cloud Runtime。- 400
application/jsonPROXY_REQUIRED、INVALID_PROXY、INVALID_TABS、INVALID_COOKIES、INVALID_FINGERPRINT_SETTINGS。显式 null、未知字段(含 countryCode/source/browserSettings)、非法 JSON 或类型不匹配均被拒绝;不创建档案。- 401
application/json鉴权缺失、无效或已过期。- 402
application/jsonPAID_PLAN_REQUIRED 或 INSUFFICIENT_CREDITS;不创建档案。- 403
application/json所选 Key 越权或与认证 Key 不匹配;不创建档案。- 409
application/jsonCloud Browser limit reached:保存数量满,不创建。CLOUD_BROWSER_CONCURRENCY_LIMIT:运行额度满或为 0;若已创建档案,响应附 id、source: launch、deleteOnStop: false、deleted: false 与真实 runtime,档案保留。- 502/503/504/500
application/json沿用启动接口错误码和容量重试字段。档案创建后的错误附 id、runtime 与 Location;已预留时含 sessionId。未确认回收时仍为 stopping 并占额度。Cloud Runtime 未启用返回 503,不转发 Worker。启动等待 60 秒,回收确认可能额外等待至多 120 秒。- 502/503/504/500
application/json每次调用创建新档案,无幂等键;不要自动重发 launch。错误返回 id 时先查询并有界重试同一 stop,直到 stopped。档案保留,deleted: false;未确认回收时还继续占运行额度。完全丢失响应时先核对列表与额度;不能假定未创建或已停止。
请求示例
curl --fail-with-body --silent --show-error --max-time 200 \
-X POST 'https://api.adscrawl.net/cloud-browsers/launch' \
-H 'x-api-key: <api-key>' \
-H 'content-type: application/json' \
--data '{
"proxy": {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
},
"tabs": [
"https://example.com"
],
"cookies": [
{
"name": "sid",
"value": "<cookie-value>",
"domain": "example.com",
"path": "/",
"secure": true
}
],
"fingerprint": {
"canvas": "real"
}
}'{
"proxy": {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
},
"tabs": [
"https://example.com"
],
"cookies": [
{
"name": "sid",
"value": "<cookie-value>",
"domain": "example.com",
"path": "/",
"secure": true
}
],
"fingerprint": {
"canvas": "real"
}
}{
"proxy": {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
}
}// Node.js 20+, save as .mjs. Replace proxy placeholders before running.
const baseUrl = "https://api.adscrawl.net";
const apiKey = process.env.ADSCRAWL_API_KEY;
if (!apiKey) throw new Error("ADSCRAWL_API_KEY is required");
const proxy = {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
};
async function request(method, path, body, timeoutMs = 65000) {
const res = await fetch(baseUrl + path, {
method,
headers: { "x-api-key": apiKey, "content-type": "application/json" },
body: body === undefined ? undefined : JSON.stringify(body),
signal: AbortSignal.timeout(timeoutMs),
});
const data = await res.json();
if (!res.ok) {
const error = new Error(data.error || "HTTP " + res.status);
error.status = res.status;
error.code = data.code;
error.id = data.id;
throw error;
}
return data;
}
async function stopAndWait(id) {
const path = "/cloud-browsers/" + encodeURIComponent(id);
// At most 30 attempts, 2 seconds apart; each request times out after 10 seconds.
for (let attempt = 0; attempt < 30; attempt++) {
try {
const stopped = await request("POST", path + "/stop", undefined, 10000);
if (stopped.runtime.status === "stopped") return;
const current = await request("GET", path, undefined, 10000);
if (current.runtime.status === "stopped") return;
} catch (error) {
if (error.code !== "CDP_SESSION_STARTING" &&
!(error.status >= 500) && error.name !== "TimeoutError") throw error;
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
throw new Error("Stop unconfirmed; quota is still reserved. Retry stop for " + id);
}
let id;
try {
// One call creates AND starts. Never automatically repeat this POST.
const launched = await request("POST", "/cloud-browsers/launch", {
proxy,
tabs: ["https://example.com"],
// cookies and fingerprint omitted: use their defaults.
}, 195000);
id = launched.id;
const current = await request("GET", "/cloud-browsers/" + encodeURIComponent(id));
console.log({ id, status: current.runtime.status });
} catch (error) {
id = id || error.id;
if (!id) console.error("No profile id received; inspect /cloud-browsers before retrying launch.");
throw error;
} finally {
// Errors after profile creation also return id; unconfirmed cleanup reserves quota.
if (id) await stopAndWait(id);
}
console.log("Stopped; the saved profile remains", id);响应示例
{
"ok": true,
"id": "<browser-id>",
"source": "launch",
"deleteOnStop": false,
"runtime": {
"runtimeKind": "neko",
"status": "running",
"sessionId": "<session-id>",
"expiresAt": "2026-09-07T09:00:00.000Z",
"connectUrl": "https://api.adscrawl.net/cloud-browser-runtime/<session-id>/?usr=adscrawl&pwd=adscrawl"
}
}{
"error": "Cloud browser runtime request timed out",
"code": "CLOUD_RUNTIME_TIMEOUT",
"id": "<browser-id>",
"source": "launch",
"deleteOnStop": false,
"deleted": false,
"runtime": {
"runtimeKind": "neko",
"status": "stopping",
"sessionId": "<session-id>",
"expiresAt": "2026-09-07T09:00:00.000Z"
}
}/cloud-browsers/{id}查询云浏览器状态
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
id必填 | string (UUID) | 创建或列表返回的持久化云浏览器 id,不是运行时 sessionId。 |
响应
- 200
application/json直接返回档案对象,不包裹 data 或 ok。包括 id、remark、browserSettings、proxyDisplayIp/Region(可为 null)、lastOpenedAt(可为 null)、updatedAt 和 runtime。代理凭据从响应中移除;所有者可读取已保存的 cookies。- 200
application/jsonruntime.status 为 starting、running、stopping 或 stopped;starting/stopping 仍占额度。runtimeKind 为 neko 或 worker_cdp。活动会话带 sessionId、expiresAt;只有 running 才可能带 connectUrl,可直接打开对应实例的交互界面,需使用档案所有者账号登录。neko 链接指向 API 域 /cloud-browser-runtime/{sessionId}/,不返回 cdpBaseUrl;固定 usr/pwd 参数是公共查看器协议值,访问权限仍由会话 Cookie 校验,不使用只读 cast 模式。worker_cdp 使用 CDP Studio,可返回带临时令牌的 cdpBaseUrl。请使用返回地址,勿自行拼接或向 URL 添加 API Key、Cookie、代理凭据。地址缺失时先查询真实状态。- 200
application/jsonsource 为 manual 或 launch;launch 表示创建并启动接口来源,不是删除策略。旧 deleteOnStop 标记由后端兼容处理,现返回 false;停止后配置、快照和来源继续保留,仍占保存额度。历史已删除记录不会恢复,可能返回 deleted: true、stopped 和空配置;仅真正删除的记录不在列表中。- 401
application/json鉴权缺失、无效或已过期。- 404
application/json档案不存在或不属于当前用户。- 503
application/jsonCDP_WORKER_UNAVAILABLE,或无 code 的 Cloud browser runtime is unavailable。原节点记录丢失、bootId 改变或暂时失联都不能证明已停止;保留会话和运行额度,连接地址可能省略。- 500
application/jsonInternal error:服务内部错误。
请求示例
curl --fail-with-body --silent --show-error --max-time 65 \
-X GET 'https://api.adscrawl.net/cloud-browsers/<browser-id>' \
-H 'x-api-key: <api-key>'响应示例
{
"id": "<browser-id>",
"source": "manual",
"deleteOnStop": false,
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
},
"proxyDisplayIp": null,
"proxyDisplayRegion": null,
"lastOpenedAt": null,
"updatedAt": "2026-09-07T08:00:00.000Z",
"runtime": {
"runtimeKind": "neko",
"status": "stopped"
}
}{
"id": "<browser-id>",
"source": "manual",
"deleteOnStop": false,
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
},
"proxyDisplayIp": null,
"proxyDisplayRegion": null,
"lastOpenedAt": null,
"updatedAt": "2026-09-07T08:00:00.000Z",
"runtime": {
"runtimeKind": "neko",
"status": "stopping",
"sessionId": "<session-id>",
"expiresAt": "2026-09-07T09:00:00.000Z"
}
}{
"id": "<browser-id>",
"source": "launch",
"deleteOnStop": false,
"remark": "work profile",
"browserSettings": {
"viewport": {
"width": 1440,
"height": 900
}
},
"proxyDisplayIp": null,
"proxyDisplayRegion": null,
"lastOpenedAt": null,
"updatedAt": "2026-09-07T08:00:00.000Z",
"runtime": {
"runtimeKind": "neko",
"status": "stopped"
}
}/cloud-browsers/{id}/start启动云浏览器
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
content-type必填 | application/json | 请求体为一个 JSON 对象,最大 1 MiB。 |
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
id必填 | string (UUID) | 创建或列表返回的持久化云浏览器 id,不是运行时 sessionId。 |
请求体
| 字段 | 类型 | 说明 |
|---|---|---|
proxyAPI Key 鉴权时 | object | API Key 每次启动必须显式传顶层有效 proxy;历史 browserSettings.proxy、上次运行代理、countryCode 或伪造 source 都不能替代。仅接受 http 或 socks5:{server: "http://proxy.example.com:8080"} 或 {protocol: "socks5", host: "proxy.example.com", port: 1080}。端口为 1-65535 的整数或整数字符串;server 必须含端口,不含 URL 凭据、查询或片段,不能同时传 host。username/password 可选但须成对非空字符串,不能写在 URL 内。代理失败不得回退直连。 |
apiKeyId会话/Bearer 鉴权时 | string (UUID) | 页面会话/Bearer 鉴权必填,选择本人有效 Key。API Key 鉴权时自动使用当前 Key;若同时传 apiKeyId 必须与之相同。 |
countryCode | string (session/Bearer only) | 页面可明确选择 GLOBAL 或支持的二字地区码(例如 FR),优先同地区可信代理,不可用时动态代理兜底;空字符串不算选择。页面启动在合并保存配置与本次覆盖后也必须有 proxy 或非空 countryCode。API Key 不能用它替代 proxy;同次请求不得同时出现两者。本次选择会清除相反的已保存路由,仅作用于运行快照,不写回档案。 |
cookies | cookie[] | 可选本次运行覆盖,必须为数组;优先于保存快照,不写回档案配置。 |
fingerprint | object | 可选本次覆盖,按字段与保存设置合并。webRtc: forward|real|disabled(旧 random 转 forward);webGpu: random|real|disabled;doNotTrack: random|enabled|disabled;webGl、webGlImage、canvas、audioContext、clientRects、speechVoices、fonts、hardware: random|real。兼容 hardwareConcurrency/deviceMemory 整数 1-64;未知、非法或冲突组合返回 INVALID_FINGERPRINT_SETTINGS。 |
响应
- 200
application/json同步等待启动确认,只在 running 后返回 {ok: true, runtime},不会把 starting 当成功。需要有效付费套餐,成功启动至停止按已开始分钟计费,每分钟 1 credit,不足 1 分钟按 1 分钟。runtime 字段见查询接口;neko 不含 cdpBaseUrl。- 400
application/jsonPROXY_REQUIRED:缺少本次顶层 proxy;INVALID_PROXY:代理无效;COUNTRY_PROXY_CONFLICT:同次传 proxy/countryCode;INVALID_COUNTRY_CODE、INVALID_FINGERPRINT_SETTINGS、Invalid cookies。body/cookies/fingerprint 类型错误,或页面缺少 apiKeyId、选择的 Key 不存在/停用/过期也返回 400。- 401
application/json鉴权缺失、无效或已过期。- 402
application/jsonPAID_PLAN_REQUIRED:无有效付费套餐;INSUFFICIENT_CREDITS:余额不足 1 credit(附 balance、requiredCredits)。- 403
application/jsonapiKeyId 与认证 Key 不一致,或所选 Key 不属于当前用户。- 404
application/json档案不存在或不属于当前用户。- 409
application/jsonCLOUD_BROWSER_CONCURRENCY_LIMIT:用户额度已满或为 0。Browser is already running(无 code):该档案已有活动会话。 limit 是套餐允许保存的档案数量;runningLimit 是用户同时运行上限;runningCount 统计该用户所有档案的 starting、running、stopping,会跨分页、API Key 和页面共享,不包含临时 /cdp/sessions。users.cloud_browser_running_limit 为 NULL 或负数时默认 1,0 禁止新启动,正数为上限。列表和每次启动实时读取;下调不会主动关闭已有实例。全局容量仍单独限制,不叠加临时 CDP 的每 Key 并发限制。- 502
application/jsonCLOUD_RUNTIME_AUTH_FAILED、CLOUD_RUNTIME_NOT_FOUND、CLOUD_RUNTIME_HTTP_ERROR、CLOUD_RUNTIME_INVALID_RESPONSE 或 CLOUD_RUNTIME_CONTROLLER_FAILED:运行时拒绝或响应异常。- 503
application/jsonCLUSTER_NO_CAPACITY:在线节点无容量,附可空 nextAvailableAt、retryAfterMs;CDP session capacity exhausted(无 code):全局容量满。也可能是 DYNAMIC_PROXY_NOT_CONFIGURED、MANAGED_PROXY_UNAVAILABLE、CLOUD_RUNTIME_CONFIG_INVALID 或 CLOUD_RUNTIME_UNREACHABLE。代理失败不会直连;先查询档案状态再决定重试。- 503
application/jsonCDP_WORKER_UNAVAILABLE,或无 code 的 Cloud browser runtime is unavailable。原节点记录丢失、bootId 改变或暂时失联都不能证明已停止;保留会话和运行额度,连接地址可能省略。- 504
application/jsonCLOUD_RUNTIME_TIMEOUT:启动超时不代表实例不存在;查询状态,必要时重试停止。未确认回收时保留 stopping 和额度。- 500
application/jsonInternal error:服务内部错误。
请求示例
curl --fail-with-body --silent --show-error --max-time 65 \
-X POST 'https://api.adscrawl.net/cloud-browsers/<browser-id>/start' \
-H 'x-api-key: <api-key>' \
-H 'content-type: application/json' \
--data '{
"proxy": {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
}
}'{
"proxy": {
"server": "http://proxy.example.com:8080",
"username": "<proxy-user>",
"password": "<proxy-password>"
}
}{
"proxy": {
"protocol": "socks5",
"host": "proxy.example.com",
"port": 1080,
"username": "<proxy-user>",
"password": "<proxy-password>"
}
}curl --fail-with-body --silent --show-error --max-time 65 \
'https://api.adscrawl.net/cloud-browsers/<browser-id>/start' \
-H 'Authorization: Bearer <access-token>' \
-H 'content-type: application/json' \
--data '{
"apiKeyId": "<api-key-id>",
"countryCode": "GLOBAL"
}'响应示例
{
"ok": true,
"runtime": {
"runtimeKind": "neko",
"status": "running",
"sessionId": "<session-id>",
"expiresAt": "2026-09-07T09:00:00.000Z",
"connectUrl": "https://api.adscrawl.net/cloud-browser-runtime/<session-id>/?usr=adscrawl&pwd=adscrawl"
}
}{
"error": "API key starts require an explicit proxy in every request",
"code": "PROXY_REQUIRED"
}{
"error": "Cloud browser running limit reached",
"code": "CLOUD_BROWSER_CONCURRENCY_LIMIT"
}{
"error": "Cloud browser cluster has no available capacity",
"code": "CLUSTER_NO_CAPACITY",
"nextAvailableAt": null,
"retryAfterMs": null
}/cloud-browsers/{id}/stop停止云浏览器
请求
请求头
| 字段 | 类型 | 说明 |
|---|---|---|
x-api-keyAPI Key 鉴权时 | string | API 调用使用完整 API Key。这些接口也接受页面会话 Cookie 或 Authorization: Bearer <access-token>;任选一种鉴权方式。资源按用户归属隔离。 |
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
id必填 | string (UUID) | 创建或列表返回的持久化云浏览器 id,不是运行时 sessionId。 |
响应
- 200
application/jsonruntime.status=stopped:已确认停止或本来就无活动会话,释放运行额度。manual 和 launch 档案均保留配置、快照和来源,继续占保存额度;可再次启动,只有显式删除才删档。重复停止仍返回 stopped,不重复计费。source 标识来源,deleteOnStop 为 false;历史已删除记录才返回 deleted: true。无活动会话时省略 sessionId。- 202
application/jsonruntime.status=stopping:另一个停止请求正在执行,尚未完成,仍占运行额度。继续 GET 详情做有界轮询;如一直 stopping,可重试同一 stop,直到确认 stopped。创建接口的 Node.js 完整流程含轮询和重试示例。- 401
application/json鉴权缺失、无效或已过期。- 404
application/json档案不存在或不属于当前用户。- 409
application/jsonCDP_SESSION_STARTING:启动尚未完成,等待后重试停止。- 503
application/jsonCDP_WORKER_UNAVAILABLE,或无 code 的 Cloud browser runtime is unavailable。原节点记录丢失、bootId 改变或暂时失联都不能证明已停止;保留会话和运行额度,连接地址可能省略。- 500
application/jsonInternal error:停止失败或超时不能当作成功。会话仍可能 stopping 并占额度;先查询,修复可达性后重试 stop。原节点身份丢失时不能改向新节点删除或手工伪造 stopped 释放额度。
请求示例
curl --fail-with-body --silent --show-error --max-time 65 \
-X POST 'https://api.adscrawl.net/cloud-browsers/<browser-id>/stop' \
-H 'x-api-key: <api-key>'响应示例
{
"ok": true,
"runtime": {
"status": "stopped",
"sessionId": "<session-id>"
}
}{
"ok": true,
"runtime": {
"status": "stopping",
"sessionId": "<session-id>"
}
}{
"error": "CDP session is starting; retry after startup completes",
"code": "CDP_SESSION_STARTING"
}{
"error": "Cloud browser runtime is unavailable"
}{
"ok": true,
"source": "launch",
"deleteOnStop": false,
"runtime": {
"status": "stopped",
"sessionId": "<session-id>"
}
}