01概览

chromebot 为 AI agent 提供可自动启停、抗风控的浏览器实例。每个实例 = 一个固定身份 + 独立指纹 + 持久 profile 卷 + 自带代理,身份跨重启稳定

两种用法:

基址

用途地址
REST APIhttps://at.ci/v1/...
CDP 网关wss://at.ci/cdp/{id}?token=...
控制台https://at.ci/app
约定:id 为 32 位十六进制;tokencb_ 前缀 opaque 串,明文仅签发时返回一次,服务端只存 SHA-256。

02快速开始

1 · 登录拿 token

浏览器打开 https://at.ci 点「用 GitHub 登录」,成功后跳 /app 并种 httponly cookie。右上「API token → 重新生成」复制明文 cb_...(只显示一次,旧 API token 立即失效,不影响登录会话)。

2 · 创建实例

curl -s https://at.ci/v1/instances \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"my-account-1","locale":"en-US","tz":"America/New_York"}'

3 · 启动,拿 CDP 端点

curl -s -X POST https://at.ci/v1/instances/$ID/start \
  -H "Authorization: Bearer $TOKEN"
# → {"status":"running","cdp_endpoint":"wss://at.ci/cdp/...?token=...","cdp_token":"cb_..."}

cdp_endpoint 已含 token,只返回一次;stop 后失效,running 时再调 start 会轮换。

4 · 驱动

from patchright.async_api import async_playwright
async with async_playwright() as pw:
    b = await pw.chromium.connect_over_cdp(CDP_ENDPOINT)
    pg = b.contexts[0].pages[0]
    await pg.goto("https://abrahamjuliot.github.io/creepjs/")
    await b.close()   # 只断开 CDP,实例继续运行

5 · 停止 / 删除

POST /stop 保留身份与 profile;DELETE 永久销毁卷,不可恢复

03鉴权

两条等价路径落到同一用户:

解析顺序:Authorization 头,无则回落 cookie。都没有或无效 → 401 invalid or missing token

登录会话与 API token 相互独立:POST /v1/token/regenerate 只轮换 API token(旧 API token 立即失效),不影响登录会话(不会把你登出);重新登录也不动 API token。每用户同时只有一个有效 API token,服务端只存 sha256(token),丢了再 regenerate;登录会话则可多设备同时有效。

凭据前缀 / 形态用途有效期
登录会话 cookie签名串浏览器 UI 调 /v1/*30 天,滑动续期;多设备并存
账户 API tokencb_编程调所有 /v1/*长期,至下次 regenerate
实例 CDP tokencb_仅连 /cdp/{id}start 返回一次;stop 即失效;再 start 轮换

04API · 账户

GET/v1/me

当前用户与配额 → 200 {login, email, instances_used, instances_max}(email 可能为 null,instances_max 默认 10)。

POST/v1/token/regenerate

无请求体。签发新明文 token,旧的立即失效 → 200 {"token":"cb_..."}(明文仅一次)。未鉴权 → 401。

05API · 实例

两种投影:Summary(id, name, status, platform, locale, tz, proxy_set, pending_restart, health_check, extensions_count, updated_at)、Detail(Summary + container_name, cdp_endpoint, fingerprint_committed, extensions[], mem_rss_bytes, cpu_pct, last_started_at, last_error)。

statuscreated · starting · running · stopping · stopped · error · deleting

POST/v1/instances

创建实例(不启动)→ 201 Summary。

字段类型说明
namestring 必填1–128 字符
platformstring默认 windows(MVP 仅此)
localestring?en-US,留空用 profile 默认
tzstring?IANA,如 America/New_York
proxystring?scheme 须 socks5/socks5h/http/https
health_checkbool浏览器存活检测,默认 true,见 存活检测

错误:429 配额满、422 校验失败。插件在创建后经插件 API 上传。

GET/v1/instances

列出本人实例 → 200 Summary[]。

GET/v1/instances/{id}

详情 → 200 Detail(running 时附 cdp_endpoint(不含 token)、mem_rss_bytescpu_pct)。404 = 不存在或越权(不暴露他人实例)。

DELETE/v1/instances/{id}

停 + 删容器 + 销毁 profile 卷 + 删记录,不可恢复200 {"status":"deleted"}

06API · 生命周期 & 代理

POST/v1/instances/{id}/start

created/stopped/error 起容器、首启固化身份、签发新 cdp_token 转 running;对已 running 再调幂等,不重启容器、只轮换 cdp_token → 200 {id, status:running, cdp_endpoint, cdp_token}(明文仅一次)。错误:409 cannot start from status=...500 start failed(转 error)。

POST/v1/instances/{id}/stop

停容器转 stopped、清除 cdp_token(已建 CDP 连接失效),身份 / profile 保留可再 start。对 stopped/created 幂等 → 200 {status:stopped}

PUT/v1/instances/{id}/proxy

请求体 {"proxy":"socks5://user:pass@host:1080"}{"proxy":null} 清除。代理进程级:running 改不热生效,需下次 start(此时 pending_restart=true)。scheme 非法 → 422 → 200 {proxy_set, pending_restart}

07API · 插件

为实例挂自定义浏览器插件:上传 .zip(仅 Manifest V3),解压后挂进该实例的 Chromium。每实例独立、随 profile 卷持久,改动下次 start 生效(running 时置 pending_restart,同代理语义)。可在创建弹窗直接选文件,或事后调本 API。

POST/v1/instances/{id}/extensions

multipart/form-data,字段名 files,可一次多个 .zip。逐个安全解压校验落卷 → 200 {installed:[{slug,name,version}], errors:[{filename,error}], extensions:[…], pending_restart}。全部失败 → 400

curl -s -X POST https://at.ci/v1/instances/$ID/extensions \
  -H "Authorization: Bearer $TOKEN" \
  -F 'files=@adblock.zip' -F 'files=@my-ext.zip'
GET/v1/instances/{id}/extensions

列出已装插件 → 200 [{slug,name,version}]

DELETE/v1/instances/{id}/extensions/{slug}

删除一个插件 → 200 {slug, removed:true, pending_restart}404 = 无此插件。

约束

抗检测提示:装插件会增加指纹暴露面(web_accessible_resources 可被探测),按需使用。

08存活检测

创建时开关 health_check(默认 ),让实例自动发现浏览器崩溃 / 卡死。两层协作:

所以:开检测能捕获浏览器级死亡(崩溃/卡死);关检测仍能捕获容器级死亡(OOM/进程退出)。检测到后实例转 error,身份 / profile 不受影响,重新 POST /start 即原样恢复(检测不自动重启)。

health_check 为创建时设定;控制台卡片上以 💓 存活检测 标签标示,异常时红色卡片显示 last_error

09实时查看 (DevTools)

控制台卡片「查看 / 操作」用浏览器自带的 Chrome DevTools 前端(经控制面网关本地反代,不依赖外网),打开即看到实例真实画面并直接操作,Elements / Console / Network 全功能。

GET/v1/instances/{id}/devtools

为 running 实例返回一次性可打开的 DevTools URL → 200 {url, target_id, title}。会轮换 CDP token 并内嵌进回连 ws(与 start 幂等轮换一致)。非 running → 409

前端与控制面同源同 scheme,无混合内容;版本随容器 Chromium 必然匹配;token 不外泄第三方。编程驱动仍走 CDP 网关

10CDP 驱动 (patchright)

CDP 网关是实例唯一对外暴露点。用 start 返回的 cdp_endpoint(已含 ?token=)直喂 connect_over_cdp,网关校验 token + 确认 running + 双向转发到容器内真实 Chrome。

import asyncio
from patchright.async_api import async_playwright

CDP = "wss://at.ci/cdp/<id>?token=<cdp_token>"

async def main():
    async with async_playwright() as pw:
        browser = await pw.chromium.connect_over_cdp(CDP)
        ctx = browser.contexts[0]
        page = ctx.pages[0] if ctx.pages else await ctx.new_page()
        await page.goto("https://example.com")
        print(await page.title())
        await browser.close()   # 仅断开 CDP,不停实例

asyncio.run(main())

注意

WS 关闭码

含义
4401token 无效 / 越权
4409实例非 running
4404容器无 IP
4502上游连接失败

11代理设置

每实例绑一个独立出口代理,凭据 Fernet 密文落库,API 永不回显明文,日志按 scheme://***:***@host:port 脱敏。

支持:socks5://socks5h://(远端解析 DNS,推荐)、http://https://(均可带或不带 user:pass),其余 → 422。

两种时机:创建时带 proxy,或事后 PUT /proxy。生效为进程级,running 改返回 pending_restart:true,stop→start 后生效。

geo 对齐:建议把 locale/tz pin 到代理出口的真实地理(德国代理配 de-DE / Europe/Berlin),避免「IP 在德国但浏览器声称美东」的矛盾。

12配额 & 生命周期

默认每用户 10 个实例(instances_max),超额 429 instance quota reached (max 10)。按实例数计,不分启停;腾配额需 DELETE。

created ──start──▶ starting ──▶ running ──stop──▶ stopped
   │                  │ 失败                          │
   │                  └──▶ error                      └──start──▶ running
   └──delete──▶ deleting ──▶ (销毁)   stopped ──delete──▶ (销毁)

13抗检测说明

自测:连上后访问 https://abrahamjuliot.github.io/creepjs/,关注多次重启指纹是否稳定、IP geo 与 tz/locale 是否对齐、有无 automation 红旗。

14错误码速查

REST 错误体 {"detail":"..."}:

含义处理
400插件上传全部失败(非 zip / 非 MV3 / 超限 / 路径非法)看返回 errors[],修正后重传
401缺 / 无效 token 或会话重新登录 / regenerate API token
404不存在或越权(实例 / 插件)核对 id / slug / 归属
409状态冲突(对 starting/stopping 调 start;对非 running 取 devtools)轮询 GET /v1/instances/{id} 至稳定再操作
422校验失败(name 空/超长、platform、proxy scheme)修正请求体
429配额满DELETE 不用的实例
500容器启动失败转 errorlast_error,重试 start
503GitHub OAuth 未配置(仅登录接口)

CDP WS 关闭码 4401/4409/4404/4502CDP 驱动。遇 4401/4409 重新 POST /start 拿最新带 token 端点再连。