DIYgod/RSSHub · error · Error

Bilibili browser response does not contain video list data

Error message

Bilibili browser response does not contain video list data

What it means

Thrown by fetchVideoListFromBrowser after Bilibili's video-list XHR was captured but its JSON body contained a falsy `data` field (response.code was 0 yet no payload). This is the browser-mode fallback path; getVideoList only reaches it after the plain API request already failed. It signals that Bilibili served a well-formed but empty/envelope-only response to the headless browser, so there is genuinely nothing to render.

Source

Thrown at lib/routes/bilibili/video.ts:204

            await page.route('**/*', (route) => {
                const request = route.request();
                allowedBrowserRequestTypes.has(request.resourceType()) ? route.continue() : route.abort();
            });
        },
        gotoConfig: { waitUntil: 'domcontentloaded' },
    });

    try {
        const response = await waitForVideoListResponseFromVideoPage(page, videoUrl);
        const data = (await response.json()) as VideoListResponse;
        if (data.code) {
            logger.error(JSON.stringify(data.data));
            throw new Error(`Got error code ${data.code} while fetching in browser mode: ${data.message}`);
        }

        if (!data.data) {
            throw new Error('Bilibili browser response does not contain video list data');
        }

        return data.data;
    } finally {
        await destroy();
    }
}

async function getVideoList(uid: string): Promise<VideoListData> {
    try {
        return await fetchVideoListFromApi(uid);
    } catch (error) {
        logger.warn(`[bilibili/video] API request failed, falling back to browser mode: ${error}`);
        return fetchVideoListFromBrowser(uid);
    }
}

async function handler(ctx: Context) {

View on GitHub (pinned to bed535e087)

Solutions

  1. Set a valid BILIBILI_COOKIE_{uid} (at least SESSDATA) in config so the browser session is authenticated.
  2. Verify Playwright browsers are installed (`npx playwright install chromium`) and that resource-type allow-list includes xhr/document.
  3. Check the uid actually has public videos on the source site; if not, the empty response is legitimate.
  4. Inspect server logs for the prior API-mode failure that forced the browser fallback and address that root cause first.

Example fix

// No code fix recommended — this is data-shape validation.
// Mitigate by ensuring an authenticated cookie is applied:
// config: BILIBILI_COOKIE_<uid> with a fresh SESSDATA
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on the browser response, validate the envelope shape.
const data = (await response.json()) as VideoListResponse;
if (data.code) { throw new Error(`code ${data.code}`); }
if (!data.data || !Array.isArray(data.data.list?.vlist)) {
    throw new Error('Bilibili browser response does not contain video list data');
}

Type guard

const isVideoListData = (d: unknown): d is VideoListData =>
    typeof d === 'object' && d !== null &&
    Array.isArray((d as any).list?.vlist);

Try / catch

// getVideoList already wraps API in try/catch and falls back to browser.
// Wrap the browser call too and degrade gracefully rather than throwing raw:
try { return await fetchVideoListFromBrowser(uid); }
catch (e) { logger.error(`browser fallback failed: ${e}`); return { list: { vlist: [] } }; }

Prevention

When it happens

Trigger: The headless Playwright page loaded space.bilibili.com/{uid}/video and waitForVideoListResponseFromVideoPage resolved an XHR whose JSON has `code: 0` but no `data` key (or `data: null`). Common when the uid has zero public videos, the space requires login the cookie does not satisfy, or Bilibili anti-bot returns a stub response to the detected headless client.

Common situations: Running RSSHub without a valid BILIBILI_COOKIE_*; Bilibili tightening headless detection after a version bump; requesting a uid that deleted all videos or set them private; Playwright/Chromium not installed so resource blocking aborts the real XHR.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/e798a2b6d9d41ad5. Report an issue: GitHub.