哔哩哔哩开放平台调用手册

查询授权用户稿件与投稿分区

同步授权 UP 主的稿件状态并读取当前分区树,完整展示两个只读接口的动态签名。

官方资料核对 2026-10-15示例代码,未进行真实接口实测
← 返回平台功能

接入准备

  • 已通过当前企业开发者入驻与应用认证;官方入驻指引暂未开放个人申请,需营业执照、公函及一致的应用 ICP 主体。
  • 拥有同一应用的 Client ID 和 App Secret,并通过对应 scope 申请;用户授权与应用获批是两项独立条件。
  • 安装 Node.js 22;本页代码只从环境变量读自己的凭证,网站不会代收密钥或发送请求。
  • 应用已申请并获批 ARC_BASE,目标 UP 主已在官方授权页勾选该 scope;只有 USER_INFO 的令牌不能执行本场景。

准备环境变量

示例值需要替换为自己的凭证或资源 ID。代码在本机或服务端运行;密钥不应放进公开网页。

BILIBILI_CLIENT_ID
企业入驻、创建并审核应用后,在管理中心取得该应用 Client ID。
BILIBILI_APP_SECRET
同一应用的 App Secret,只放在本机或受保护服务端,不放入网页源码。
BILIBILI_ACCESS_TOKEN
目标 UP 主已同意该应用所需 scope 后,由服务端以 OAuth code 交换的有效令牌。
终端
export BILIBILI_CLIENT_ID='replace_with_your_client_id'
export BILIBILI_APP_SECRET='replace_with_your_app_secret'
export BILIBILI_ACCESS_TOKEN='replace_with_your_user_access_token'

以上 export 适用于 macOS / Linux 的终端。按调用步骤保存代码文件,再在同一终端执行。

调用步骤

  1. 01

    先完成官方 OAuth 授权与服务端令牌交换;可按账号资料手册中的流程准备,新增 ARC_BASE 后需要 UP 主重新授权。

  2. 02

    设置下方三项凭证,分别将两个独立示例保存为 request.mjs 并使用 node request.mjs 执行;本页只读,不上传或发布稿件。

  3. 03

    稿件查询从 pn=1 开始,ps 不超过 50。结合 data.page.total 与返回 list 判断是否继续读取下一页;按实际配额分页,不做无界循环或紧密轮询。

  4. 04

    读取 addit_info.state 和 reject_reason 了解审核情况;只将本次分区树返回的二级 id 用于投稿表单 tid,不把父分区或过期静态列表硬编码。

调用 01

分页查询授权用户视频稿件

查询当前授权 UP 主的稿件状态;本例取第 1 页 20 项,包含全部发布状态。

GEThttps://member.bilibili.com/arcopen/fn/archive/viewlist?pn=1&ps=20&status=all

请求头

Accept
application/json
Content-Type
application/json
access-token
${BILIBILI_ACCESS_TOKEN}
x-bili-accesskeyid
${BILIBILI_CLIENT_ID}
x-bili-signature-version
2.0
x-bili-signature-method
HMAC-SHA256
x-bili-content-md5
d41d8cd98f00b204e9800998ecf8427e
x-bili-timestamp
运行时生成 Unix 秒时间戳
x-bili-signature-nonce
运行时生成唯一随机串
Authorization
运行时由下方完整代码计算 HMAC-SHA256

参数说明

参数表可左右滑动,查看完整说明。

字段 / 位置类型 / 必填说明
access-tokenHeaderstring必填当前 UP 主向同一应用授权后取得的 access_token;不是网页登录 Cookie,不加 Bearer 前缀。
x-bili-accesskeyidHeaderstring必填开放平台应用 client_id,必须与 app_secret 及令牌所属应用一致。
x-bili-content-md5Headerstring必填本页 GET 无请求体,使用空字符串的 MD5 小写十六进制 d41d8cd98f00b204e9800998ecf8427e。
x-bili-timestamp / x-bili-signature-nonceHeaderstring必填Unix 秒时间戳及每次新生成的唯一随机串;时间戳偏离当前时间不能超过官方规定的 10 分钟。
x-bili-signature-method / x-bili-signature-versionHeaderstring必填固定 HMAC-SHA256 与 2.0。
AuthorizationHeaderstring必填将 x-bili- 头名按字典序排序,以 key:value 和 LF 连接,末尾无 LF;用 app_secret 做 HMAC-SHA256,结果为小写十六进制。
Accept / Content-TypeHeaderstring必填本例均为 application/json;GET 不发送 JSON body。
pnQueryinteger必填页码,最小 1;示例 1。翻页修改 URL 中的 pn。
psQueryinteger必填每页数量 1–50;示例 20。
statusQuerystring可选all 全部、is_pubing 发布中、pubed 已发布、not_pubed 未发布;省略为全部。本例 all。

调用代码

替换示例 ID 与请求体内容后运行。

Node.js
import { createHash, createHmac, randomUUID } from 'node:crypto';
const required = (name) => {
  const value = process.env[name];
  if (!value || value.includes('replace_with_')) throw new Error(`请设置自己的 ${name}`);
  if (/[\r\n]/.test(value)) throw new Error(`${name} 不能包含换行`);
  return value;
};
const clientId = required('BILIBILI_CLIENT_ID');
const secret = required('BILIBILI_APP_SECRET');
const token = required('BILIBILI_ACCESS_TOKEN');
const url = 'https://member.bilibili.com/arcopen/fn/archive/viewlist?pn=1&ps=20&status=all';
// 本例为 GET,无 body。空字符串的 MD5 仍需发送,不能省略或改成 {} 的 MD5。
const signingHeaders = {
  'x-bili-accesskeyid': clientId,
  'x-bili-content-md5': createHash('md5').update('', 'utf8').digest('hex'),
  'x-bili-signature-method': 'HMAC-SHA256',
  'x-bili-signature-nonce': randomUUID(),
  'x-bili-signature-version': '2.0',
  'x-bili-timestamp': String(Math.floor(Date.now() / 1000)),
};
// 只对 x-bili- 请求头排序;每行 key:value,以 LF 分隔,最后一行不追加换行。
const canonical = Object.keys(signingHeaders).sort()
  .map((key) => `${key}:${signingHeaders[key]}`).join('\n');
const authorization = createHmac('sha256', Buffer.from(secret, 'utf8'))
  .update(canonical, 'utf8').digest('hex');
const response = await fetch(url, {
  method: 'GET', redirect: 'error', signal: AbortSignal.timeout(20000),
  headers: { ...signingHeaders, 'access-token': token, Authorization: authorization,
    Accept: 'application/json', 'Content-Type': 'application/json' },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
let result;
try { result = JSON.parse(await response.text()); }
catch { throw new Error('平台未返回有效 JSON,检查服务状态及请求地址'); }
if (result.code !== 0) {
  throw new Error(`业务错误 ${result.code}: ${result.message || ''}; request_id=${result.request_id || ''}`);
}
if (!result.data || typeof result.data !== 'object') throw new Error('响应缺少预期 data');
console.log(JSON.stringify(result.data, null, 2));
// 输出只来自该授权用户;生产系统应限制访问并按用户同意范围保存。

返回示例

官方响应的字段节选,非完整稿件对象;示例 ID、标题和数字为说明值。data.list 可能为空,非开放浏览稿件 video_info 可为空;查看 addit_info.state 与 reject_reason。 以下为结构示意,非本站实测结果。

JSON
{
  "code": 0,
  "message": "0",
  "request_id": "example_request_id",
  "data": {
    "list": [
      {
        "resource_id": "example_resource_id",
        "title": "示例稿件",
        "tid": 21,
        "addit_info": {
          "state": 0,
          "state_desc": "开放浏览",
          "reject_reason": ""
        },
        "video_info": {
          "duration": 30,
          "share_url": "https://www.bilibili.com/video/example_resource_id"
        }
      }
    ],
    "page": {
      "pn": 1,
      "ps": 20,
      "total": 1
    }
  }
}

常见错误与排查

4002 / 4008 / 127002签名异常或请求体 MD5 不匹配。
核对同一应用的 client_id 与 app_secret、全部六个 x-bili- 头、LF 分隔且末尾无换行;GET 应签空字符串,不要把 {} 当请求体。
4003 / 4004请求过期或重复请求。
校准机器时钟、使用秒级时间戳,并为每次请求生成新 nonce,不要重复复制文档中的固定签名。
127001 / 127011令牌无效或用户未授权所需接口。
确认令牌有效期、应用归属及用户已勾选的 scope;新增 scope 需重新引导授权。不要反复重试无效令牌。
127005 / 127006 / 127007 / 127305主体、应用、接口权限或白名单未通过。
到管理中心核对认证及权限审批状态;官方白名单限制不能靠换账号 Cookie 解决。
127009 / 127306接口次数达到上限、繁忙或频率过高。
停止紧密重试,缓存结果并按实际限额退避;大量使用需向平台运营确认配额,本文不杜撰统一 QPS。

调用注意

  • 下方仅提供 Node.js 22 完整示例,使用内置 crypto 和 fetch。保存为 request.mjs,执行 node request.mjs;不提供缺少动态签名的伪 cURL。
  • 所有 x-bili- 头参与签名;access-token、Accept、Content-Type 与 Authorization 不加入该签名串。HTTP 成功后仍须检查业务 code=0。
  • 官方接口页未列按次价格或统一配额,需在应用实际开通时确认;本页仅完成协议与离线检查,未真实调用。
调用 02

读取当前投稿分区树

为自己的投稿界面读取分区 id、名称、描述及 children;选二级分区作为 tid。

GEThttps://member.bilibili.com/arcopen/fn/archive/type/list

请求头

Accept
application/json
Content-Type
application/json
access-token
${BILIBILI_ACCESS_TOKEN}
x-bili-accesskeyid
${BILIBILI_CLIENT_ID}
x-bili-signature-version
2.0
x-bili-signature-method
HMAC-SHA256
x-bili-content-md5
d41d8cd98f00b204e9800998ecf8427e
x-bili-timestamp
运行时生成 Unix 秒时间戳
x-bili-signature-nonce
运行时生成唯一随机串
Authorization
运行时由下方完整代码计算 HMAC-SHA256

参数说明

参数表可左右滑动,查看完整说明。

字段 / 位置类型 / 必填说明
access-tokenHeaderstring必填当前 UP 主向同一应用授权后取得的 access_token;不是网页登录 Cookie,不加 Bearer 前缀。
x-bili-accesskeyidHeaderstring必填开放平台应用 client_id,必须与 app_secret 及令牌所属应用一致。
x-bili-content-md5Headerstring必填本页 GET 无请求体,使用空字符串的 MD5 小写十六进制 d41d8cd98f00b204e9800998ecf8427e。
x-bili-timestamp / x-bili-signature-nonceHeaderstring必填Unix 秒时间戳及每次新生成的唯一随机串;时间戳偏离当前时间不能超过官方规定的 10 分钟。
x-bili-signature-method / x-bili-signature-versionHeaderstring必填固定 HMAC-SHA256 与 2.0。
AuthorizationHeaderstring必填将 x-bili- 头名按字典序排序,以 key:value 和 LF 连接,末尾无 LF;用 app_secret 做 HMAC-SHA256,结果为小写十六进制。
Accept / Content-TypeHeaderstring必填本例均为 application/json;GET 不发送 JSON body。

调用代码

替换示例 ID 与请求体内容后运行。

Node.js
import { createHash, createHmac, randomUUID } from 'node:crypto';
const required = (name) => {
  const value = process.env[name];
  if (!value || value.includes('replace_with_')) throw new Error(`请设置自己的 ${name}`);
  if (/[\r\n]/.test(value)) throw new Error(`${name} 不能包含换行`);
  return value;
};
const clientId = required('BILIBILI_CLIENT_ID');
const secret = required('BILIBILI_APP_SECRET');
const token = required('BILIBILI_ACCESS_TOKEN');
const url = 'https://member.bilibili.com/arcopen/fn/archive/type/list';
// 本例为 GET,无 body。空字符串的 MD5 仍需发送,不能省略或改成 {} 的 MD5。
const signingHeaders = {
  'x-bili-accesskeyid': clientId,
  'x-bili-content-md5': createHash('md5').update('', 'utf8').digest('hex'),
  'x-bili-signature-method': 'HMAC-SHA256',
  'x-bili-signature-nonce': randomUUID(),
  'x-bili-signature-version': '2.0',
  'x-bili-timestamp': String(Math.floor(Date.now() / 1000)),
};
// 只对 x-bili- 请求头排序;每行 key:value,以 LF 分隔,最后一行不追加换行。
const canonical = Object.keys(signingHeaders).sort()
  .map((key) => `${key}:${signingHeaders[key]}`).join('\n');
const authorization = createHmac('sha256', Buffer.from(secret, 'utf8'))
  .update(canonical, 'utf8').digest('hex');
const response = await fetch(url, {
  method: 'GET', redirect: 'error', signal: AbortSignal.timeout(20000),
  headers: { ...signingHeaders, 'access-token': token, Authorization: authorization,
    Accept: 'application/json', 'Content-Type': 'application/json' },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
let result;
try { result = JSON.parse(await response.text()); }
catch { throw new Error('平台未返回有效 JSON,检查服务状态及请求地址'); }
if (result.code !== 0) {
  throw new Error(`业务错误 ${result.code}: ${result.message || ''}; request_id=${result.request_id || ''}`);
}
if (!result.data || typeof result.data !== 'object') throw new Error('响应缺少预期 data');
console.log(JSON.stringify(result.data, null, 2));
// 输出只来自该授权用户;生产系统应限制访问并按用户同意范围保存。

返回示例

只保留一个父分区和子分区展示树状结构。此处 ID、名称用于结构说明,不是当前完整分区目录;正式投稿以本次接口返回的二级分区为准。 以下为结构示意,非本站实测结果。

JSON
{
  "code": 0,
  "message": "0",
  "request_id": "example_request_id",
  "data": [
    {
      "id": 160,
      "parent": 0,
      "name": "生活",
      "description": "一级分区说明",
      "children": [
        {
          "id": 21,
          "parent": 160,
          "name": "日常",
          "description": "二级分区说明"
        }
      ]
    }
  ]
}

常见错误与排查

4002 / 4008 / 127002签名异常或请求体 MD5 不匹配。
核对同一应用的 client_id 与 app_secret、全部六个 x-bili- 头、LF 分隔且末尾无换行;GET 应签空字符串,不要把 {} 当请求体。
4003 / 4004请求过期或重复请求。
校准机器时钟、使用秒级时间戳,并为每次请求生成新 nonce,不要重复复制文档中的固定签名。
127001 / 127011令牌无效或用户未授权所需接口。
确认令牌有效期、应用归属及用户已勾选的 scope;新增 scope 需重新引导授权。不要反复重试无效令牌。
127005 / 127006 / 127007 / 127305主体、应用、接口权限或白名单未通过。
到管理中心核对认证及权限审批状态;官方白名单限制不能靠换账号 Cookie 解决。
127009 / 127306接口次数达到上限、繁忙或频率过高。
停止紧密重试,缓存结果并按实际限额退避;大量使用需向平台运营确认配额,本文不杜撰统一 QPS。

调用注意

  • 下方仅提供 Node.js 22 完整示例,使用内置 crypto 和 fetch。保存为 request.mjs,执行 node request.mjs;不提供缺少动态签名的伪 cURL。
  • 所有 x-bili- 头参与签名;access-token、Accept、Content-Type 与 Authorization 不加入该签名串。HTTP 成功后仍须检查业务 code=0。
  • 官方接口页未列按次价格或统一配额,需在应用实际开通时确认;本页仅完成协议与离线检查,未真实调用。

注意事项

  • 稿件接口只查询授权用户,不能填写其他 UID 变成全站视频搜索。返回空列表不表示签名失败。
  • 取得稿件记录不等于视频已经开放浏览;state=0 才是开放浏览,其他状态的 video_info 可能为空。
  • 分区和稿件列表是两次独立请求,每次生成新的 nonce 与时间戳;复用过去的 Authorization 会触发过期或重复错误。
  • 本组接口公开文档未给出按次单价、固定 QPS 或日额度,开通时需向平台确认;未做真实授权或接口调用。

核验来源

本站按官方资料整理本场景的必要调用步骤与代码,覆盖范围以本页列出的接口为准。官方资料用于追溯规范及查看变更。

  1. 01
    开发者入驻与主体认证核验日期 2026-10-15
  2. 02
  3. 03
  4. 04
    查询用户视频稿件列表核验日期 2026-10-15
  5. 05
  6. 06
    官方 C# 公共签名实现核验日期 2026-10-15
  7. 07
    投稿分区查询核验日期 2026-10-15

哔哩哔哩开放平台的其他调用手册

← 返回哔哩哔哩开放平台的全部功能