# Bilibili 哔哩哔哩 Video Scraper (`herus13/bilibili-scraper`) Actor

Scrape Bilibili videos, creators, comments and danmaku by keyword, video ID or creator ID. Every row carries kind, bvid, title, owner\_name, view, like and reply, plus comment message and danmaku progress\_ms. Export JSON, CSV or Excel.

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

## Pricing

from $4.00 / 1,000 videos

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

The Bilibili 哔哩哔哩 Video Scraper extracts public data from [Bilibili](https://www.bilibili.com), China's largest video community. One actor, nine modes: search videos, read a video's full stats, a creator's profile, uploads, followers and feed, comments with replies, on-screen danmaku, and the video or audio file itself.

### 中文说明

哔哩哔哩（Bilibili）公开数据抓取工具。按关键词搜索视频，或用 BV 号、UP 主 mid 获取视频详情、UP 主资料与投稿、评论与回复、粉丝、动态、弹幕，也可下载视频或音频文件。

每行数据都带 `kind` 标明类型：视频含标题 `title`、UP 主 `owner_name`、播放 `view`、点赞 `like`、评论数 `reply`；评论含正文 `message` 与作者 `member_name`；弹幕含正文 `message` 与出现时间 `progress_ms`；下载文件给出 `download_url`。

运行自带住宅代理，无需自行配置，多数模式也无需登录。在 Apify Console 选好模式、填入关键词或 ID 后点击 Start 即可，也可以通过 Apify API 提交同样的 JSON。结果支持导出 JSON、CSV 或 Excel。

### What you get

One dataset, one row per record, with `kind` saying what each row is. Export as JSON, CSV or Excel.

```json
{
  "kind": "video",
  "bvid": "BV1wD4y1o7AS",
  "title": "花了2万多买的Python教程全套，现在分享给大家，入门到精通(Python全栈开发教程)",
  "owner_name": "Python_子木",
  "view": 35494331,
  "like": 1094798,
  "reply": 23760,
  "scraped_at": "2026-09-04T11:20:31.004112+00:00"
}
```

Every mode writes into the same dataset, so a mixed run filters cleanly on `kind`:

- `video` — `bvid`, `title`, `owner_name`, `view`, `like`, `coin`, `favorite`, `reply`, `danmaku`, `duration_sec`, `published_at`, `tags`, `cover_url`
- `creator` — `mid`, `name`, `sign`, `follower`, `following`
- `comment` — `rpid`, `parent_rpid`, `member_name`, `message`, `like`, `reply_count`, `ctime`
- `fan` — `creator_mid`, `mid`, `name`, `followed_at`
- `dynamic` — `dynamic_id`, `dynamic_type`, `text`, `bvid`, `like`, `comment`, `forward`
- `danmaku` — `cid`, `part`, `parts_total`, `bvid`, `progress_ms`, `message`, `mode`, `color`, `sender_hash`
- `media` — `bvid`, `media`, `quality_id`, `codec`, `size_bytes`, `download_url`

A `video` row also says which target found it: `source_keyword` for a search, `source_creator_mid` for a creator's uploads. Pass several keywords or creators in one run and split the rows on those columns.

`download_url` points at the file in this run's storage, so download anything you mean to keep before the run's data retention expires.

### What it costs

| Event | Price |
|---|---|
| Actor Start (`apify-actor-start`) | $0.00005 |
| video (`video`) | $0.004 |
| creator (`creator`) | $0.004 |
| comment (`comment`) | $0.001 |
| fan (`fan`) | $0.001 |
| dynamic (`dynamic`) | $0.0015 |
| danmaku (`danmaku`) | $0.00002 |
| danmaku, per 1,000 (`danmaku-1k`) | $0.01 |
| media (`media`) | $0.002 |
| media, per 10 MB (`media-file-10mb`) | $0.002 |

### Input

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `mode` | string | no | `"search"` | Which kind of record to collect: `search` finds videos by keyword; `video` returns full stats for specific videos; `creator` returns a creator's profile and follower count; `creator_videos` lists a creator's uploads; `comments` returns a video's comments; `fans` lists a creator's followers; `dynamics` reads a creator's feed; `danmaku` returns a video's on-screen bullet comments; `media` returns a download link for the video or its audio. Default search. |
| `keywords` | array | no | — | Search terms, one per entry — for example `python`. Each term returns up to `max_items` videos, ranked the way `order` says. Bilibili search ignores capitals, so terms that differ only in capitals or surrounding spaces are searched, and billed, once. Used when `mode` is search; leave empty for every other mode. |
| `video_ids` | array | no | — | Videos to work on, one per entry, as a BV id (`BV1wD4y1o7AS`), an av id (`av712020469`) or the video part of a bilibili.com URL — the two id styles name the same video and both work. Used when `mode` is video, comments, danmaku or media; leave empty for every other mode. |
| `creator_ids` | array | no | — | Creators to work on, one numeric mid per entry — the number in a `space.bilibili.com/12345` URL. Used when `mode` is creator, creator\_videos, fans or dynamics; leave empty for every other mode. |
| `max_items` | integer | no | `100` | How many records to return per keyword, video or creator, at least 1. Default 100. Comments: counts top-level comments only; with `include_replies` their replies (up to `max_replies_per_comment` each) come on top, so a run can return and bill more rows than this. Danmaku: applies to each six-minute stretch of a video, not the whole video, and with `danmaku_all_parts` to each stretch of every part read, so a long video returns more rows than this. |
| `order` | string | no | `"totalrank"` | How search results are ranked: totalrank for best match, click for most viewed, pubdate for newest, dm for most bullet comments, stow for most favourited. Default totalrank. Used when `mode` is search. |
| `duration` | string | no | `"any"` | Keep only search results of this length: any for no filter, under\_10m for under ten minutes, 10\_30m, 30\_60m, over\_60m for over an hour. Default any. Used when `mode` is search. |
| `tid` | integer | no | — | Bilibili category to restrict a search to, given as the numeric tid that appears in a category page's URL. Leave empty to search every category. Used when `mode` is search. |
| `include_replies` | boolean | no | `false` | Also collect the replies under each comment, as extra rows whose `parent_rpid` names the comment they belong to. Default false, which returns top-level comments only. Used when `mode` is comments. |
| `max_replies_per_comment` | integer | no | `20` | Most replies to collect under one comment, at least 1. Default 20. It does nothing unless `include_replies` is true. |
| `danmaku_all_parts` | boolean | no | `false` | Read danmaku from every part of a multi-part video (a course or series uploaded as one video), up to `max_parts` parts, instead of part 1 only. Each row's `part` and `parts_total` say which part it came from out of how many (part 3 of 200). Default false. Used when `mode` is danmaku. |
| `max_parts` | integer | no | `10` | Most parts of one multi-part video to read danmaku from, counting from part 1, at least 1. Default 10. Every part adds its own requests and rows, so raise it with care on long courses. It does nothing unless `danmaku_all_parts` is true. |
| `quality` | string | no | `"best"` | Which stream to download: best for the highest the video offers, 720p or 480p to cap it at that resolution. Default best. A video that offers nothing at the resolution you ask for returns the best one below it, never a larger file than you asked for. Used when `mode` is media. |
| `audio_only` | boolean | no | `false` | Download the audio track on its own instead of the video file — far smaller, and enough for transcription or music. Default false. Used when `mode` is media. |
| `auth` | object | no | — | Your own Bilibili cookies, as {"cookies": "SESSDATA=..."}, if you want the run to act as your own account — for instance to reach media resolutions Bilibili reserves for members. Leave empty and you need no account at all. |
| `proxyUrls` | array | no | — | Leave empty and the run uses the residential proxy this actor ships with, included in the price of the run. To route the run through your own account instead, add one gateway URL per entry, for example http://user:pass@host:port — works with DataImpulse, Bright Data, Oxylabs, Smartproxy or any provider that issues URLs. When set, only these URLs are used. |

### How to run it

1. Open the actor on Apify Console and pick a **What to scrape** mode — it decides which other fields matter.
2. Fill that mode's target: keywords for search, video IDs for video, comments, danmaku and media, creator IDs for creator, creator videos, fans and dynamics.
3. Run. Export JSON, CSV or Excel from the dataset.

```json
{
  "mode": "search",
  "keywords": ["python", "机器学习"],
  "order": "click",
  "duration": "10_30m",
  "max_items": 200
}
```

Minimal input:

```json
{
  "keywords": ["python"]
}
```

Available as the MCP tool `herus13--bilibili-scraper` on mcp.apify.com and through the Apify API; send the same JSON.

### Why this scraper

- **Nine modes, one actor and one dataset.** Search, video stats, creator profile, uploads, comments, followers, feed, danmaku and media downloads all write rows tagged with `kind`, so a whole research pass is one run rather than five actors and a join.
- **Danmaku, which is the Bilibili-specific signal.** The on-screen comment track comes with `progress_ms`, pinning each remark to the second of the video it reacts to — audience reaction with timing attached, which no comment feed gives you.
- **No account needed.** Seven of the nine modes run anonymously, and you can still paste your own cookies if you want a run to act as you.
- **BV or av, either works.** Paste whichever id a page gave you; `av712020469` and `BV1wD4y1o7AS` are the same video.
- **Media as a playable link.** The video or the audio track alone, hosted as a link that works outside Bilibili.
- **Nothing to set up.** A residential proxy is included in the price of the run.

### Use cases

- **Content and trend research** — What ranks for a keyword today, ordered by views or recency, and how a video's stats move when you re-run the search on a schedule.
- **Creator benchmarking** — A creator's whole upload history with per-video engagement, next to their follower count, for outreach shortlists or competitor tracking.
- **Audience sentiment** — Comments and their replies for considered opinion, danmaku for the unfiltered live reaction, both as plain text ready for a classifier.
- **Reaction timing analysis** — Group danmaku by `progress_ms` to find the exact moments of a video that made an audience respond.
- **Media archiving and transcription** — Pull the audio track alone and feed it to a transcription step, or keep the video file for an archive.

### FAQ

**Do I need a Bilibili account?** No. Seven of the nine modes run anonymously. If you would rather run as yourself — for the media resolutions Bilibili reserves for members, for instance — paste your own cookies into **Your own login cookies**.

**Can I pass a video URL instead of an id?** Use the BV id from the URL: `https://www.bilibili.com/video/BV1wD4y1o7AS` means `BV1wD4y1o7AS`. Old-style av ids such as `av712020469` work too.

**Why did I get fewer comments than the video reports?** Bilibili publishes a sample of a popular video's comments to any single visitor, not the whole archive. A video showing tens of thousands of comments will not return tens of thousands of rows.

**Why did a long video return more danmaku than Max items?** Bilibili serves danmaku in six-minute stretches, and the cap applies to each stretch rather than to the whole video. With **Danmaku from every part** on, it applies to each stretch of every part read.

**Why did a comments run return more rows than Max items?** Max items counts top-level comments. With **Include replies** on, each comment's replies (up to **Max replies per comment**) come on top as their own rows, and every row is billed as a comment.

**Why did a multi-part video return danmaku from part 1 only?** A course or series uploaded as one video has one danmaku track per part. Part 1 is read by default; turn on **Danmaku from every part** and set **Max parts per video** to read more, and each row's `part` and `parts_total` say which part it came from out of how many. When **Max parts per video** leaves parts unread, the run log says how many were skipped.

**Is a proxy included?** A residential proxy is included in the price of the run. To use your own, paste gateway URLs into **Your own proxy URLs**. Scraping at volume? Your own [DataImpulse](https://dataimpulse.com/?aff=404588\&utm_source=apify) account is cheaper per GB.

**Is scraping Bilibili legal?** This actor reads only public pages, the ones any visitor sees, and never signs in as you unless you supply cookies yourself. You are responsible for how you use the data, including copyright in downloaded media and personal data in comments. Check Bilibili's terms and your local rules.

### Related actors

Building a wider video or social pipeline? Pair this actor with:

- [TikTok Video Scraper](https://apify.com/herus13/tiktok-video-scraper) — video metadata, stats and optional video files.
- [TikTok Profile Scraper](https://apify.com/herus13/tiktok-profile-scraper) — creator profiles with follower and engagement counts.
- [YouTube Transcript Scraper](https://apify.com/herus13/youtube-transcript-scraper) — transcripts with timestamps, for the same research in another market.
- [Instagram Post Scraper](https://apify.com/herus13/instagram-post-scraper) — posts with captions, hashtags and engagement.

# Actor input Schema

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

Which kind of record to collect: `search` finds videos by keyword; `video` returns full stats for specific videos; `creator` returns a creator's profile and follower count; `creator_videos` lists a creator's uploads; `comments` returns a video's comments; `fans` lists a creator's followers; `dynamics` reads a creator's feed; `danmaku` returns a video's on-screen bullet comments; `media` returns a download link for the video or its audio. Default search.

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

Search terms, one per entry — for example `python`. Each term returns up to `max_items` videos, ranked the way `order` says. Bilibili search ignores capitals, so terms that differ only in capitals or surrounding spaces are searched, and billed, once. Used when `mode` is search; leave empty for every other mode.

## `video_ids` (type: `array`):

Videos to work on, one per entry, as a BV id (`BV1wD4y1o7AS`), an av id (`av712020469`) or the video part of a bilibili.com URL — the two id styles name the same video and both work. Used when `mode` is video, comments, danmaku or media; leave empty for every other mode.

## `creator_ids` (type: `array`):

Creators to work on, one numeric mid per entry — the number in a `space.bilibili.com/12345` URL. Used when `mode` is creator, creator\_videos, fans or dynamics; leave empty for every other mode.

## `max_items` (type: `integer`):

How many records to return per keyword, video or creator, at least 1. Default 100. Comments: counts top-level comments only; with `include_replies` their replies (up to `max_replies_per_comment` each) come on top, so a run can return and bill more rows than this. Danmaku: applies to each six-minute stretch of a video, not the whole video, and with `danmaku_all_parts` to each stretch of every part read, so a long video returns more rows than this.

## `order` (type: `string`):

How search results are ranked: totalrank for best match, click for most viewed, pubdate for newest, dm for most bullet comments, stow for most favourited. Default totalrank. Used when `mode` is search.

## `duration` (type: `string`):

Keep only search results of this length: any for no filter, under\_10m for under ten minutes, 10\_30m, 30\_60m, over\_60m for over an hour. Default any. Used when `mode` is search.

## `tid` (type: `integer`):

Bilibili category to restrict a search to, given as the numeric tid that appears in a category page's URL. Leave empty to search every category. Used when `mode` is search.

## `include_replies` (type: `boolean`):

Also collect the replies under each comment, as extra rows whose `parent_rpid` names the comment they belong to. Default false, which returns top-level comments only. Used when `mode` is comments.

## `max_replies_per_comment` (type: `integer`):

Most replies to collect under one comment, at least 1. Default 20. It does nothing unless `include_replies` is true.

## `danmaku_all_parts` (type: `boolean`):

Read danmaku from every part of a multi-part video (a course or series uploaded as one video), up to `max_parts` parts, instead of part 1 only. Each row's `part` and `parts_total` say which part it came from out of how many (part 3 of 200). Default false. Used when `mode` is danmaku.

## `max_parts` (type: `integer`):

Most parts of one multi-part video to read danmaku from, counting from part 1, at least 1. Default 10. Every part adds its own requests and rows, so raise it with care on long courses. It does nothing unless `danmaku_all_parts` is true.

## `quality` (type: `string`):

Which stream to download: best for the highest the video offers, 720p or 480p to cap it at that resolution. Default best. A video that offers nothing at the resolution you ask for returns the best one below it, never a larger file than you asked for. Used when `mode` is media.

## `audio_only` (type: `boolean`):

Download the audio track on its own instead of the video file — far smaller, and enough for transcription or music. Default false. Used when `mode` is media.

## `auth` (type: `object`):

Your own Bilibili cookies, as {"cookies": "SESSDATA=..."}, if you want the run to act as your own account — for instance to reach media resolutions Bilibili reserves for members. Leave empty and you need no account at all.

## `proxyUrls` (type: `array`):

Leave empty and the run uses the residential proxy this actor ships with, included in the price of the run. To route the run through your own account instead, add one gateway URL per entry, for example http://user:pass@host:port — works with DataImpulse, Bright Data, Oxylabs, Smartproxy or any provider that issues URLs. When set, only these URLs are used.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "python"
  ],
  "max_items": 100,
  "order": "totalrank",
  "duration": "any",
  "include_replies": false,
  "max_replies_per_comment": 20,
  "danmaku_all_parts": false,
  "max_parts": 10,
  "quality": "best",
  "audio_only": false
}
```

# Actor output Schema

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

One row per record. The kind field says what it is: video, creator, comment, fan or dynamic.

# 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": [
        "python"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("herus13/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 = { "keywords": ["python"] }

# Run the Actor and wait for it to finish
run = client.actor("herus13/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 '{
  "keywords": [
    "python"
  ]
}' |
apify call herus13/bilibili-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,herus13/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/KMnec1T0rAfxS5gl0/builds/88dV1gWPDq4hXVCl0/openapi.json
