部署——Docker & CDP 端点
把 Clearcote 作为常驻的 CDP 端点运行,再让任意现有框架连接它——Playwright、Puppeteer、browser-use、Crawl4AI、Stagehand——无需改代码。它直接启动二进制文件(不带 --enable-automation),因此 navigator.webdriver 保持为 false:隐蔽性是由启动方式本身决定的。
官方 Docker 镜像
拉取镜像即可开始使用。任何 CDP 客户端都可以通过暴露的端口接入。
docker run -d --rm -p 127.0.0.1:9222:9222 -e CC_FINGERPRINT=user-7423 teamflatearth/clearcote # CDP on http://localhost:9222from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp("http://localhost:9222") # your code, unchanged
page = browser.contexts[0].new_page() # the container's own profile
page.goto("https://example.com")
print(page.title())镜像内置了经过 SHA-256 校验的 Linux 版开源版构建,以及与 Windows 字体度量一致的克隆字体(让拉丁文字的测量结果与身份画像的字体一致;开源版构建的字体包不含 CJK 字形,所以在你改用授权版构建之前,中文、日文和韩文文本渲染时没有可用字体,授权版构建的字体包则包含这些字形),并默认使用一致的原生 Linux 身份画像(persona)。浏览器在虚拟显示器上以有头模式运行(CC_HEADLESS=1 为纯无头模式)。所有配置都通过环境变量完成:
docker run -d -p 127.0.0.1:9222:9222 -e CC_PLATFORM=linux -e CC_FINGERPRINT=user-7423 -e CC_ACCEPT_LANGUAGE=en-US -e CC_TIMEZONE=America/New_York teamflatearth/clearcote| 变量 | 含义 |
|---|---|
CC_FINGERPRINT | 种子(seed)→ 稳定的身份。不设置时,所有容器都呈现同一个身份(种子为 clearcote-docker),所以请为每个容器单独设置。 |
CC_PLATFORM | linux(默认)| windows | macos | android。Windows 身份画像还会开启 Widevine,并在授权版构建(151 r15+)上启用 HLSL 着色器方言(可用 CC_WIDEVINE / CC_SHADER_DIALECT 覆盖)。 |
CC_BRAND, CC_BRAND_VERSION | Chrome(默认)| Edge | Opera | Vivaldi,以及它所声称的版本。 |
CC_ACCEPT_LANGUAGE, CC_TIMEZONE | 语言列表和 IANA 时区。 |
CC_TLS_PROFILE | 保持不设置即可:TLS 会跟随身份画像声称的 Chrome 版本。只有在同时设置了匹配的 CC_BRAND_VERSION 时,才固定为 chrome-<major>。 |
CC_HARDWARE_CONCURRENCY, CC_GPU_VENDOR, CC_GPU_RENDERER, CC_STORAGE_QUOTA | 单项身份画像值。 |
CC_HEADLESS, CC_SCREEN | 1 表示纯无头模式;虚拟屏幕尺寸(默认 1920x1080x24)。 |
CC_EXTRA_ARGS | 额外的浏览器开关,以空格分隔。 |
CLEARCOTE_LICENSE_KEY, CC_VERSION | 运行授权版构建——见下文。 |
让身份画像声明容器实际运行的操作系统。页面能读取到的部分信息来自浏览器之下的宿主操作系统,任何身份画像设置都触及不到那一层。在这个 Linux 镜像中,无论CC_PLATFORM设为什么,文字尺寸都由 Linux 的 FreeType 缩放器计算,字体都来自 fontconfig。在此镜像上以CC_PLATFORM=windows实测:字号每次调整 0.01 px,只有 66% 的调整会改变文本宽度(真实的 Windows Chrome 为 99%),而且 Segoe UI 和 Georgia 在测量上显示为已安装,却无法按名称加载。指纹检测会把这两点都标记出来。默认的 Linux 身份画像则能通过。如需 Windows 身份,请运行 Windows 构建,或使用运行在 Windows 机器上的托管浏览器。在 Linux 服务器上使用serve()和launch()也是同样的道理。详情参见:用户代理之下的字体栈。
在 Docker 中运行授权版构建——传入密钥,挂载缓存
镜像内置的是开源版构建。设置 CLEARCOTE_LICENSE_KEY 后,容器会改为获取授权版构建——默认是最新的那个;如果是 Pro 套餐,也可以用 CC_VERSION 指定某个构建。免费密钥始终运行最新构建,指定版本会被拒绝。
docker run -d -p 127.0.0.1:9222:9222 -v clearcote-cache:/opt/xdg-cache -e CLEARCOTE_LICENSE_KEY=cc_lic_... teamflatearth/clearcote
# Pro only: pin a major, an exact build, or a revision
# -e CC_VERSION=153 -e CC_VERSION=153.0.8010.36 -e CC_VERSION=r28务必挂载缓存卷。授权版容器会在首次启动时下载引擎;如果没有持久化的卷,每个容器都会重新下载一遍。挂载卷之后,后续的容器会直接从缓存的构建启动。
启动日志会显示你拿到的是哪个引擎,所以密钥配置有误时能立刻发现,而不是等到第一个请求被拦截才察觉:
[clearcote] engine: /opt/xdg-cache/clearcote/pro-153.0.8010.36-r28/browser/chrome (licensed)
[clearcote] licence lease acquired镜像需要基于 SDK 0.26.1 或更新版本构建;使用来自 GitHub 的免费密钥时,则需要 0.30.0 或更新版本——授权版浏览器要求免费容器在运行期间持续续期许可证,并会拒绝较旧的镜像。较旧的已发布镜像会忽略密钥,悄悄提供开源版构建——运行 docker pull teamflatearth/clearcote 即可更新。授权版运行还会在启动时申领一个并发租约,因此容器需要能出站访问许可证 API;如果租约申领失败,容器会带着失败原因退出,而不是启动一个无法运行的引擎。一个免费密钥在你所有的容器中同一时间只能运行一个浏览器——参见授权版浏览器的计数方式。安全提示:CDP 端点意味着对浏览器的完全控制。只应将其发布到受信任的网络——-p 127.0.0.1:9222:9222 可将其限制在本机。docker/ Dockerfile 可供审计——你可以自己重新构建并验证。通过 SDK 提供常驻 CDP 端点——serve()
自己启动二进制文件,并获得一个任何客户端都能接入的 cdp_url。与镜像相同的隐蔽直接启动方式,只是由你自己的进程来驱动。
from clearcote import serve
srv = serve(fingerprint="seed-123", platform="windows") # -> srv.cdp_url
# attach ANY CDP client:
# playwright: p.chromium.connect_over_cdp(srv.cdp_url)
# puppeteer: puppeteer.connect({ browserURL: srv.cdp_url, defaultViewport: null })
# browser-use / Crawl4AI / Stagehand: point them at srv.cdp_url
srv.close()import { serve } from "clearcote";
const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
// srv.cdpUrl -> connectOverCDP / puppeteer.connect({ browserURL, defaultViewport: null })
await srv.close();在无头模式下,被服务的浏览器会获得一个真实尺寸的显示器——采用身份画像的尺寸,或从真实桌面数据中抽取的尺寸——并且在任何客户端接入之前,窗口就已适配到工作区,因此每个页面、标签页和弹出窗口上报的窗口都与其屏幕相符(SDK 0.31+)。如需更小的窗口,请传入 windowSize: { width, height }(Python 中为 window_size,.NET 中为 WindowSize);也可以在 args 中传入你自己的 --window-size,由你完全接管。
一个端点,多个身份——clearcote serve
在命令行中(Python 和 Node 包,0.29+),clearcote serve 会运行一个常驻端点,为连接所请求的每个身份分别启动一个独立的浏览器——其种子、代理、时区和语言都取自连接 URL。相同的种子会复用已经在运行的浏览器。
clearcote serve --port 9222 --idle-timeout 300 --max-browsers 16
# then, from any Playwright client:
# chromium.connect_over_cdp("http://127.0.0.1:9222?fingerprint=acct-1&platform=windows")
# chromium.connect_over_cdp("http://127.0.0.1:9222?fingerprint=acct-2&proxy=socks5://user:pass@host:1080&geoip=true")
# (a password-protected proxy needs the licensed build)它默认绑定到 localhost,并会拒绝网页可能发起的请求。空闲的身份会在 --idle-timeout 秒后关闭,--max-browsers 限制同时运行的数量(超出的身份会收到 HTTP 429),--data-dir 会在重启之间保留每个身份的 profile,--allow-host / --allow-origin 则让它可以运行在反向代理之后。打开 http://127.0.0.1:9222/ 可以查看当前在运行什么。使用 GitHub 免费版密钥时,同一时间只能运行一个浏览器。旧版的单身份脚本 clearcote-serve --port 9222 --fingerprint seed-123 仍然保留在 Python 包中。
直接启动——开源版构建,不用 SDK
Releases 页面上的开源版构建是一个普通的 Chromium 二进制文件,你可以通过 executable_path 和启动开关自行启动。授权版构建则需要 SDK,因为许可证令牌由 SDK 持有。下面的额外参数是 SDK 在 Windows 上为这个种子添加的主要默认值(它还会合并功能开关,并在使用代理时关闭 QUIC):
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=r"C:\clearcote\chrome.exe",
ignore_default_args=["--enable-automation", "--enable-unsafe-swiftshader"],
args=[
"--fingerprint=seed-123",
"--fingerprint-platform=windows",
"--fingerprint-brand=chrome",
"--accept-lang=en-US,en",
"--lang=en-US",
"--timezone=America/New_York",
"--webrtc-ip-handling-policy=disable_non_proxied_udp",
"--ignore-gpu-blocklist",
],
)
browser.new_page().goto("https://example.com")构建你自己的镜像(由 SDK 驱动)
Clearcote 提供 Linux x64 二进制文件,因此可以在容器中以无头模式运行。镜像需要浏览器运行时库、fontconfig 和 SDK。浏览器使用其版本自带的字体包,而不是系统字体;与官方镜像一样,开源版构建不含 CJK 字形(授权版构建的字体包包含这些字形)。在 Linux 上,身份画像默认是一致的原生 Linux 身份。WebRTC 防泄漏默认开启;Privacy Sandbox API 保持开启,与 Google Chrome 一致。
FROM node:22-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
xz-utils libnss3 libnspr4 libgbm1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libxfixes3 libxext6 libxrender1 \
libpango-1.0-0 libcairo2 libx11-6 libxcb1 libexpat1 libdbus-1-3 ca-certificates \
fontconfig fonts-liberation fonts-noto-color-emoji fonts-unifont fonts-ipafont-gothic fonts-wqy-zenhei \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN npm i clearcote
RUN node --input-type=module -e "import { download } from 'clearcote'; await download();" # bake the binary in
COPY run.mjs .
CMD ["node", "run.mjs"]import { launchPersistentContext } from "clearcote";
const ctx = await launchPersistentContext("/tmp/prof", {
headless: true,
fingerprint: "user-1",
proxy: { server: "http://gateway:8080", username: "u", password: "p" },
geoip: true, // timezone + languages + WebRTC IP matched to the proxy exit
humanize: true, // trusted bezier input; navigator.webdriver stays false
args: ["--no-sandbox"],
});
const page = ctx.pages()[0] ?? (await ctx.newPage());
await page.goto("https://example.com");
await ctx.close();运行容器时加上--shm-size=1g,避免在重型页面上出现/dev/shm相关的崩溃。Python 的用法完全相同(from clearcote import launch_persistent_context,选项使用snake_case命名)。
哪些客户端可以通过 CDP 接入
| 客户端 | 接入方式 |
|---|---|
| Playwright | chromium.connect_over_cdp(url) / connectOverCDP(url) |
| Puppeteer | puppeteer.connect({ browserURL: url, defaultViewport: null }) |
| browser-use · Crawl4AI · Stagehand | 把它们的 CDP/端点设置指向该 URL |
| 任何支持 CDP 的工具 | 直接使用该端口上的原始 DevTools Protocol |