# Bilibili Scraper (`romajure/bilibili-scraper`) Actor

Scrape Bilibili (哔哩哔哩) videos by keyword, BV id, uploader or trending list: views, likes, coins, favorites, danmaku, tags, followers, comments and subtitle tracks. No login. Pay per video.

- **URL**: https://apify.com/romajure/bilibili-scraper.md
- **Developed by:** [Romas Jurevicius](https://apify.com/romajure) (community)
- **Categories:** Social media, Videos
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 video scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Bilibili Scraper

Bilibili Scraper turns Bilibili (哔哩哔哩, B站), China's largest video community, into clean JSON. Give it a keyword, a list of BV ids or URLs, an uploader (UP主) or a trending board, and it returns one record per video: BV id and av id, title and description in the original Chinese, uploader with **follower count**, publish time in ISO 8601, duration, category, tags, cover, and the full engagement set - **views, likes, coins, favorites, shares, danmaku and comments**. Turn on comments to attach the top-level comments (pinned one first) to each video, and subtitles to list the CC tracks. No account, cookie or API key is needed: everything comes from Bilibili's public web APIs, signed the same way the website signs them.

Typical uses: tracking what trends in China every day for brand, gaming or entertainment research, monitoring a list of Chinese creators (KOLs) and their latest uploads, measuring how a keyword such as `黑神话悟空` or a product name performs, collecting comments for sentiment analysis, and feeding AI agents with fresh Chinese video data.

Four modes:

- **`popular`** (default) - the trending feed 综合热门 (up to ~1,000 videos), the 3-day **ranking boards** 排行榜 for 20 categories, the weekly editor pick 每周必看, or the all-time must-watch list 入站必刷.
- **`search`** - keyword search with Bilibili's own sort orders (relevance, most played, newest, most danmaku, most favorited) and a duration filter; up to 1,000 results per keyword.
- **`video`** - full details for BV ids, av ids, video URLs and `b23.tv` short links.
- **`user`** - an uploader's videos, newest or most played first, by mid or space URL.

### How to scrape Bilibili videos

1. Open the Actor in Apify Console and click **Try for free**.
2. Pick a **Mode**. The default (`popular`, 20 videos) returns today's trending videos in under a minute.
3. Fill in the field for that mode: **Search keywords**, **Videos**, **Uploaders**, or the **Popular list** and **Ranking category**.
4. Set **Max videos per query / uploader / list**, and switch on **Include comments** (with **Max comments per video**) or **Include subtitle tracks** if you need them.
5. Click **Start**. Download the results as JSON, CSV or Excel, or read them through the API.

#### How it works

Lists come from `/x/web-interface/popular`, `/ranking/v2`, `/popular/series/one`, `/popular/precious`, `/wbi/search/type` and the uploader endpoints `/x/space/wbi/arc/search` and `/x/series/recArchivesByKeywords`. Each video is then completed from `/x/web-interface/wbi/view/detail` (stats, tags, parts, follower count) and, on request, comments from `/x/v2/reply/wbi/main`. Signed endpoints use **WBI signing** with keys read from `/x/web-interface/nav` and refreshed automatically. When Bilibili's risk control answers (HTTP 412 page, `-412`, `-352`), the Actor backs off, switches to a new proxy session with a fresh `buvid3` cookie and retries; uploader lists alternate between two endpoints, because the main one is blocked for most anonymous sessions.

### Bilibili Scraper pricing

Pay-per-event, no subscription:

- **Video scraped**: **$0.002 per video** ($2 per 1,000 videos), full details included.
- **Comment scraped**: **$0.0005 per comment** attached to a video (only with **Include comments** on).
- **Actor start**: Apify's standard small start fee per run.

Detail requests, subtitle track lists and free status records (deleted video, blocked uploader, empty search) cost nothing extra. Example: the default run of 20 trending videos costs $0.04; 100 videos with 20 comments each costs $0.20 + $1.00. Set **Maximum cost per run** to cap spending: the Actor checks the remaining budget before every video, trims the comment count to what is left, and stops cleanly with everything collected so far.

### Input example

```json
{
    "mode": "search",
    "searchQueries": ["黑神话悟空", "原神"],
    "searchOrder": "click",
    "maxVideos": 100,
    "fetchDetails": true,
    "includeComments": true,
    "maxComments": 20,
    "commentsSort": "hot",
    "proxyConfiguration": { "useApifyProxy": true }
}
```

Other modes: `{"mode": "video", "videos": ["BV1qt411j7fV", "av170001", "https://b23.tv/..."]}`, `{"mode": "user", "users": ["546195"], "userOrder": "pubdate"}`, `{"mode": "popular", "popularSource": "ranking", "rankingCategory": "4"}` (gaming board).

### Output example

One dataset item per video (trending video, captured 2026-10-12, comments shortened):

```json
{
    "type": "video",
    "bvid": "BV1uopn6NEMR",
    "aid": 117422443004890,
    "cid": 42656206326,
    "url": "https://www.bilibili.com/video/BV1uopn6NEMR",
    "title": "那个卖菱角的小贩想要弄伤我的鳞片",
    "description": "",
    "language": "zh",
    "author": { "mid": 1582757648, "name": "印度老吃家", "face": "https://i2.hdslb.com/bfs/face/d6208f529dff2c6cc91e1bdaf4bb8fa74dc2b898.jpg", "followers": 1051420 },
    "publishedAt": "2026-10-11T14:00:00.000Z",
    "durationSec": 169,
    "category": "美食侦探",
    "categoryId": 212,
    "tags": ["舌尖真探事务所", "印度美食", "街头美食", "美食侦探", "街头小吃"],
    "stats": { "views": 967617, "likes": 26583, "coins": 529, "favorites": 1149, "shares": 325, "danmaku": 277, "comments": 334 },
    "cover": "https://i2.hdslb.com/bfs/archive/ece16da3ebfd4ce11d7b9c9765a37279458077c3.jpg",
    "isReprint": false,
    "parts": [{ "cid": 42656206326, "page": 1, "title": "那个卖菱角的小贩想要弄伤我的鳞片", "durationSec": 169 }],
    "rank": 1,
    "source": { "mode": "popular", "list": "popular 综合热门" },
    "detailsFetched": true,
    "scrapedAt": "2026-10-12T08:36:34.840Z",
    "comments": [
        {
            "rpid": "316778356289",
            "author": { "mid": 3546712312384082, "name": "是小小付吖", "level": 4, "avatar": "https://i2.hdslb.com/bfs/face/352b22079fc46cfb0678599e4a40b2ab3d1a96ee.jpg" },
            "text": "为什么主播说哎呦喂会被骂，有没有了解的说一下谢谢[打call]",
            "likes": 1202,
            "replyCount": 17,
            "createdAt": "2026-10-11T14:02:36.000Z",
            "ipLocation": null,
            "isPinned": false
        }
    ],
    "commentsTotal": 334
}
```

Field notes:

- Text is **never translated**. `language` is a script-based guess on title + description (`zh`, `ja`, `ko`, `en`, `und`).
- `stats` fields Bilibili does not publish for a list are `null`, never invented. With **Fetch full details** on (default) every field is filled from the video's detail record; with it off, search rows lack coins and shares, and uploader rows carry only views, danmaku and comments.
- `author.followers` comes from the detail record (or the uploader card in `user` mode).
- `rank` is the position in the source list: trending rank, search result order or upload order.
- `subtitles` (with **Include subtitle tracks**) lists each CC track as `{ lang, langName, isAiGenerated, url, requiresLogin, text, cues }`. See the limitations below.
- `ipLocation` on comments is what Bilibili shows next to a comment; it is usually `null` for anonymous visitors.
- Videos and uploaders that cannot be read produce one free `{"type": "status"}` record with `not_found`, `blocked`, `empty` or `error` and the Bilibili response code, so a pipeline can tell "deleted" from "blocked".

### Integrations

- **API and clients**: start runs and read the dataset through the [Apify API](https://docs.apify.com/api/v2) or the JavaScript and Python clients; `run-sync-get-dataset-items` returns a trending snapshot in one call.
- **MCP / AI agents**: add the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) to Claude, Cursor or ChatGPT and enable this Actor as a tool; the input schema becomes the tool schema, for example `{"mode": "search", "searchQueries": ["小米 SU7"], "maxVideos": 50}`.
- **n8n, Make, Zapier**: use the Apify node or module and map dataset items into your workflow.
- **Schedules and webhooks**: run the trending board every hour and push results to Google Sheets, Slack, BigQuery or Postgres.

### Limitations

- **Proxy**: Apify datacenter proxy (the default) works for every mode; on 2026-10-12 trending, ranking, search, detail and comments all answered from US datacenter IPs, and a China residential IP gave no advantage. No China proxy is needed.
- **Uploader lists** are Bilibili's most risk-controlled endpoints. The Actor rotates sessions and alternates two endpoints; in testing about half of the attempts were blocked, and retries recovered every page. A page that stays blocked after 10 sessions yields a free `blocked` record.
- **Subtitle text needs login.** Since Bilibili's 2024 change, CC subtitle files are only served to logged-in users: the Actor lists the tracks (language, AI or human) with `requiresLogin: true` and `text: null`. If a track's file is public, its text and timed cues are filled in.
- **Comments** are top-level only (reply threads are counted in `replyCount`, not fetched). They are requested without cookies on purpose: with a fresh `buvid3` cookie Bilibili cuts anonymous comment lists to 3 items.
- Search stops at 1,000 results per keyword (50 pages of 20); the trending feed at about 1,000 videos; ranking boards at 100. Paid courses, bangumi episodes and live rooms are not covered.

### Bilibili Scraper FAQ

#### Do I need a Bilibili account or cookies?

No. Every mode uses public endpoints that Bilibili's own website calls for logged-out visitors. You never paste cookies, so there is no account to get banned.

#### Is the Chinese text translated?

No. Titles, descriptions, tags and comments stay exactly as published. Each video carries a `language` field so you can route records to your own translation step.

#### How do I get an uploader's newest videos?

Use `"mode": "user"` with the mid (`546195`) or the space URL, and keep `userOrder` at `pubdate` (newest first) or set `click` for most played. Newest-first sorting works, unlike tools that ignore the order parameter.

#### Why is a video missing from my results?

Deleted, private or under-review videos return a free `status` record with `not_found` and Bilibili's code (`-404`, `62002`, `62012`). The same video appearing in two lists is pushed and charged only once per run.

#### How much does a daily trending snapshot cost?

The top 100 trending videos with full details cost $0.20 per run. Adding 20 comments per video adds $1.00. Detail lookups are not charged separately.

### Related actors

Same author, same pay-per-event model, all without login:

- [Telegram Channel Scraper](https://apify.com/romajure/telegram-channel-scraper) - posts, views, media and links from public Telegram channels.
- [Substack Scraper](https://apify.com/romajure/substack-scraper) - posts, authors, likes, restacks and comments from Substack publications.
- [Product Hunt Scraper](https://apify.com/romajure/product-hunt-scraper) - leaderboards, topics, search and launches with votes and makers.
- [Economic Calendar Scraper](https://apify.com/romajure/economic-calendar) - Forex Factory and Investing.com macro events with actual, forecast and previous values.
- [Prediction Market Odds Scraper](https://apify.com/romajure/prediction-market-odds) - Polymarket and Kalshi odds as 0-1 probabilities.

### Legal and compliance

This Actor reads only publicly visible data through the same unauthenticated endpoints Bilibili's website uses, and it never logs in or touches account features. Bilibili's [robots.txt](https://www.bilibili.com/robots.txt) disallows only `/medialist/detail/` and `/index.html`, which the Actor does not request. Videos, comments and profile data can still contain personal data and copyrighted content: you are responsible for using the output lawfully, including GDPR, China's Personal Information Protection Law (PIPL) and Bilibili's [terms of service](https://www.bilibili.com/protocal/licence.html). Keep request rates modest (the Actor spaces requests and limits concurrency by default), and read Apify's article on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) if in doubt.

### Support

Found a field that normalizes wrongly, a list that stopped working, or need danmaku or reply threads? Open an issue on the Actor's **Issues** tab with the input JSON and the BV id or mid; fixes usually ship within days.

# Actor input Schema

## `mode` (type: `string`):

`popular`: trending / ranking lists (default). `search`: keyword search. `video`: specific BV ids, av ids or URLs. `user`: an uploader's (UP主) videos by mid or space URL.

## `popularSource` (type: `string`):

Popular mode only. `popular`: 综合热门, the live trending feed (paginated, up to ~1,000). `ranking`: 排行榜, top 100 of the last 3 days for one category. `weekly`: 每周必看, the weekly editor pick. `precious`: 入站必刷, the all-time must-watch list.

## `rankingCategory` (type: `string`):

Popular list `ranking` only: which category board to read.

## `weeklyIssue` (type: `integer`):

Popular list `weekly` only: issue number (e.g. 394). Empty = latest issue.

## `searchQueries` (type: `array`):

Search mode: one or more keywords, in Chinese or any language (`原神`, `黑神话悟空`, `AI 教程`). Each keyword is searched separately.

## `searchOrder` (type: `string`):

Search mode: `totalrank` relevance, `click` most played, `pubdate` newest, `dm` most danmaku, `stow` most favorited.

## `searchDuration` (type: `integer`):

Search mode: 0 any length, 1 under 10 min, 2 10-30 min, 3 30-60 min, 4 over 60 min.

## `videos` (type: `array`):

Video mode: BV ids (`BV1qt411j7fV`), av ids (`av170001` or `170001`), video URLs (`https://www.bilibili.com/video/BV...`, `m.bilibili.com/video/...`) or `b23.tv` short links.

## `users` (type: `array`):

User mode: uploader ids (mid, e.g. `546195`) or space URLs (`https://space.bilibili.com/546195`).

## `userOrder` (type: `string`):

User mode: `pubdate` newest first (default) or `click` most played first.

## `maxVideos` (type: `integer`):

Stop each search keyword, uploader or popular list after this many videos. Bilibili search stops at 1,000 results (50 pages). Not used in video mode.

## `fetchDetails` (type: `boolean`):

Read each video's detail record: complete stats (coins, shares, likes), tags, multi-part info and uploader follower count. One extra request per video, no extra charge. Turn off for faster list-only data (some stats then stay null).

## `includeComments` (type: `boolean`):

Attach top-level comments (with the pinned one first) to every video. Charged per comment as `comment-scraped`.

## `maxComments` (type: `integer`):

Upper limit of top-level comments per video when comments are on.

## `commentsSort` (type: `string`):

`hot` most liked first (Bilibili default) or `time` newest first.

## `includeSubtitles` (type: `boolean`):

List each video's CC subtitle tracks (language, AI or human). Bilibili currently serves subtitle text only to logged-in users, so `text` is usually null; tracks whose file is public are downloaded with timed cues.

## `maxConcurrency` (type: `integer`):

Parallel requests. Bilibili's risk control reacts to bursts; 3 is a safe default.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy works for every mode (verified from US IPs). Sessions are rotated automatically when Bilibili answers with risk-control codes (412, -352).

## Actor input object example

```json
{
  "mode": "popular",
  "popularSource": "popular",
  "rankingCategory": "0",
  "searchQueries": [
    "原神"
  ],
  "searchOrder": "totalrank",
  "searchDuration": 0,
  "videos": [],
  "users": [],
  "userOrder": "pubdate",
  "maxVideos": 20,
  "fetchDetails": true,
  "includeComments": false,
  "maxComments": 20,
  "commentsSort": "hot",
  "includeSubtitles": false,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `videos` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "popular",
    "searchQueries": [
        "原神"
    ],
    "videos": [],
    "users": [],
    "maxVideos": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("romajure/bilibili-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "popular",
    "searchQueries": ["原神"],
    "videos": [],
    "users": [],
    "maxVideos": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("romajure/bilibili-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "popular",
  "searchQueries": [
    "原神"
  ],
  "videos": [],
  "users": [],
  "maxVideos": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call romajure/bilibili-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,romajure/bilibili-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/SXtHyZgkdCQvXjokg/builds/3g4phLVW5tyb7UMJT/openapi.json
