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_...(只显示一次,旧 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 missing token;查不到 → 401 invalid token

每用户同时只有一个有效 token;POST /v1/token/regenerate 签发新明文、旧 token(含旧 cookie)立即失效。服务端只存 sha256(token),丢了再 regenerate。

token 类型前缀用途有效期
账户 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, updated_at)、Detail(Summary + container_name, cdp_endpoint, fingerprint_committed, 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

错误:429 配额满、422 校验失败。

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}

07CDP 驱动 (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上游连接失败

08代理设置

每实例绑一个独立出口代理,凭据 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 在德国但浏览器声称美东」的矛盾。

09配额 & 生命周期

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

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

10抗检测说明

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

11错误码速查

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

含义处理
401缺 / 无效 token重新 regenerate
404不存在或越权核对 id / 归属
409状态冲突(对 starting/stopping 调 start)轮询 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 端点再连。