dust to dust, ash to ash
一、先看风险:这条路到底有多危险
网页版没有正式关闭,但被账号门槛卡住了
微信网页版(wx.qq.com / wx2.qq.com / web.wechat.com)没有发布过正式的”关闭”公告,页面还能打开。但它是按账号设限的,不是人人都能用。Wechaty 的 FAQ(2026 年仍在线)写明:2017 年之后注册的账号无法通过 Web API 登录,登录会返回错误 1203(”当前登录环境异常……暂时不能登录 web 微信”),或者页面直接显示”为了保障你的账号安全,暂不支持使用网页版微信”。新账号基本进不去,老账号在用了自动化之后也可能失去权限。腾讯的方向是官方桌面和手机客户端。
GitHub 上的自动化项目,基本都死了
星数是 2026-11-06 当天从 GitHub 页面上抓的快照。星数是历史化石,2016–2017 年网页版登录还开放时攒下的星,并没有转化成 2024–2026 年的维护。
| 仓库 | 星数(约) | 干什么的 | 状态 |
|---|---|---|---|
| littlecodersh/ItChat | 26,458 | Python 调网页版协议做机器人 | 实际已弃。最后一次 push 是 2023-09-28,283 个 open issue |
| wechaty/wechaty | 23,518 | 多协议聊天机器人 SDK | 未归档但已停滞。Snyk 评为 inactive,约 4 年无 release |
| cluic/wxauto | 7,441 | 用 UIAutomation 驱动 Windows 版微信客户端 | 2025-10-28 停止维护。微信 4.0.5 从 Qt Widgets 改成 Qt Quick/QML,UI 树读不到了 |
| lich0821/WeChatFerry | 6,804 | DLL 注入官方 Windows 客户端 | 已归档 |
| trazyn/weweChat | 5,700 | 基于网页版协议的非官方桌面客户端 | 2024-06-26 被作者归档 |
| eatmoreapple/openwechat | 5,465 | Go 的网页版协议 SDK | 停滞。最后更新 2025-01-02 |
| songtianyi/wechat-go | 1,863 | Go 的网页版 API 实现 | README 自己就写明只支持 2017 年 6 月之前登过网页版的账号 |
| nodeWechat/wechat4u | 1,860 | JS 的网页版 API 实现 | 停滞。最后更新 2024-07-26 |
| why2lyj/ItChat-UOS | ~750 | ItChat 的分支,用 UOS 桌面协议”复活” | 已弃。UOS 绕法据报 2022 年初就失效了 |
| padlocal/wechaty-puppet-padlocal | ~769 | 逆向 iPad 协议的 Wechaty puppet | 无人维护。最后 npm 发布 2022 年 6 月 |
判断一个项目能不能用,看最后一次提交和它针对的协议今天还能不能登录,不看星数。
封号是真实存在的
微信帮助中心把”使用非官方插件运行微信”列为封禁原因,写明”严格禁止”。分两种结果:临时封禁可以按登录页提示申诉;永久封禁”没有解封选项”,只能重新注册账号。
社区里有记录的案例:
- 有人只用聊天机器人自用两天就被封了(ChatGPT-wechat-bot issue #158,2023 年)。
- 网页版专属封禁,持续 1 周到 3 个月不等,手机和桌面登录不受影响(EFB issue #7,2017–2021 年间的记录,2023–2026 年的讨论还在引用)。
- 重复违规会加长封禁时长,第三次可能永久。
触发因素(社区总结,腾讯不公布检测规则):高频或批量发送、回复太快太规律、24/7 不间断在线、DLL 注入、新账号加自动化、服务器或境外 IP、手机和网页登录的地理位置不一致、被其他用户举报、用了有明显指纹特征的自动化库。
只读 watcher 和高频机器人,风险一样吗
没有哪个来源实测过”每几分钟读一次聊天列表”的封号概率,下面的比较是基于触发因素的推理,不是实测数据。任何声称某个具体间隔”安全”的说法,都是编出来的数字。
- 高频机器人(自动回复、群发、固定间隔、24/7):风险最高。消息量、速度、规律性都是最靠前的触发因素,有几天内被封的记录。
- 低频只读 watcher(每隔几分钟查一次聊天列表,基本不发送,老账号、家庭网络、真实浏览器):去掉了最强的信号(发送),但还剩网页版协议登录本身、长时间持续在线、固定间隔轮询、没有鼠标键盘操作这几个信号。账号仍然可能在不发任何消息的情况下被限制网页版访问。
- 真实浏览器(CDP 接入自己在用的 headed 浏览器):指纹风险在非官方方案里最低(真实 UA、TLS、cookie、profile),但不能让它合规。Wechaty 自己的网页版 puppet 就是 Puppeteer 驱动 Chrome,用户照样会遇到 1203 和警告,说明”真实浏览器”绕不过网页版协议的门槛。
- 逆向协议库(itchat / wechat4u / openwechat):风险高且在上升。这些库正是 1203 和封号报告背后的主角,而且都已无人维护,无法适应新的检测。
- DLL 注入:检测面最大,也最脆弱。旗舰项目已归档。
- UI 自动化驱动桌面客户端:理论上协议风险最低,但 2026 年已实际死亡(微信 4.0 的 Qt Quick 让 UIAutomation 读不到控件)。
给轮询设计的几点具体建议:真正的网页版客户端不是定时轮询聊天列表,它是长连接,服务器有新消息就推过来。固定间隔定时查,比真人更规律,也比原生客户端更可疑。如果必须轮询,加随机抖动、夜间暂停、不要 24/7 不间断。只在已经登录的标签页里读 DOM,不导航、不点、不发,是最不具侵入性的形式。第一次发送会重新引入最强的触发信号,能不发就别发。
二、操作方法:用 CDP 操作微信网页版
下面是这套做法的完整描述。所有操作都针对一个已经登录的网页版标签页,通过 Chrome DevTools Protocol(CDP)走 WebSocket 完成,不发任何额外的 HTTP 请求,不模拟登录。
连接
- 从浏览器的调试端点取页面目标,挑
type是page的那一项。 - 用
websocket-client建连,建连时传suppress_origin=True。Chromium 会拒绝带Origin头的 CDP WebSocket 握手,不发这个头才能连上。 - 建连后先启用
Runtime域再执行 JavaScript;需要操作 DOM 节点时再启用DOM域。 - 辅助脚本写成文件再运行,不要把 JavaScript 塞进 shell heredoc,bash 的引号处理会把代码搅坏。
读聊天列表
- 在页面里读聊天列表元素。每个条目能拿到名字、是不是群聊(群聊的标识以
@@开头)、预览文字、未读数。 - 聊天列表只显示最近的会话。很久没发消息的联系人可能不在列表里,找这种联系人要用搜索框,不要翻列表。
- 可以注入一个 MutationObserver,让聊天列表一变就更新一个快照对象,轮询时直接读快照,不用每次都扫 DOM。页面重载后要重新注入。
找联系人
- 用搜索框,不要用通讯录标签页。通讯录只渲染有限条目,滚动也翻不出更多。
- 点搜索结果时只点昵称和目标名字完全一致、且整行文字很短的那一项。
- 联系人在可见聊天列表里时,直接点列表项;不在时再走搜索。
发文字消息
- 点开聊天后,先核对标题。读标题栏的昵称,和目标收件人逐字比对,不一致就中止,没有例外。
- 确认无误后聚焦输入框,用
Input.insertText输入内容,再用Input.dispatchKeyEvent发一个 Enter(keyDown 和 keyUp 各一次)。 - 发完读最后一条消息元素确认:它的 class 包含
me,文本和发送内容一致。
发文件或语音
- 网页版没有语音按钮。语音消息就是一个 MP3 文件附件。
- 用
DOM.querySelector找到工具栏里的 file input,用DOM.setFileInputFiles把要发送的文件设进去。 - 设完会出现确认对话框,点文字恰好是”发送”且可见的那个按钮。
- 发完读最后一条消息元素确认,文件消息会显示文件名和大小。
判断消息方向
- 预览文字变了,并不能说明是谁发的。点开聊天,读最后一条消息元素:class 有
me是自己发的(绿色气泡在右边),没有me是对方发的(白色气泡在左边)。 - 只有在未读数已经是 0(说明用户在手机上读过了)时,才点开聊天做方向判断。点开未读的聊天会把消息在手机上标已读。
读语音消息并转文字
- 语音消息在页面里是一个可点击的元素,点一下会触发播放,播放时发起一个取音频的请求,响应是 MP3。
- 在页面里用带登录态的
fetch把音频拉下来,转 base64,存成 MP3 文件。 - 转文字可以用语音识别服务(比如 Whisper 类模型),把 MP3 当请求体发过去。机器转写的质量有限,呈现时要说明是机器转的,并把原音频一并给出,让人自己听。
轮询设计
- 每一轮开头加随机抖动,实际间隔在几分钟内浮动,不要固定间隔。凌晨加一段静默期。
- 检测只看预览文字变化,不看未读数。手机和网页版的已读状态是同步的,未读数不能作为新消息的判断依据。
- 预览变了,未读 > 0:一定是对方发的,直接报。
- 预览变了,未读 == 0:分不清是谁发的,走方向判断(点开聊天看最后一条气泡的颜色,已经是已读状态,点开安全)。
- 新出现的聊天也按同样的流程处理:预览有实质内容就处理,预览只有名字就跳过。
- 用锁文件防止两轮轮询并发跑,抢到锁的那轮跑,抢不到的直接退出。
- 连续失败达到一定次数再报给用户,单次失败只记日志。
三、降低风险的做法
以下都是减害措施,没有任何一条能让非官方使用变得安全或合规。
- 先手动测试账号能不能登录网页版。如果不行(1203 / “暂不支持”),就此打住。绕过插件和伪装正是检测要抓的逃避行为。
- 用可以丢弃的小号,绝不用绑定了支付或工作的重要账号。
- 能用官方客户端手动做的事,就用官方客户端。
- 如果 watcher 不可避免:只读不发、间隔随机加抖动、夜间暂停、不要 24/7、不要批量枚举联系人或群、不要自动加好友或进群。
- 环境保持一致:同一台设备、和手机一样的家庭网络,不要用服务器或 VPS、不要频繁换 IP、不要多设备同时登录。
- 不要用已死的规避工具:逆向协议库、伪装、”解除网页版限制”浏览器插件、DLL 注入、pad token 服务。
- 开始之前先想好恢复办法:登录页的申诉入口、绑定手机号要能收到验证码、接受恢复可能失败的结果。不要付费找第三方”解封”,那是骗局。
- 2026 年腾讯出了一个官方的个人账号机器人通道(OpenClaw / iLink 协议),扫码绑定、标准 HTTP/JSON、只能回复不能主动发起。多个二手来源说这是第一条官方的、无封号风险的个人账号机器人接入方式。但这篇调研没有对照腾讯自己的文档核实过,是否开放、只读 watcher 能不能用,都还没确认。用之前先去微信开放平台查官方文档。
参考
- Chrome DevTools Protocol:https://chromedevtools.github.io/devtools-protocol/
- websocket-client(Python):https://websocket-client.readthedocs.io/
- Wechaty FAQ(2017 年后注册账号无法登录网页版):https://wechaty.js.org/docs/explanations/faq
- 微信帮助中心(非官方插件封禁原因):https://help.wechat.com/
- EFB issue #7(网页版封禁 1 周到 3 个月):https://github.com/ehForwarderBot/efb-wechat-slave/issues/7
- ChatGPT-wechat-bot issue #158(自用两天被封):https://github.com/AutumnWhj/ChatGPT-wechat-bot/issues/158
附件
本文涉及的操作方法已整理成一份 skill,随包附上。