# Bilibili Scraper: Videos, Comments, Creators & Rankings (`crawleast/bilibili-video-scraper`) Actor

Bilibili API alternative: scrape B站 (哔哩哔哩) videos, comments with replies, UP主 creator profiles and the official top-100 rankings by keyword, URL, creator or feed. Engagement rates included. $5 per 1,000 videos, $2 per 1,000 comments. No login or cookies needed.

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

## Pricing

from $5.00 / 1,000 video rows

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: Videos, Comments, Creators & Rankings

Get Bilibili (B站 / 哔哩哔哩) data as clean JSON without a login or an API key: **video metadata with engagement metrics, comments with replies (楼中楼), creator (UP主) profiles with a stats rollup, and the official top-100 rankings**. Feed it keywords, video URLs, creator URLs or a ranking feed — or all four in one run. A practical Bilibili API alternative for market research, KOL vetting and comment analysis.

**$5 per 1,000 videos · $2 per 1,000 comments (replies included) · $10 per 1,000 creator profiles.** One price on every Apify plan, China residential proxy included, and runs that deliver nothing cost $0.

- **One run, four inputs** — keywords, video URLs/BV ids, creator space URLs and ranking/popular feeds can be mixed; duplicates are delivered once.
- **Numbers you can sort by straight away** — every video row carries engagement rate, like/coin/favorite/share rates, age and views per day; every creator row carries average and median views, average engagement and posting cadence for the videos fetched in the run.
- **Ready-made discovery** — one input gives you Bilibili's official top-100 board for the whole site or any region.
- **Checked against Bilibili itself** — in our October 2026 acceptance tests, 17 videos × 29 fields were compared with the videos' own pages (the only difference was a live counter that grew between the two reads), and the ranking's top 10 matched the official board in order.
- **Transparent delivery** — fixed per-row prices, caps you control, and a run report (`RUN_SUMMARY`) that accounts for every source, every video's comments and anything skipped, with the reason.
- **No setup** — no login, no cookies or API key needed.

Scrapes publicly available data without login. Users are responsible for complying with Bilibili's terms of service in their use case.

### Pricing

Pay per row delivered. Rows that fail or are skipped are never charged.

| Event | Price | When |
| --- | --- | --- |
| Video row | $0.005 | per video row delivered (engagement metrics included) |
| Comment row | $0.002 | per comment or reply delivered |
| Creator row | $0.01 | per creator row whose rollup includes at least one video (other creator rows, e.g. when the video list could not be fetched, are delivered free) |
| Run fee | $0.00005 | once per run, only if the run delivers at least one row |

What common configurations cost at most (you pay only for rows delivered; videos with fewer comments than requested return fewer rows and cost less):

| Configuration | Delivers up to | Cost up to |
| --- | --- | --- |
| Try example (the form's prefilled keyword, 10 videos, 20 comments each) | 10 videos + 200 comments | $0.45 |
| Defaults (20 videos, no comments) | 20 videos | $0.10 |
| Defaults + comments (`commentsPerVideo: 20`) | 20 videos + 400 comments | $0.90 |
| One ranking board (`feeds: ["ranking"]`, `maxVideos: 100`) | 100 videos | $0.50 |
| All default caps reached | 300 videos + 1,000 comments + 20 creators | ≈ $3.70 |
| Beyond the default caps (raise `maxCommentsTotal` and `maxTotalChargeUsd`) | 300 videos + 6,000 comments | ≈ $13.50 |

Measured examples: the defaults + comments run delivered 20 videos + 242 comments for $0.58 (many keyword results are new videos with few comments); 20 creators with 15 videos each and 1,000 comments delivered 295 videos + 1,000 comments + 20 creators for $3.68 in 18 minutes.

`maxTotalChargeUsd` (default $10) is a hard stop: the Actor stops delivering before the next row would exceed it, and the lower of this value and your platform max-charge setting applies.

### Three recipes

**KOL vetting** — profile and benchmark creators before you contact them.

```json
{
  "creatorUrls": ["https://space.bilibili.com/946974", "https://space.bilibili.com/163637592"],
  "maxVideosPerCreator": 30,
  "maxVideos": 60
}
```

You get each creator's 30 newest videos (with engagement metrics) and one creator row per creator: followers, total likes, video count, verification, plus `rollup` with `avgViews`, `medianViews`, `maxViews`, `avgEngagementRate`, `postingSpanDays` and `videosPerWeek`. Set `maxVideos` to at least creators × `maxVideosPerCreator`; with a smaller `maxVideos` it is split evenly across the creators, so each rollup covers fewer videos.

**Trend scan** — what is hot right now, in one region or the whole site.

```json
{
  "feeds": ["ranking"],
  "rankRegionIds": [0, 188],
  "maxVideos": 200
}
```

Up to 100 ranked videos per region (`0` = whole site, `188` = Tech), each with `source.rank` (its position on the board), zone, tags, stats and derived metrics. Add `"keywords": ["露营装备"]` to scan a product category in the same run.

**Comment mining** — reactions and threads for specific videos.

```json
{
  "videoUrls": ["https://www.bilibili.com/video/BV1GJ411x7h7", "BV1KiJk67EQ9"],
  "commentsPerVideo": 50,
  "includeReplies": true,
  "commentSort": "hot"
}
```

Up to 50 comment rows per video: the pinned comment and Bilibili's hot list first. Many videos have a hot list shorter than that (few comments with likes), so the rest is filled newest-first; each row's `sort` field says which list it came from (`hot` or `new`). With `includeReplies`, each comment is followed by up to `maxRepliesPerComment` of its replies (default 10) before the next comment starts, so one very long thread cannot use up the whole allowance; the comment's `replyCount` still shows the full thread size. Replies carry `rootRpid` and `parentRpid`, so threads can be rebuilt.

### Input

| Field | Default | Notes |
| --- | --- | --- |
| `keywords` | — | Up to 20 keywords, Chinese or English. Bilibili returns at most 1,000 results per keyword. |
| `videoUrls` | — | Up to 300 video URLs, BV ids or av ids. b23.tv short links are not resolved. |
| `creatorUrls` | — | Up to 20 space.bilibili.com URLs or numeric mids. |
| `feeds` | — | `ranking` (top 100 per region) and/or `popular` (trending). |
| `rankRegionIds` | `[0]` | Up to 5 regions for the ranking feed: 0 whole site, 1 Animation, 3 Music, 4 Gaming, 5 Entertainment, 36 Knowledge, 119 Remix, 129 Dance, 155 Fashion, 160 Life, 181 Film & TV, 188 Tech, 211 Food, 217 Animals, 223 Cars, 234 Sports. |
| `maxVideos` | 20 | Hard cap for the whole run, across all inputs (max 300). |
| `maxVideosPerKeyword` | 20 | Per-keyword cap. |
| `maxVideosPerCreator` | 40 | Newest videos per creator. |
| `commentsPerVideo` | 0 | 0–100 comment rows per video. |
| `includeReplies` | false | Also fetch replies (same price, counted toward both comment caps). |
| `maxRepliesPerComment` | 10 | With `includeReplies`: at most this many replies per comment (1–100). |
| `commentSort` | `hot` | `hot` (pinned comment and hot list first, topped up newest-first when the hot list is shorter than `commentsPerVideo`) or `new` (newest first). |
| `maxCommentsTotal` | 1000 | Hard cap on comment rows for the run. |
| `maxTotalChargeUsd` | 10 | Spending cap in USD. |
| `proxyConfiguration` | Apify RESIDENTIAL, China | Keep the default — see below. |

**Order and caps.** Inputs are processed in this order: video URLs → creators → feeds → keywords, and `maxVideos` is shared by all of them. Creators split what is left evenly, so every creator gets a rollup (with 5 creators and `maxVideos: 10`, each gets 2 videos); feeds and keywords are then served first come, first served. The report shows what each source received and why it stopped. All videos are collected first; comments are then collected per video in that same order, first come, first served against `maxCommentsTotal`, so later videos may get fewer comments or none. `RUN_SUMMARY.perVideoComments` shows exactly what each video got.

### Output

One dataset with three row types, told apart by `type`. The dataset has *Overview*, *Videos*, *Comments* and *Creators* views; CSV and Excel exports flatten nested fields.

```json
{"type":"video","bvid":"BV1KiJk67EQ9","aid":117443632567747,"cid":42756868744,"url":"https://www.bilibili.com/video/BV1KiJk67EQ9",
 "title":"我造了一块会飞的滑板...","description":"…","duration":598,"parts":1,"pubdate":"2026-10-15T17:30:00+08:00","isRepost":false,"copyrightCode":1,
 "category":{"tid":233,"tname":"极客DIY","tidV2":2104,"tnameV2":"自制发明/设备"},"tags":["滑板","DIY"],
 "owner":{"mid":431956189,"name":"神奇阿宇Ayu"},
 "stats":{"view":5363695,"danmaku":7144,"reply":10592,"favorite":89000,"coin":112376,"share":34722,"like":254161},
 "derived":{"engagementRate":0.0914,"likeRate":0.0474,"coinRatio":0.021,"favoriteRate":0.0166,"shareRate":0.0065,"ageDays":2,"viewsPerDay":2681847.5},
 "coverUrl":"https://i1.hdslb.com/bfs/archive/….jpg","source":{"mode":"ranking","keyword":null,"creatorMid":null,"rankRegionId":0,"rank":1}}
{"type":"comment","bvid":"BV1GJ411x7h7","aid":80433022,"rpid":3760801399,"parentRpid":null,"rootRpid":null,
 "author":{"mid":320773657,"name":"老咸鱼A"},"content":"坏消息：被骗了\n好消息：真好听","like":767623,"replyCount":2206,
 "publishedAt":"2020-11-29T20:26:45+08:00","sort":"hot","isPinned":false}
{"type":"creator","mid":946974,"name":"影视飓风","sign":"…","followers":18600000,"videoCount":937,"totalLikes":300000000,"level":6,
 "officialTitle":"…","profileStatus":"ok","spaceUrl":"https://space.bilibili.com/946974",
 "rollup":{"videosFetched":30,"sumViews":61000000,"avgViews":2033333,"medianViews":1650000,"maxViews":7900000,"maxVideoBvid":"BV1…",
           "avgEngagementRate":0.0712,"postingSpanDays":96,"videosPerWeek":2.19}}
```

(Values are illustrative.)

**How the metrics are computed**

- `engagementRate` = (like + coin + favorite + share) / view; `likeRate`, `coinRatio`, `favoriteRate`, `shareRate` = that count / view. Four decimals; `null` when the video has no views yet.
- `ageDays` = whole days since publishing, at least 1; `viewsPerDay` = view / ageDays, one decimal.
- Creator `rollup` uses only that creator's videos fetched in this run: `medianViews` averages the two middle values for an even count; `postingSpanDays` = days between the oldest and newest fetched video; `videosPerWeek` = videosFetched / max(1, postingSpanDays / 7). Span fields are `null` with fewer than two videos. Very large accounts (hundreds of thousands of uploads) may not list their videos; their creator row then has an empty rollup and the report says why.
- Zone names: `tname` is Bilibili's classic zone name; `tnameV2` (the newer zone name) is filled when the video came from a ranking or popular list.
- Phone numbers and email addresses in titles, descriptions, bios and comments are replaced with `[removed]`. Authors appear only as public mid and nickname.

**Run report.** `RUN_SUMMARY` in the key-value store lists requested vs delivered counts, per-source results (`perCreator`, `perRegion`, `perKeyword`), `perVideoComments`, what was skipped and why (`skippedBy`: budget, request quota, deadline, risk-control stop, rejected items), billed events, request statistics and a plain-English `humanReadableReason` whenever something was cut short.

### Reliability and limits

- **Proxy.** Bilibili rejects most requests that come from outside mainland China — including Apify's own servers — so the default is the Apify RESIDENTIAL proxy in China. Its cost is on us, not you. With another proxy or a direct connection most requests are rejected, and the run usually stops within seconds with nothing delivered and nothing charged — keep the default.
- **Pacing.** Requests are sent one at a time with a short random pause (about 2 seconds per request in tests), so a default run takes about a minute, a full ranking board about 3–4 minutes and the largest default job about 18 minutes.
- **Stops.** A run stops early, keeps everything already delivered and explains why when (1) the spending cap is reached, (2) 1,500 requests have been made, (3) the run is close to its timeout, or (4) Bilibili rejects three requests in a row. Any run that delivers nothing costs $0; if Bilibili's rejections were the reason, the run is marked failed.
- **Platform limits.** Search returns at most 1,000 results per keyword; the ranking board has 100 videos per region.
- **Creator video lists.** Bilibili rejects many creator video-list requests at random, so each page is retried up to 8 times with pauses on fresh connections. If a creator's list still cannot be fetched, you get the profile row free, with an empty rollup, and the report says so.

### What this Actor does not do

No login or account features, no danmaku, no subtitles or transcripts, no video or audio files, no live streams, no anime/film (OGV) catalogues, and no private or personal data beyond public nicknames and ids.

| | This Actor | Typical alternatives |
| --- | --- | --- |
| Keyword, URL, creator and ranking input in one run | ✅ | Usually one mode per run |
| Engagement rates and creator rollups in the rows | ✅ | Usually raw counts only |
| Comment replies with thread ids | ✅ | Varies |
| Danmaku, subtitles | ❌ | Some offer them |
| Pricing | Fixed per row, zero-delivery runs free | Varies |

### FAQ

**Do I need a Bilibili account, cookies or an API key?** No.

**Can I search in English?** Yes, but most Bilibili content is in Chinese; Chinese keywords return more relevant results.

**Why do some search results look unrelated?** Bilibili's search is fuzzy, like the website: for rare, misspelled or very long keywords it matches parts of the keyword. Use specific keywords and check `title` and `tags` before relying on a result.

**Why did some videos not come back?** Deleted, private or region-locked videos are listed in `RUN_SUMMARY.perVideoUrl.unavailable`; items Bilibili rejected are counted in `skippedBy.blocked`. Neither is charged.

**Why do later videos have fewer comments?** `maxCommentsTotal` is shared first come, first served in video order. Raise it, or lower `commentsPerVideo`, to spread comments further. A video can also simply have fewer comments than you asked for: its `stats.reply` count includes replies and comments Bilibili has folded or removed, so it is often higher than what can be listed. `RUN_SUMMARY.perVideoComments` shows each video's result and stop reason.

**Can I schedule it or call it from n8n, Make or my own code?** Yes. Input and output are plain JSON; use the Apify API, an Apify schedule or any integration that can start an Actor run.

# Changelog

This Actor's version history is a separate document: https://apify.com/crawleast/bilibili-video-scraper/changelog.md

# Actor input Schema

## `keywords` (type: `array`):

Bilibili video search, one keyword per line (Chinese or English, e.g. 机械键盘 = mechanical keyboard). Up to 20 keywords. Bilibili itself returns at most 1,000 results per keyword.

## `videoUrls` (type: `array`):

Up to 300 videos: https://www.bilibili.com/video/BV…, m.bilibili.com links, BV ids or av ids (av170001 or 170001). b23.tv short links are not resolved — paste the full URL.

## `creatorUrls` (type: `array`):

Up to 20 creators: https://space.bilibili.com/946974 or the numeric mid. Each creator gives one profile row (followers, total likes, video count, verification) plus a rollup computed from the videos fetched in this run, and up to maxVideosPerCreator of their newest videos.

## `feeds` (type: `array`):

ranking = Bilibili's official top-100 board per region (see rankRegionIds); popular = the site-wide trending feed. Both are capped by maxVideos — set maxVideos to 100 to get a full board.

## `rankRegionIds` (type: `array`):

Up to 5 region ids for the ranking feed. 0 = whole site, 1 Animation, 3 Music, 4 Gaming, 5 Entertainment, 36 Knowledge, 119 Remix, 129 Dance, 155 Fashion, 160 Life, 181 Film & TV, 188 Tech, 211 Food, 217 Animals, 223 Cars, 234 Sports.

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

Hard cap on video rows for the whole run, across all inputs (1–300). Creators split what is left evenly; feeds and keywords are then served in order until the cap is reached.

## `maxVideosPerKeyword` (type: `integer`):

Per-keyword cap, applied together with maxVideos.

## `maxVideosPerCreator` (type: `integer`):

Newest videos fetched per creator, applied together with maxVideos. For full rollups on N creators set maxVideos ≥ N × this value.

## `commentsPerVideo` (type: `integer`):

Comment rows per delivered video (0–100). 0 = no comments. Videos are processed first; comments are then collected in video order.

## `includeReplies` (type: `boolean`):

Also fetch the replies under each comment, up to Max replies per comment. Replies are comment rows at the same price and count toward both comment caps; they follow their comment directly, before the next comment starts.

## `maxRepliesPerComment` (type: `integer`):

With Include replies: at most this many replies under each comment (1–100), so one very long thread cannot use up a video's whole comment allowance. The comment's replyCount still shows the full thread size.

## `commentSort` (type: `string`):

Hot = the pinned comment and Bilibili's hot list first; when a video's hot list is shorter than commentsPerVideo (common for videos with few liked comments) the rest is filled newest-first. Newest = most recent first. Each comment row's sort field says which list it came from; replies keep Bilibili's own order.

## `maxCommentsTotal` (type: `integer`):

Hard cap on comment rows for the run (0–30,000). Comments are assigned first come, first served in video order, so later videos may get fewer or none; RUN_SUMMARY.perVideoComments shows what each video got.

## `maxTotalChargeUsd` (type: `number`):

The run stops delivering before this amount would be exceeded. The lower of this value and the platform's max-charge setting applies.

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

Keep the default (Apify RESIDENTIAL, China). Bilibili rejects most requests from non-China IPs, including Apify's own servers; with other settings the run usually stops early with nothing delivered.

## Actor input object example

```json
{
  "keywords": [
    "机械键盘"
  ],
  "rankRegionIds": [
    0
  ],
  "maxVideos": 10,
  "maxVideosPerKeyword": 20,
  "maxVideosPerCreator": 40,
  "commentsPerVideo": 20,
  "includeReplies": false,
  "maxRepliesPerComment": 10,
  "commentSort": "hot",
  "maxCommentsTotal": 1000,
  "maxTotalChargeUsd": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Video rows with derived engagement metrics, comment rows (including replies) and creator rows with a stats rollup, in delivery order.

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

The dataset shown with video columns (stats, engagement rate, views per day, tags, source).

## `comments` (type: `string`):

The dataset shown with comment columns (thread ids, author, text, likes, time).

## `creators` (type: `string`):

The dataset shown with creator columns and the stats rollup.

## `runSummary` (type: `string`):

Machine-readable report: delivered counts, per-source and per-video comment counts, what was skipped and why (budget, request quota, deadline, risk control), billed events and request statistics.

# 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 = {
    "keywords": [
        "机械键盘"
    ],
    "maxVideos": 10,
    "commentsPerVideo": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "CN"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawleast/bilibili-video-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 = {
    "keywords": ["机械键盘"],
    "maxVideos": 10,
    "commentsPerVideo": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "CN",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("crawleast/bilibili-video-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 '{
  "keywords": [
    "机械键盘"
  ],
  "maxVideos": 10,
  "commentsPerVideo": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}' |
apify call crawleast/bilibili-video-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawleast/bilibili-video-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/8nJxOU1ybTBujOYPz/builds/9a7wbMnzKDbTJSlUS/openapi.json
