百趣云 - 淘宝
type: channel
link: https://teawhites.cn/index.php/tag/%E6%B7%98%E5%AE%9D/
items: 淘宝 h5 mtop 签名：_m_h5_tk 体系详解

淘宝 h5 mtop 签名：_m_h5_tk 体系详解
type: item
date: 2026-08-28T05:11:25+08:00
description: mtop 签名：阿里系的"祖传配方"淘宝 H5 的 mtop 接口签名是阿里系应用最广的一套方案，公式一句话说完：sign = md5(token + "&" + t + "&" + appKey + "&" + data)token：cookie _m_h5_tk 的下划线前段（_m_h5_tk=abc123_def456，取 abc123）t：毫秒时间戳appKey：H5 端固定 12574478（不同端不同值，App 端是另一套）data：业务参数的紧凑 JSON 字符串公式简单到令人发指，但这套体系的精髓不在算法，在 token 的生命周期管理。token 的"过期-刷新"循环_m_h5_tk 不是登录才有的，匿名访问也会下发。它的获取方式很鸡贼：你直接请求接口，它故意返回令牌过期，同时在响应头里种新 token：响应: {"ret":["FAIL_SYS_TOKEN_EXOIRED::令牌过期"]} 响应头: Set-Cookie: _m_h5_tk=abc123_def456; ...所以完整的客户端必须实现这个循环：import hashlib, json, time, requests class MtopClient: def __init__(self): self.session = requests.Session() self.app_key = '12574478' def _token(self): tk = self.session.cookies.get('_m_h5_tk', domain='.taobao.com') return tk.split('_')[0] if tk else '' def request(self, api, data, v='1.0', retry=True): t = str(int(time.time() * 1000)) data_str = json.dumps(data, separators=(',', ':')) sign = hashlib.md5(f"{self._token()}&{t}&{self.app_key}&{data_str}".encode()).hexdigest() resp = self.session.get( f'https://h5api.m.taobao.com/h5/{api}/{v}/', params={'jsv': '2.7.4', 'appKey': self.app_key, 't': t, 'sign': sign, 'api': api, 'v': v, 'type': 'originaljson', 'dataType': 'json', 'data': data_str} ) ret = resp.json() if any('TOKEN_EXOIRED' in r or '令牌过期' in r for r in ret.get('ret', [])): if retry: return self.request(api, data, v, retry=False) # cookie 已自动种下新 token return ret注意 retry=False 防死循环——刷新后再失败就是别的问题了。精髓：六个实测坑点data 序列化是头号杀手。必须 separators=(',', ':') 紧凑无空格，key 顺序保持接口定义原样（Python dict 保序，按抓包顺序构造即可）。多空格、换行、key 乱序，签名全废。调试时把浏览器抓的 data 原文和你的生成结果做字符串 diff。appKey 分端不通用。H5 是 12574478，但同一个接口在 App 端是另一个 appKey，token 体系也不同。跨端抄参数必挂。_m_h5_tk 有配套兄弟 _m_h5_tk_enc。部分敏感接口两个都校验，清 cookie 时要一起处理。域名体系。接口域名是 h5api.m.taobao.com，但 cookie 种在 .taobao.com 域。天猫业务走 h5api.m.tmall.com，token 不通用。签名对了只是入场券。高频请求会触发 FAIL_SYS_ACCESS_DENIED 或要求滑块验证（x5sec 体系），那是行为风控，签名层无解，只能控速 + 代理池。type 参数影响返回格式。originaljson 返回纯 json，jsonp 返回回调包裹——协议模拟用前者，别给自己找解析麻烦。一个完整的调试方法论签名不对时按这个顺序排查：抓浏览器真实请求，把 data 参数原文复制出来，和你的 data_str 逐字符对比确认 token 是下划线前段，没把 _def456…