{"_id":"@bryan-kuang/bilibili-audio-extractor","name":"@bryan-kuang/bilibili-audio-extractor","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bryan-kuang/bilibili-audio-extractor","version":"0.1.0","description":"Extract audio stream URLs and metadata from Bilibili videos using the native web API — WBI request signing included, no yt-dlp required.","license":"MIT","author":{"name":"Bryan Kuang"},"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.json","test":"jest","prepublishOnly":"npm test && npm run build"},"keywords":["bilibili","audio","extractor","wbi","playurl","dash","bv","b23"],"engines":{"node":">=20.0.0"},"devDependencies":{"@jest/globals":"^29.7.0","@types/node":"^20.12.12","jest":"^29.7.0","ts-jest":"^29.1.5","typescript":"^5.4.5"},"gitHead":"19f0374523588a43739789f4e7208ba9395cade9","_id":"@bryan-kuang/bilibili-audio-extractor@0.1.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-vbiC9QepwMSeEibWGCXGG8zze8gUp7tvA3fxXxilK1fO5ZJkk/ETvWHvBSNQZMtbF+W2lku0GydW6uJs3eT6WQ==","shasum":"3725972e47901219133a3a851885e764c5f48062","tarball":"https://registry.npmjs.org/@bryan-kuang/bilibili-audio-extractor/-/bilibili-audio-extractor-0.1.0.tgz","fileCount":12,"unpackedSize":44795,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD8e6Ll2EX+VyVvQPZMblectEFsuxlHP0sHfEpuDjFalAIhAPMfPm/Ejqd/ddSDeXXSADQHyXISiy36tPg8sqBVFhYO"}]},"_npmUser":{"name":"bryan-kuang","email":"BryanKuang@outlook.com"},"directories":{},"maintainers":[{"name":"bryan-kuang","email":"BryanKuang@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bilibili-audio-extractor_0.1.0_1783966930074_0.8593321507024967"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-13T18:22:09.928Z","0.1.0":"2026-07-13T18:22:10.225Z","modified":"2026-07-13T18:22:10.480Z"},"maintainers":[{"name":"bryan-kuang","email":"BryanKuang@outlook.com"}],"description":"Extract audio stream URLs and metadata from Bilibili videos using the native web API — WBI request signing included, no yt-dlp required.","keywords":["bilibili","audio","extractor","wbi","playurl","dash","bv","b23"],"author":{"name":"Bryan Kuang"},"license":"MIT","readme":"# @bryan-kuang/bilibili-audio-extractor\n\nExtract audio stream URLs and metadata from Bilibili videos using the native web API. TypeScript, zero dependencies, no yt-dlp or headless browser required.\n\n```bash\nnpm install @bryan-kuang/bilibili-audio-extractor\n```\n\n```ts\nimport { BilibiliAudioExtractor } from '@bryan-kuang/bilibili-audio-extractor';\n\nconst extractor = new BilibiliAudioExtractor();\nconst audio = await extractor.extract('https://www.bilibili.com/video/BV1xx411c7BF');\n\naudio.title;      // video title\naudio.duration;   // seconds (the played part, for multi-part videos)\naudio.audioUrl;   // direct CDN URL for the best audio stream\n```\n\nAccepts desktop URLs, mobile URLs, `b23.tv` short links (resolved automatically), and bare `BV...` / `av...` ids.\n\n## What it handles for you\n\n- **WBI request signing.** The `playurl` endpoint requires requests signed with rotating keys and Bilibili's mixin-key permutation. Keys are fetched (works logged-out) and cached for ~12 hours.\n- **Anonymous identity bootstrap.** Bilibili's risk control rejects requests with a made-up `buvid3` cookie (HTTP 412). The extractor obtains a server-issued one from the fingerprint SPI endpoint, once, automatically.\n- **Stream selection.** Prefers direct HTTP(S) URLs over HLS, `mp4a` codecs over others, then highest bandwidth, from the DASH manifest.\n- **Multi-part (分P) videos.** `duration` is the default part's length — the one the audio URL plays — not the sum of all parts that the raw API reports.\n\n## Streaming the audio\n\n`audioUrl` is a **signed, expiring CDN link**, and the CDN rejects requests without the right headers. Use the `streamHeaders` that come with the result:\n\n```ts\nconst res = await fetch(audio.audioUrl, {\n  headers: {\n    Referer: audio.streamHeaders.referer,\n    'User-Agent': audio.streamHeaders.userAgent,\n  },\n});\n```\n\nFor FFmpeg: `-headers \"Referer: https://www.bilibili.com/\"` and a matching `-user_agent`. Extract again when a URL expires (typically after ~2 hours) — extraction is two fast API calls (see `result.timing`).\n\n## Higher quality with a logged-in session\n\nAnonymous extraction tops out at standard-quality audio. Passing a logged-in session unlocks the higher-bandwidth streams your account can access:\n\n```ts\n// Netscape cookie file (e.g. exported from a browser)\nnew BilibiliAudioExtractor({ cookiesFile: '/path/to/bilibili_cookies.txt' });\n\n// or a raw Cookie header\nnew BilibiliAudioExtractor({ cookieHeader: 'SESSDATA=...; bili_jct=...' });\n```\n\n## URL utilities\n\n```ts\nimport { isValidBilibiliUrl, extractVideoId, normalizeUrl } from '@bryan-kuang/bilibili-audio-extractor';\n\nextractVideoId('https://m.bilibili.com/video/av170001'); // { type: 'AV', id: '170001' }\nnormalizeUrl('BV1xx411c7BF');                            // 'https://www.bilibili.com/video/BV1xx411c7BF'\n```\n\n## Options\n\n| Option | Default | |\n|---|---|---|\n| `userAgent` | desktop Chrome UA | Sent on API calls and echoed in `streamHeaders` |\n| `cookiesFile` | — | Netscape-format cookie file |\n| `cookieHeader` | — | Raw `Cookie` value; wins over `cookiesFile` |\n| `timeoutMs` | `15000` | Per-request timeout |\n| `baseURL` | `https://api.bilibili.com` | API origin override |\n| `fetchJson`, `resolveRedirect` | global `fetch` | Injectable HTTP, for testing |\n\n## Caveats\n\n- **Undocumented API.** Bilibili changes these endpoints without notice; pin a version and expect occasional maintenance releases. Issue reports with a failing BV id are welcome.\n- **Region matters.** Some content is mainland-only; the API answers but returns no streams (or region-locked errors) from some networks.\n- **Personal use.** This does what your browser does when you press play — fetch the same streams with the same API. Respect Bilibili's terms and uploaders' rights; don't use it to redistribute content.\n\n## Provenance\n\nExtracted from [FM-Hachimi](https://github.com/Bryan-Kuang/FM-Hachimi), a Discord music bot where this extraction path serves production traffic daily. MIT.\n","readmeFilename":"README.md","_rev":"1-f2934c20729dd9a84f8f802312aa0714"}