Playwright & Puppeteer
Clearcote 本质上就是 Chromium,因此可以直接替换你现有自动化工具所用的浏览器。
使用 SDK(推荐)
clearcote 包(npm、PyPI 和 NuGet)把身份选项变成具名参数,返回的是普通的 Playwright 对象。它会在首次使用时下载浏览器并做 SHA-256 校验——没有许可证密钥时是开源版构建,有密钥时是最新的授权版构建(参见安装)——并应用下文介绍的默认设置。
# pip install clearcote
from clearcote import launch
browser = launch(fingerprint="seed-123", platform="windows", brand="Chrome")
page = browser.new_page()
page.goto("https://example.com")
browser.close()当前 SDK 版本:0.45.0。从 0.23 起,Python 和 Node 中的 launch() 不再使用无痕模式,而是运行在一个真实的临时 profile 目录上(关闭时删除),这样与 profile 相关的可检测面就和真实 Chrome 一致,widevine: true 也能加载 DRM 模块。它返回一个类似 browser 的句柄:newPage() 照常可用,但 newContext() 返回的是同一个 profile 上下文,而不是一个隔离的新上下文。需要相互独立的 Cookie 存储时,请分别启动多个浏览器;传入 ephemeralProfile: false / ephemeral_profile=False 可以拿回旧的无痕 Browser,传入 userDataDir / user_data_dir 则可以保留 profile。
异步 API(clearcote.async_api)在 asyncio 循环中接受同样的身份画像(persona)和代理选项,返回 Playwright 异步对象;它的 launch() 使用无痕模式,所以需要 profile 时(以及使用 widevine=True 时)请用 launch_persistent_context()。.NET SDK 支持 LaunchEphemeralProfileAsync(推荐——.NET 的 LaunchAsync 使用无痕模式,且无法在无头模式下让窗口适配屏幕)、LaunchPersistentContextAsync、ServeAsync、经过校验的下载、授权、Geoip 以及拟人化输入(通过显式调用 HumanClickAsync / HumanTypeAsync / HumanSelectOptionAsync 实现,而不是启动参数)。已保存的 profile、profile: "auto"、渲染一致性检查、Widevine 和智能体辅助功能目前仅支持 Python & Node。完整的可复制工作流请参见示例。
Puppeteer 及其他 CDP 客户端(serve)
SDK 没有提供 Puppeteer 启动器,而是提供了 serve():它用 SDK 的启动设置(身份画像、代理、默认值)启动 Clearcote,并在回环地址上开放一个 CDP 端点,任何 CDP 客户端都可以接入——Puppeteer、Playwright 的 connectOverCDP、browser-use、Crawl4AI、Stagehand。它支持授权版构建,而且整个过程中没有任何环节会添加 --enable-automation。humanize 是在 Playwright 侧实现的,因此对以这种方式接入的客户端不起作用。
import { serve } from "clearcote";
import puppeteer from "puppeteer-core";
const srv = await serve({ fingerprint: "seed-123", platform: "windows" });
const browser = await puppeteer.connect({ browserURL: srv.cdpUrl, defaultViewport: null });
const page = await browser.newPage();
await page.goto("https://example.com");
await browser.disconnect();
await srv.close();在无头模式下,serve() 会为浏览器提供一个真实尺寸的显示器,并在任何客户端接入之前把窗口适配到工作区(0.31+);如需更小的窗口,请传入 windowSize / window_size。在命令行中,clearcote serve 以常驻服务的形式实现同样的功能——还可以为每个连接分配独立的浏览器,其身份、代理、时区和语言都取自连接 URL。参见部署。
直接驱动二进制文件(开源版构建)
你也可以用自己的启动器驱动开源版构建:通过 executablePath(Node)或 executable_path(Python)指定路径,并以 args 传入身份选项。授权版构建无法以这种方式启动——它需要 SDK 申领的许可证令牌,所以请使用上文的 launch() 或 serve()。像 SDK 那样去掉 --enable-automation(Puppeteer 和较旧版本的 Playwright 会添加它;它会让 Chromium 切换到自动化模式)。走这条路时,SDK 的默认设置(语言、WebRTC 策略、窗口几何尺寸)一概不生效。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
executable_path=r"C:\clearcote\chrome.exe",
headless=False,
ignore_default_args=["--enable-automation"],
args=[
"--fingerprint=seed-123",
"--fingerprint-platform=windows",
"--timezone=America/New_York",
],
)
page = browser.new_page()
page.goto("https://abrahamjuliot.github.io/creepjs/")
browser.close()解析或预取经过校验的二进制文件
SDK 按以下顺序确定使用哪个浏览器:显式指定的 executablePath / executable_path,然后是 CLEARCOTE_BINARY,然后是你指定的 version(或 CLEARCOTE_BROWSER_VERSION),然后是授权版构建(前提是找到了许可证密钥:licenseKey 选项、CLEARCOTE_LICENSE_KEY 或 ~/.clearcote/license.key),最后是当前 SDK 版本锁定的开源版构建。你提供的路径会在启动前检查是否有缺失或被截断的文件。如果你想在不启动浏览器的情况下预热缓存、使用自定义缓存目录,或在运行时主动选用 GitHub 上最新的开源版构建,请调用 download / executable_path。
from clearcote import download, launch
chrome = download(cache_dir=r"C:\clearcote-cache", auto_update=True)
browser = launch(executable_path=chrome, fingerprint="seed-123")锁定模式会校验 SDK 内置的 SHA-256 值。autoUpdate / auto_update 需要手动开启,它会校验发行版的校验和清单;如果系统中有 gpg,还会用内置锁定的 Clearcote 签名密钥指纹核验已签名的清单。它只适用于开源版构建:设置了许可证密钥时,download() 会改为获取当前的授权版构建(可用 version 或 releaseChannel 选择——参见选择构建)。在 .NET 中,DownloadAsync 只获取开源版构建;要预取授权版构建,请使用 ExecutablePathAsync(new LaunchOptions { LicenseKey = … })。
默认保持一致(无需额外参数)
无论你用什么参数启动,引擎都会让次要可检测面与你选择的身份画像保持一致——对于 Windows 身份画像,就是与真实的 Windows 桌面版 Chrome 上报的内容一致。身份画像的平台默认跟随宿主操作系统,所以在 Linux 主机上,除非传入 platform,这些值会遵循 Linux 身份画像。WebGL getParameter 限制值(WebGL1 + WebGL2)上报的是身份画像的数值,但不会超过本机 GPU 实际能提供的上限;UNMASKED_RENDERER / UNMASKED_VENDOR 在整个会话内保持不变(每个站点看到的都是同一块 GPU,并与身份画像对应)。对于 Windows 身份画像,navigator.getBattery() 上报的是接通电源的台式机,navigator.connection 上报住宅网络连接,AudioContext 上报与之匹配的 Windows WASAPI 采样率和延迟。getScreenDetails() 上报单个显示器,@media (pointer: fine) / (hover: hover) 与使用鼠标的台式机相符。
已在 153 r26 上验证,Windows 有头模式(2026 年 9 月):BrowserScan 的结果为未发现机器人,CreepJS 显示 0% stealth。使用代理时,请加上 geoip,让时区和 WebRTC 与出口保持一致。
一致的默认设置(可覆盖)
SDK 会应用几项符合隐蔽性要求的默认设置,避免露出明显的破绽:
- 有头模式启动默认不模拟视口(
viewport: null/no_viewport=True),这样window.innerWidth会跟随真实的操作系统窗口——在真实窗口上套一个模拟的 1280×720 视口,就是一个“不可能存在的窗口”破绽。传入显式的viewport可覆盖此行为。在没有窗口管理器的 Linux 服务器上(Xvfb、你自己的容器),--start-maximized不起作用,此时有头窗口会在第一个页面打开之前适配到屏幕的工作区,就像一个最大化的桌面窗口(SDK 0.42.0)。 - 无头模式启动会在第一个页面打开之前获得一个逼真的显示器,以及一个与之适配的窗口:使用身份画像的屏幕,没有身份画像时则使用真实的桌面尺寸。从 SDK 0.42.0 起,即使身份画像没有生效,这一点在所有平台上也都成立,因此页面不会看到引擎原始的 800×600 无头渲染表面。你自己传入的
viewport或screen选项会关闭这一行为,而你自己传入的--screen-info则由你自行设定显示器。你自己传入的--window-size、--window-position或--start-maximized会保留显示器,只跳过窗口适配;在serve()中,单独传入的--window-position同样会保留显示器,只有尺寸开关或--screen-info才会把几何设置完全交给你。 - Linux 上统一的 WebGL 表面:在 Linux 主机上,Linux 身份画像的 WebGL 无论有头还是无头,都通过基于 EGL 的 Mesa 渲染(SDK 0.42.0;主机需要安装
libegl1),因此两种模式下页面看到的都是同一个渲染器字符串、扩展列表和同一组限制值,并采用大多数真实 Linux 机器报告的 OpenGL ES 形式。没有 EGL 时,有头模式启动会使用 Mesa 的桌面 GL,而 Windows 身份画像则通过 SwiftShader 渲染。你自己在args中传入的--use-angle或--use-gl优先生效,同时无头模式启动仍会获得--ignore-gpu-blocklist,因此 WebGL 可以继续正常工作。 - 浅色或深色由身份画像决定(154 r32 起的授权版构建):SDK 创建的上下文不会开启 Playwright 的配色方案模拟(SDK 0.41.0+),否则 Playwright 会强制使用浅色。如果仍想模拟某种配色方案,请传入
colorScheme/color_scheme。 - 身份画像不出现在命令行上(154 r32 起的授权版构建):种子、身份画像覆盖项和代理凭据通过环境变量传给浏览器,而不是出现在它的进程列表条目中(SDK 0.41.0+;
personaEnv: false可保留命令行方式)。参见启动选项。 - WebRTC 默认使用
disable_non_proxied_udp,因此不会有 UDP 流量不经代理直接发出,本机的真实地址也不会外泄。只有你自己在args中传入的--webrtc-ip-handling-policy能覆盖它——此外,在开源版构建上,webrtcIp/geoip也会让 WebRTC UDP 重新从你自己的网络连接发出(授权版构建无论如何都会阻止 WebRTC UDP)。在该策略下且没有设置webrtcIp时,页面完全拿不到任何 ICE candidate——使用代理时,请传入geoip(或webrtcIp),让 WebRTC 上报代理的地址,或者用socks5Udp通过 SOCKS5 代理传输真实的 UDP。 - 使用代理时,QUIC / HTTP-3 处于关闭状态,与真实 Chrome 使用代理时一样——因此不会尝试在代理之外发送任何 UDP。
- 身份画像的平台默认跟随宿主操作系统,品牌默认为 Google Chrome。如果既没有
timezone也没有geoip,时区会跟随语言(en-US→ 纽约)。 - 在引擎支持的情况下,代理凭据交给浏览器处理,而不是交给 Playwright:SOCKS5 始终如此(Playwright 根本无法对 SOCKS5 进行认证),HTTP(S) 则从 151 r19+ 起如此,这样页面缓存可以保持开启(Python & Node)。见下文。
humanize会在每次可信点击之前执行可操作性预检(可见 / 已启用 / 稳定 + 基于elementFromPoint的遮挡检查),不满足条件时回退到原生点击,因此可信点击不会在元素被遮挡或动画进行中时触发。
提示:用你自己的账号/租户 ID 派生种子,让每个身份都可以复现——同样的种子,每次都得到同样的浏览器指纹。完整的开关列表见指纹参数。