OpenClaw 的指纹伪装还没跑通,验证码照弹、表单照被拦,被拒的原因往往不在出口 IP。先把模型通道换到 TaoToken(https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=)取一把 Key,再回头收拾 config.yaml 里的 browser.args,这条顺序能省掉很多来回。
日志里最常见的画面是这样的:脚本跑到第二步,页面直接 403,或者弹出的验证码怎么点都不给过。你以为是出口 IP 又被拉黑了,于是换一条、再换一条,结果换到第五条还是同样的结局。问题在于,OpenClaw 默认拉起来的那个 Chromium,本身就把自己的身份写在脸上——navigator.webdriver是true,Canvas 指纹每一轮刷新都不一样,无头模式下 UA 里甚至带着 Headless 字样,窗口的outerWidth是 0,插件列表是空的。这些东西跟你从哪个 IP 出去没有任何关系,检测逻辑看的是浏览器像不像一个真人用的浏览器。
这篇要讲的不是把指纹伪装那一整套原理再复述一遍,而是一个更靠前的顺序问题:OpenClaw 的判断、重试、填表、翻页,全靠模型侧给出稳定的输出。模型通道在抖、额度打满、或者 Base URL 配错了根本请求不出去,你把 browser.args 改出花来也没用,因为 Agent 根本走不到操作页面那一步。所以合理的路径是——拿 Key、改 model 段、跑通一次最小调用、再回到浏览器段做指纹。
需要先说清楚的是,下面这些配置只应该用在你自己拥有、或者拿到明确授权的自动化环境里,比如内部测试账号、自有站点的回归脚本。指纹配置本身是个中性的技术项,用在哪里决定了它是什么性质,批量注册、刷量之类的操作不在讨论范围内。
1. 出口 IP 换了一轮,被拒的其实是浏览器身份
1.1 navigator.webdriver 与无头标记:第一眼就被分开
默认启动的 Chromium 在自动化模式下,最直接的暴露点是navigator.webdriver。普通用户浏览器里这个值是undefined,自动化上下文里它是true,一行 JS 就能读出来。很多人以为改掉 UA 就够了,其实 UA 只是众多信号里的一个,而且是最容易伪造的一个,反而没人拿它当唯一判据。
无头模式的问题更大。老式--headless启动的浏览器,UA 里会多出HeadlessChrome,window.outerWidth和window.outerHeight会是 0,window.chrome对象可能残缺,navigator.plugins长度是 0。这些信号单独看都不致命,组合在一起就成了一个非常清晰的特征。检测方不需要什么高级模型,几条规则串起来就能把这类流量摘出去。
所以"换 IP 解决不了"这件事就很好理解了:你换的是网络层的身份,暴露的是浏览器层的身份。两层对不上,风控反而更容易判断——一个美国出口 IP,配一个Asia/Shanghai时区、zh-CN语言、空插件列表的浏览器,这个组合本身就够可疑的。
1.2 Canvas 指纹每轮都变,等于自己举手
Canvas 指纹的原理不复杂:让浏览器画一段带文字和渐变的图形,不同设备因为显卡、驱动、字体渲染的细微差异,画出来的像素会略有不同,把像素哈希一下就得到设备指纹。真实用户的这个哈希值基本是稳定的,一年半载都不太变。
问题出在"防追踪"类的插件和某些默认配置上。有些环境每次启动都随机注入噪声,导致同一个账号的 Canvas 哈希每轮都不一样。对风控来说,这比指纹固定还刺眼——一个正常用户的设备指纹不应该五分钟换一次。你越想藏,痕迹越明显。
这里有个容易踩的坑:一致性比随机性更重要。时区、语言、viewport、字体列表、WebGL vendor、Canvas 哈希,这几个值应该在同一个 profile 里保持稳定,并且和出口 IP 的地理位置大致对得上。稳定加合理,比每次随机要安全得多。
2. 先拿 Key:把 OpenClaw 的模型请求交给 TaoToken 兼容通道
2.1 在官网创建 API Key
打开 TaoToken 完成注册并登录,进控制台的 API Keys 页面创建一把新 Key。创建完立刻复制,页面刷新之后就看不全了。这串东西在你本地配置文件里就是YOUR_API_KEY的位置,本文所有示例都用这个占位符,你替换成自己那把。
有一条纪律值得单独说:Key 只放在本机配置文件或者环境变量里,不要写进代码仓库,不要贴进聊天记录。OpenClaw 的 config.yaml 如果放在项目目录下,记得把对应的 profile 目录和配置文件加进.gitignore。我见过太多人排障排到一半发现 Key 泄露被刷量,那种情况下再讨论指纹配置就没有意义了。
2.2 Base URL 为什么是 https://taotoken.net/api 而不是带 /v1
OpenClaw 的模型配置里,base_url填的是https://taotoken.net/api,末尾不要加/v1。这是最容易出错的一行,也是 404 报错里占比最高的一类。
原因在于 OpenAI 兼容客户端的行为:它拿到base_url之后会自己拼接/chat/completions这样的路径。如果你提前写成https://taotoken.net/api/v1,最终请求就变成了.../api/v1/v1/chat/completions,服务端自然找不到路由。另外要分清两个地址的用途——官网页面 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 是给你注册、建 Key、看模型广场、查用量用的;填进工具配置文件的接口地址是 https://taotoken.net/api,两者不要混着写。
注意:接口地址
https://taotoken.net/api后面既不加/v1,也不要附加任何查询参数。它就是一个干净的 Base URL。
3. OpenClaw 的 model 段怎么改:config.yaml 可复制示例
3.1 model 段的完整写法
OpenClaw 的配置文件位置跟安装方式有关,常见的是项目根目录下的config.yaml,也有装在~/.openclaw/config.yaml的。先确认你实际加载的是哪一份,改错文件是最浪费时间的排障方式。找到之后,把 model 段改成下面这样:
# ~/.openclaw/config.yaml model: provider: openai-compatible base_url: https://taotoken.net/api api_key: YOUR_API_KEY model: YOUR_MODEL_ID max_tokens: 4096 temperature: 0.2 timeout: 120逐行说一下。provider保持兼容协议不变;base_url就是上一条说的地址;api_key换成你刚才创建的那把;model先留占位符,下一节讲怎么填;timeout建议给到 120 秒以上,OpenClaw 的某些步骤会让模型输出较长的规划文本,超时设短了会出现"请求发出去了但结果没回来"的假故障。
改完保存,重启 OpenClaw 进程。多数版本支持热加载,但涉及 provider 变更时重启更保险。
3.2 模型 ID 从模型广场抄,别自己拼
model这个字段不要凭印象写。像gpt-5、带随机日期后缀的名字,看着合理但大概率不存在,请求过去会直接返回模型不存在的错误。正确做法是打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= 的模型广场,找到你要用的那个,把 ID 原样复制过来替换YOUR_MODEL_ID。
不同模型对 Agent 类任务的表现差别不小。OpenClaw 经常要输出结构化的动作序列,指令跟随弱的模型会漏字段、编参数,表现出来就是"脚本随机失败"。所以换模型时别只看价格,先拿一条最小的任务试一次,确认它能稳定输出你要的格式再切。切换成本极低,模型段只改一行,改完重启即可。
4. 模型跑通后再动 browser.args:隐藏 AutomationControlled、固定 viewport
4.1 args 数组里该加哪几行
模型侧确认能正常返回之后,再回来处理浏览器身份。原文阶段一的核心就是改config.yaml里的browser.args,把几个最明显的自动化标记压下去:
browser: type: chromium headless: false viewport: width: 1440 height: 900 args: - --disable-blink-features=AutomationControlled - --window-size=1440,900 - --lang=zh-CN - --no-default-browser-check user_data_dir: ./profiles/default fingerprint: timezone: Asia/Shanghai locale: zh-CN canvas: noise webgl: noise--disable-blink-features=AutomationControlled是这里最关键的一行,它能让 Chromium 不再主动暴露自动化控制状态。--window-size要和下面的viewport对齐,否则outerWidth和innerWidth的比例会很奇怪。user_data_dir指向一个固定目录,让 cookie、localStorage、缓存跨轮次保留,这对维持稳定的指纹很重要——每次都从零开始的干净 profile,本身就是个可疑特征。
headless: false在有图形界面的机器上是首选。如果必须在服务器上跑,用新版无头模式而不是老的--headless,两者暴露的信号差别很大。
4.2 viewport、时区、语言要和出口 IP 对得上
这一条比想象中重要。很多人把 args 配得好好的,结果时区还是Asia/Shanghai,出口 IP 却在别的大洲,指纹自检页面上两个值并排一放,矛盾一目了然。
把timezone、locale、viewport三个值当成一组来配。出口在哪个地区,时区和语言就跟到那个地区,viewport 用一个常见的桌面分辨率,不要用 800×600 这种明显不合理的值。Canvas 和 WebGL 给噪声是可以的,但噪声函数要保证同一个 profile 下输出稳定,不要每轮都重新随机。
另外提醒一句,user_data_dir的目录不要在轮次之间删。有些脚本为了"干净",每次任务前清一次 profile,结果指纹全变,前面所有伪装努力当场归零。
5. stealth 技能与 AdsPower:什么时候单开浏览器上下文
5.1 OpenClaw stealth 技能挂载方式
args 只能改启动参数,改不了页面里那些 JS 层面的探测。比如navigator.permissions.query的返回值、window.chrome.runtime是否完整、plugins数组的内容,这些需要在页面上下文里打补丁。OpenClaw 的 stealth 技能做的就是这个事:
skills: - name: stealth enabled: true options: patch_webdriver: true patch_permissions: true patch_plugins: true挂载之后重启,再跑一次指纹自检页面。要注意 stealth 技能不是银弹,它解决的是 JS 层面的补丁,解决不了显卡渲染差异、字体列表缺失这类系统层特征。把它当成第一层防线,不要指望一个技能包全部搞定。
5.2 用 AdsPower 走 CDP 接入
如果目标场景对指纹要求更高,或者你要在同一台机器上同时维持多个互相隔离的身份,那就该上指纹浏览器了。AdsPower 这类工具的思路是每个 profile 一套独立的浏览器内核参数和指纹,OpenClaw 通过 CDP 连上去用就行,不需要自己维护 args。
在 AdsPower 客户端里开启本地 API,启动目标 profile,复制它的调试地址,形如ws://127.0.0.1:PORT/devtools/browser/PROFILE_ID。然后改 OpenClaw 的 browser 段:
browser: type: chromium cdp_endpoint: "ws://127.0.0.1:PORT/devtools/browser/PROFILE_ID" user_data_dir: null args: []这里把args清空是故意的。指纹浏览器已经接管了内核参数,你再传一遍--disable-blink-features之类的开关,容易和它自己的配置打架,表现就是浏览器起不来或者 profile 直接损坏。user_data_dir也交给它管,OpenClaw 这一侧不要再指定。
6. 验证两步走:先验模型通道,再验指纹
6.1 一条最小 Agent 调用
不要一上来就跑完整业务流程。先给 OpenClaw 一个最小任务,比如"打开某个页面,读一下标题,把标题打印出来"。这一步的目的是确认模型请求真的发出去了、真的回来了。
如果这一步就失败,去看日志里的 HTTP 状态码。同时打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的控制台,在用量或调用记录里对一下时间点。如果控制台里完全没有记录,说明请求根本没到你配的这个地址,多半是配置文件路径不对或者用的是另一个 provider;如果控制台里有记录但报错,那就是模型 ID 或者参数的问题。
需要强调的是,诊断脚本、页面检测、SQL 之类的操作,都由你在本地或对应客户端里执行,把输出结果贴回对话,让模型帮你分析。OpenClaw 和模型本身不会直接连你的生产环境去跑东西,这个边界要守住。
6.2 指纹自检页面对照表
模型通了下,再开浏览器做一次自检。随便挑一个在线的指纹检测页面,重点看这几项:
| 检测项 | 期望状态 | 常见异常 |
|---|---|---|
navigator.webdriver | undefined | 仍为true,args 没生效 |
| Canvas 哈希 | 同一 profile 稳定 | 每轮都不一样,噪声函数在重随机 |
| viewport 尺寸 | 与--window-size一致 | outer 与 inner 差距过大 |
| 时区 / 语言 | 与出口地区匹配 | 与 IP 地理位置明显冲突 |
| WebGL vendor | 真实显卡厂商 | SwiftShader 等软件渲染标识 |
| plugins 列表 | 非空 | 空数组,无头模式残留 |
哪一项不对就回头改哪一段,不要一次性全改。改完再自检,形成闭环。
7. 报错对照:401、模型名不对、args 不生效
7.1 模型侧报错怎么定位
| 现象 | 大概率原因 | 处理 |
|---|---|---|
| 401 Unauthorized | Key 拼错、有多余空格、用了别的项目的 Key | 去控制台重新复制一把,全部替换 |
| 404 / 路由不存在 | Base URL 多写了/v1 | 改回https://taotoken.net/api |
| 模型不存在 | model字段是自己拼的名字 | 从模型广场复制准确 ID |
| 请求超时无返回 | timeout太短,或模型输出被截断 | 调到 120 秒以上,检查max_tokens |
这几类错误里,401 和 404 最好排查,因为报错很直接。真正烦的是"看起来成功了但结果不对",那通常是模型指令跟随的问题,换个模型试一次往往比改提示词更快。
7.2 浏览器侧配置没生效怎么查
args 改完没效果,先确认进程真的重启了。其次检查配置有没有被更高优先级的设置覆盖——有些 OpenClaw 版本会同时读项目内配置和用户目录配置,两边都有 browser 段时以其中一份为准,这个规则要看具体版本。
还有一种情况是配置生效了但检测项依然异常,比如webdriver已经是undefined,Canvas 哈希却还在变。那说明噪声是另一处注入的,可能在 stealth 技能里,也可能在你自己的脚本里。逐个关掉再测,二分定位比盯着配置文件猜要快得多。
8. 跑通之后,去控制台对一下这次调用有没有记上账
8.1 用同一把 Key 在模型对话里复测
配置改完、最小任务跑通之后,建议再做一次交叉验证:到 TaoToken 模型对话 里,用同一把 Key、同一个模型 ID 发一条测试消息。这一侧的调用记录如果和 OpenClaw 那边的时间点对得上,就说明 Base URL、Key、模型 ID 三件套完全正确,后面出了问题可以直接排除模型通道,专心查浏览器那一段。
8.2 长期跑要不要上 Coding Plan
如果只是偶尔跑几个任务,按量用就够了。但如果 OpenClaw 要长期挂在后台做定时任务、每天几十上百次调用,那就值得去 Coding Plan 看一下套餐档位,避免跑到一半因为额度问题中断——自动化任务最怕的就是失败在模型调用这一步,日志里看起来像脚本 bug,实际是额度见底。
新的 Key 随时可以在 控制台 API Keys 创建,多环境隔离时建议一个环境一把,出问题好定位是哪个环节在消耗。指纹那一段的配置值本身也要定期回头看,检测手段在变,半年前好用的 args 组合现在未必还合适,保持自检的习惯比一次配到位更实际。