抖音开放平台目前已逐渐转向封闭,不再“开放”了。2025年4月14日抖音开放平台通知:
”将于2025年4月14日起停止私信群聊能力权限申请和开放。对历史已开通私信能力的外部移动/网站应用,平台将分批回收以下私信能力权限(历史开通过的将无法继续使用):近90天无调用的,平台将于公告发布之日起,直接回收私信能力权限;近90天有调用的,平台将于2025年5月19日起,分批回收私信能力权限。“
然后,5月15日继续通知:“从2025年5月19日起,平台将对有调用的应用能力权限进行分批回收,于2025年5月30日回收完毕。检测到你所属的移动/网站应用有私信能力的调用(有授权/有Webhook调用/有OpenAPI调用),为避免应用报错,请充分自查,并及时完成调整和改造。”
此时,我们手里的私信并没有真正回收。直到2025年11月26日的通知:
“为维护平台良好生态,避免隐私安全风险,平台自2025年4月14日起,对移动应用、网站应用的私信群聊能力权限做调整,详情请参考:移动/网站应用的私信群聊能力下线/回收公告。此前,你所属的移动/网站应用通过内部业务方申请了服务私信能力延期回收 。现因业务调整,重新启动回收:平台将于2025年12月26日回收服务私信能力权限。为避免应用影响,请充分自查并及时完成调整改造。”
至此,私信能力真正回收掉了。不再能收发私信。
那目前,普通客户可以拿到私信的只有2种方式:1、手机里的抖音app里;2、网页端的抖音创作者平台。
手机端要拿到私信,如果是协议式的,手机需要root的。不是协议式的,可以利用无障碍开发者方式获取,也是需要大量适配工作的,每升级一个版本都要重新适配。
本文只探讨网页端的抖音创作者平台里如何获取私信。
打开:https://creator.douyin.com/creator-micro/data/following/chat
可以看到抖音进行了特殊的处理,POST
https://imapi.snssdk.com/v2/message/get_by_user_init ,并且使用了
content-type :application/x-protobuf 的协议,protobuf是Google开发的新型网络协议,压缩率非常高,想破解这个,需要 .proto文件,如果没有这个.proto文件,工作量就会非常巨大。
常用的逆向破解方法:
即使没有原始的 .proto 文件,开发者通常会通过以下手段进行破解:
1、静态分析(反汇编): 如果是安卓 App 或 PC 软件,可以通过反编译代码(如使用 jadx 逆向 Java,或使用 IDA Pro 逆向 C++)。Protobuf 的解析代码通常会包含字段编号与变量名的映射关系,逆向者可以据此手动还原出 .proto 文件。
2、动态抓包与猜测: 使用工具(如 Charles 或 Fiddler)配合插件,可以将二进制流自动解析为结构化数据。通过观察数据的变化(例如:修改用户名后,哪个字段变了),可以推断出每个编号代表的含义。
3、自动化工具(protoc --decode): Google 官方工具支持在不知道结构的情况下,强制以“原始 Wire Format”打印数据。
我们这里不去破解,使用巧劲。因为我们的目的只是拿到解密后的明文,完全不需要走这么复杂的方案。
通过跟踪js调用堆栈,我们找到加解密的函数:
sendRequest(e, t) {
return (0,
n.__awaiter)(this, void 0, void 0, (function*() {
const r = yield this.send(e, "POST", this.encode(t));
return this.decode(r)
}
))
}
encode(e) {
return (0,
s.serialize)(e).buffer
}
decode(e) {
return o.im_proto.Response.create((0,
s.deserialize)(this.ctx, e))
}我们只需要在 decode 函数里,把解码后的明文数据打印出来即可。
这里可以采用浏览器打断点的方式,输出调试信息,也可以打入 logprint,输出日志。还可以使用 Chrome 本地覆盖(Local Overrides)的方式覆盖js,具体的方法就不展开细述了。
经过调试,可以看出发出请求时,包的结构为:
{
"t": {
"headers": {
"aid_new": 2906,
"app_name": "douyin_creator"
},
"body": {
"messages_per_user_init_v2_body": {
"cursor": {
"low": 0,
"high": 0,
"unsigned": false
}
}
},
"cmd": 203,
"sequence_id": {
"low": 10001,
"high": 0,
"unsigned": false
},
"refer": 3,
"token": "YSHGAwEBBwECBIEaKUQBZwFVqNYCl1B...",
"device_id": 0,
"sdk_version": "0.7.2-fix.1",
"build_number": "2f4951d:fix/douyin-creator-fix",
"inbox_type": 1,
"device_platform": "douyin_creator",
"auth_type": 3,
"biz": "douyin_creator",
"access": "web_sdk",
"sdk_cert": "LS0tLS1CRUdJTiBDRVJU...",
"ts_sign": "#KVBSUXpXvAQF1rk+r6db..."
},
"e": "https://imapi.snssdk.com/v2/message/get_by_user_init"
}接收到的明文数据如下:
{
"headers": {},
"cmd": 203,
"sequence_id": {
"low": 10001,
"high": 0,
"unsigned": false
},
"status_code": 0,
"error_desc": "OK",
"inbox_type": 1,
"body": {
"messages_per_user_init_v2_body": {
"messages": [
{
"ext": {
"old_client_message_id": "1766760981412",
"s:server_message_create_time": "1766760981721",
"s:client_message_id": "F6B2ECC9-6E87-48C0-AA3F-B5A87AE3ECAA"
},
"property_list": {},
"conversation_id": "0:1:65754607:378498777535",
"conversation_type": 1,
"server_message_id": {
"low": 325191205,
"high": 1766760979,
"unsigned": false
},
"index_in_conversation": {
"low": -814715360,
"high": 389409,
"unsigned": false
},
"conversation_short_id": {
"low": -1145011693,
"high": 1766749364,
"unsigned": false
},
"message_type": 7,
"sender": {
"low": 601110275,
"high": 881261,
"unsigned": false
},
"content": "{\"ai_ext\":\"{}\",\"scene\":\"\",\"aweType\":0,\"related_share_video\":{},\"mention_users\":[],\"text\":\"可以\",\"richTextInfos\":[]}",
"create_time": {
"low": 1529422832,
"high": 411,
"unsigned": false
},
"version": {
"low": 0,
"high": 0,
"unsigned": false
},
"status": 0,
"order_in_conversation": {
"low": 1328426240,
"high": 389409810,
"unsigned": false
},
"sec_sender": "MS4wLjABAAAAU6MJ8_tfwQayS"
}
],
"conversations": [
{
"conversation_id": "0:1:65754607676:3784987775350531",
"conversation_short_id": {
"low": -1145011693,
"high": 1766749364,
"unsigned": false
},
"conversation_type": 1,
"ticket": "1laWxwIOwRJOwVmklal0h8t5m4",
"first_page_participants": {
"participants": []
},
"participants_count": 2,
"is_participant": true
}
],
"per_user_cursor": {
"low": 1785435119,
"high": 412618,
"unsigned": false
},
"next_cursor": {
"low": 10,
"high": 0,
"unsigned": false
},
"has_more": true
}
},
"log_id": "20260227171607"
}这个消息一般只需要以下字段:
"ext": {
"s:server_message_create_time": "1754566357094", 【需要】
},
"conversation_id": "0:1:6575460:9967048",
"conversation_type": 1, 【这里1是私信(只处理1),2是系统通知,如群消息、视频分享等】
"message_type": 8,
"content": "",【这里是消息主体】
"sec_sender": "MS4wLjABAAAAH3pc3D" 【判断是否宿主,区别是谁发的私信】
此时,只是拿到了用户消息主体,但是还没有用户的昵称、头像这些,需要通过另一个接口去获取。获取用户昵称、头像的网址:
https://creator.douyin.com/aweme/v1/creator/im/user_detail/
获取到的响应是:
{
"extra": {
"now": 1768383888000
},
"status_code": 0,
"status_msg": "",
"user_list": [
{
"user": {
"SecretUseId": "MS4wLjABAAAAH3",
"ShareQrcodeUri": "8af300006af8206",
"ShortId": "10182213",
"avatar_thumb": {
"uri": "aweme-avatar/tos-cn-i-0813_",
"url_list": [
"https://p3.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-i-0813_",
]
},
"nickname": "小猪",
"signature": "签名。"
},
"user_id": "MS4wLjABAAAAH"
}
]
}用户昵称、头像可以通过加密uid关联起来,再一起入库即可。
到这里,我们就已经获取到了私信的全部信息了。至于如何自动化执行或保存,各位就各有自己的方法了。飘易目前是采用软件封装好自动化流程,目前稳定获取中。