← 返回博客

百度统计 API 接入血泪录:14 次鉴权失败之后

2026-05-17 · 约 10 分钟

官网上线第二天,我需要一个自动日报——每天早晚各拉一次 PV、UV、跳出率,异常自动告警。手动导出 PDF 不是办法。

百度统计有开放 API。我想着,注册个应用,拿个 token,调个接口,半小时搞定。

三天之后,我对着终端里第十四次返回的报错,终于找到了那组正确的参数。

这篇文章记录整个过程。不是教程——教程应该告诉你正确的做法。这是踩坑录,告诉你哪些路走不通,以及为什么。

起点:一张 PDF 和一组凭证

官网上线的第一天,我在百度统计后台看到这样的数据:

日期PVUVIP跳出率
5/151110%
5/1660141766.67%

数据是好的,但只能手动看。我需要 API。

手里有的凭证:百度商业开发者中心签发的 JWT(HS384 签名,aud: "百度统计"),以及一个应用 AppKey f4909ca6e7

第一回合:标准 REST API(失败 ×3)

直觉告诉我,百度统计开放 API 用 OAuth 2.0。把 JWT 当 access_token 往标准端点扔:

GET https://openapi.baidu.com/rest/2.0/tongji/report/getSiteList
   ?access_token=<JWT>

→ error_code: 110
→ "Access token invalid or no longer valid"

换到 api.baidu.comaip.baidubce.com,同样 110。连 Authorization: Bearer header 都试了,返回 "API not supported by authorization"。

这不是鉴权方式不对——是这个 token 根本不走标准 OAuth 通路。

第二回合:JSON-RPC(失败 ×4)

查文档发现,百度商业开发者中心的应用走的是 JSON-RPC 格式:

POST https://api.baidu.com/json/tongji/v1/ReportService/getSiteList
{
  "header": {
    "username": "82454026",
    "token": "<JWT>",
    "account_type": 1
  },
  "body": {}
}

→ code: 84261
→ "The token is invalid in encrypt"

有进展——不再是 110,API 认出这个字段了,只是加密格式不对。我试了 accessTokenauth_tokenapiToken 各种字段名,只有 token 字段被识别。但内容永远不对。

又试了 AppKey 代替 JWT:

"token": "f4909ca6e7"

→ code: 8001
→ "Server internal error, please try again later"

鉴权通过了!但所有后端服务——Tongji、SEM AccountService——统一返回 8001 系统错误。不是账号问题,是整个服务集群拒绝了这个 token 的请求。

我还换了 account_type 的六个值(1/2/3/5/9/11),全部 8001。显然不是参数问题,是权限层面的阻断——这个 AppKey 注册的是移动统计(Schema: mtj),没有网站统计 API 的调用权限。

第三回合:OAuth 换发(失败 ×2)

也许需要走 OAuth 换发流程,把 AppKey + Secret Key 换成真正的 access_token:

POST https://openapi.baidu.com/oauth/2.0/token
grant_type=client_credentials
&client_id=13bd5049a676d10737959932102ec557
&client_secret=f4909ca6e7

→ "unknown client id"

appId 不是 OAuth client_id。尝试 grant_type=jwt-bearerrefresh_token ——全部不支持。

百度商业开发者中心的应用体系,和百度开放平台的 OAuth 体系,是两套完全不同的东西。

第四回合:直接账号鉴权(失败 ×3)

回到 JSON-RPC,把百度账号密码当 accessToken 传:

"userName": "xierongji",
"accessToken": "wuji.198919"

→ code: 89406
→ "The access token you provided is invalidate"

用中文名 "谢荣极"、"谢秉极",UID "82454026",手机号——全部 81020("username information is incorrect")。这个 userName 字段只认百度账号登录名,也就是 xierongji

但即使登录名对了,accessToken 传明文密码也不行。百度商业 API 的 accessToken 字段要的不是密码,是一个加密后的凭证。

破局:把 JWT 放进 accessToken

回到第一性原理。我手里有三个东西:

JWT 在 token 字段被拒(加密不匹配),但 JWT 本身就是一个标准的鉴权凭证。为什么不放进 accessToken

POST https://api.baidu.com/json/tongji/v1/ReportService/getSiteList
{
  "header": {
    "userName": "xierongji",
    "accessToken": "<JWT>",
    "account_type": 1
  },
  "body": {}
}

返回的不是错误,是 code: 91021601——"账户受限,暂不支持该操作"。这不一样了。鉴权通过了,只是数据获取权限还没开。

我用 getSiteList 先试——这个接口不需要数据权限:

→ status: 0 (success)

{
  "list": [{
    "domain": "jingxuanyoupin.icu",
    "site_id": 23188112,
    "status": 0
  }]
}

通了。而且发现了一个关键事实:

站点 ID 是 23188112,不是 JWT 里的 uid 82454026(那是用户 ID)。

用正确的 site_id 调 getData

POST /json/tongji/v1/ReportService/getData
body: {
  "site_id": "23188112",
  "start_date": "20260516",
  "end_date": "20260517",
  "metrics": "pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time",
  "method": "overview/getTimeTrendRpt"
}

→ status: 0 (success)

data: [
  [60, 14, 17, 66.67, 624],   // 5/16
  ["--", "--", "--", "--", "--"]  // 5/17(当日,未出数据)
]

和 PDF 报告完全一致。

最终方案全景

折腾三天的最终结论,正确的鉴权组合只有这一种:

参数踩坑
API 格式JSON-RPC (POST)不是 REST
端点/json/tongji/v1/ReportService/getData不是 rest/2.0 也不是短信服务
userNamexierongji(百度账号登录名)不是中文名、UID、手机号
accessToken商业开发者中心 JWT不是 token 字段、不是 password、不是 AppKey
site_id23188112不是 82454026(那是 UID)
account_type1全部试过了,就是 1

完整的错误码演变路径:

110    → 标准 REST:access_token 无效
84261  → JSON-RPC token 字段:JWT 加密不匹配
8001   → JSON-RPC token 字段:AppKey 权限不足(系统错误)
81020  → userName 字段:值不是账号登录名
89406  → accessToken 字段:明文密码不是有效 token
91021  → 鉴权通过,site_id 错误导致无权限
0      → ✅ 通了

四个完全不同的鉴权体系在同一个域名下并行存在——这就是百度商业 API 的"特色"。没有哪份文档会告诉你 "userName 要传登录名、accessToken 要传 JWT" 这个组合。你得自己试。

落地:自动日报

调通之后的事就简单了。写了一个 Node.js 脚本,两个 Cron 定时触发:

JWT 存在 600 权限的文件里,.gitignore 豁免,脚本运行时读取。不依赖任何第三方 SDK,纯 Node.js 原生 HTTPS 模块,不到 60 行代码。

如果重来一次

我会做三件事:

  1. 先用 getSiteList 验证鉴权。这个接口不需要数据权限,用来测试 userName + accessToken 组合最合适。
  2. 不要假设 UID 就是 site_id。用 API 返回的真实 site_id,而不是 JWT 里的 uid。
  3. 认准 JSON-RPC 格式。百度商业开发者中心的应用不走 REST,不走 OAuth,只走 api.baidu.com/json/ 这条 JSON-RPC 通道。

至于百度为什么要在同一个平台塞进四种互不兼容的鉴权方式——这是一个比 API 鉴权更难回答的问题。

标签:百度统计 · API 踩坑 · JSON-RPC · 自动化运维 · 鉴权调试

🛠️ 需要类似系统?

AI系统集成 · 自动化管线开发 · 全栈定制——咨询免费,能做就做。

💬 微信:星尘和光文化传媒 | 🌐 官网 →

公众号二维码

📱 关注公众号「星尘和光文化传媒」

每周推送 AI 实战技术文章、全栈开发案例和自动化管线拆解。
不写广告,只写踩坑录。