jackwener/OpenCLI · error · AuthRequiredError
Bilibili ${label} API requires login or permission: ${messag
Error message
Bilibili ${label} API requires login or permission: ${message} (${payload.code}) What it means
The Bilibili API responded with valid JSON but a non-zero `code`, and isAuthLikeBilibiliError classified it as an auth problem (code -101 not logged in, -111 csrf/token invalid, -403 forbidden, or a message mentioning csrf/登录/账号/权限/forbidden/permission/login). The library maps this to AuthRequiredError so callers know cookies/login must be supplied rather than retrying blindly.
Source
Thrown at clis/bilibili/utils.js:233
/**
* Bilibili write APIs return a JSON envelope `{ code, message, data }`. A non-zero
* `code` carries either an auth/permission failure (login expired, CSRF rejected,
* forbidden) or an application-level error (rate limit, validation, etc.). These
* two helpers route the envelope to the right typed error so every write adapter
* surfaces login problems as `AuthRequiredError`, not a generic execution error.
*/
export function isAuthLikeBilibiliError(code, message) {
return code === -101 || code === -111 || code === -403 || /csrf|登录|账号|权限|forbidden|permission|login/i.test(String(message ?? ''));
}
export function requireOkPayload(payload, label) {
if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'code')) {
throw new CommandExecutionError(`Bilibili ${label} API returned a malformed payload`);
}
if (payload.code !== 0) {
const message = payload.message ?? 'unknown error';
if (isAuthLikeBilibiliError(payload.code, message)) {
throw new AuthRequiredError('bilibili.com', `Bilibili ${label} API requires login or permission: ${message} (${payload.code})`);
}
throw new CommandExecutionError(`Bilibili ${label} API failed: ${message} (${payload.code})`);
}
return payload.data;
}
/**
* POST form-encoded params to a Bilibili API endpoint.
* Runs inside the logged-in browser context and auto-attaches the bili_jct CSRF token,
* which Bilibili requires on every authenticated write request.
*/
export async function apiPost(page, path, opts = {}) {
const params = opts.params ?? {};
const stringified = Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)]));
const paramsJs = JSON.stringify(stringified);
const urlJs = JSON.stringify(`https://api.bilibili.com${path}`);
return page.evaluate(`
async () => {View on GitHub (pinned to 49907e53dc)
Solutions
- Refresh your Bilibili cookies (re-export SESSDATA and bili_jct from a logged-in browser) and pass them to the client.
- Ensure POST requests include the bili_jct CSRF token in the form data.
- Verify the account actually has permission for the target content (private/favorites/membership).
- Catch AuthRequiredError in your code and prompt the user to log in instead of retrying.
Example fix
// before
const page = await newPage(); // no cookies -> code -101
const nav = await getNavData(page);
// after
const ctx = await browser.newContext();
await ctx.addCookies([{ name: 'SESSDATA', value: process.env.BILI_SESSDATA, domain: '.bilibili.com', path: '/' },
{ name: 'bili_jct', value: process.env.BILI_JCT, domain: '.bilibili.com', path: '/' }]);
const page = await ctx.newPage(); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify cookies work before heavy calls
const nav = await (await fetch('https://api.bilibili.com/x/web-interface/nav', { headers: { cookie } })).json();
if (nav.code !== 0 || !nav.data?.isLogin) throw new Error('Bilibili login required: refresh SESSDATA/bili_jct'); Try / catch
try { const data = requireOkPayload(payload, 'history'); } catch (e) { if (e instanceof AuthRequiredError) { await promptLoginOrRefreshCookies(); } else throw e; } Prevention
- Keep SESSDATA and bili_jct fresh; re-export cookies when they expire.
- Include bili_jct (CSRF) on all POST endpoints.
- Don't use the account from many IPs simultaneously to avoid risk control.
- Catch AuthRequiredError explicitly and route to your login flow instead of retrying.
When it happens
Trigger: Calling a Bilibili API that requires login (history, favorites, self info, etc.) with no or expired SESSDATA cookie; missing or stale bili_jct CSRF token; accessing content you lack permission for (private video, region-locked, membership-only).
Common situations: Cookies expired after Bilibili rotated them or you logged out elsewhere; copying only SESSDATA without bili_jct for POST endpoints; running headless/CI without a cookie file; account risk-controlled by Bilibili.
Related errors
- Bilibili ${label} API requires login or permission: ${messag
- bilibili.com
- Pinterest did not set a csrftoken cookie for this page
- Not logged into x.com (no ct0 cookie)
- Not logged into x.com (no ct0 cookie)
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/a403a2b9729192ef.
Report an issue: GitHub.