# Bilibili Scraper - Videos, Comments, Danmaku & Subtitles (`groupoject/bilibili-scraper`) Actor

Bilibili scraper for videos, search, UP master profiles, comments, danmaku (弹幕) and subtitles. Clean English fields, ISO dates, full stats with coins and shares. Monitor new uploads. No login or cookies.

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

## Pricing

from $3.80 / 1,000 result rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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** pulls videos, search results, UP master (UP主) profiles, comments, danmaku (弹幕 bullet comments) and subtitles from Bilibili (哔哩哔哩, B站) as clean JSON. Every row has the same English field names, ISO 8601 dates, numeric counts and full URLs, so it drops straight into a spreadsheet, a database or an AI pipeline. No Bilibili account, cookies or login needed.

![Bilibili Scraper output in Apify: video title, URL, uploader, views, likes, coins, favorites, shares, danmaku count and comment count](https://api.apify.com/v2/key-value-stores/lwQu1lCMCLQIIhSMQ/records/bilibili-scraper-output.png)

*Real output from a default run of Bilibili Scraper in Apify Console.*

### What can it do?

- **Search Bilibili videos by keyword**: sort by relevance, views, newest, danmaku or favorites; filter by length and publish date. Up to 1,000 videos per keyword (Bilibili's own limit).
- **Get full video details from a link or id**: BV ids, av ids, desktop/mobile URLs, `?p=` parts and b23.tv short links. You get views, likes, coins, favorites, shares, danmaku and comment counts, tags, partition (分区), part count and the uploader's follower count.
- **Scrape UP master profiles and uploads**: followers, following, total likes, video count, level, verification (认证), VIP label, live room, plus every uploaded video, newest or most viewed first.
- **Scrape comments and replies**: hot or newest first, pinned comments flagged, reply threads with the parent and root comment ids, likes, author level and IP region.
- **Scrape danmaku (弹幕)**: text, position in the video in seconds, display mode, colour and send time. Get one row per video (cheaper) or one row per bullet comment.
- **Get subtitles and transcripts (字幕)**: creator or AI-generated (`ai-zh`) subtitle tracks as timed segments plus the full text. Videos without subtitles cost nothing.
- **Track what is hot**: Bilibili's popular (热门) feed and the trending search (热搜) keyword list.
- **Monitor new uploads**: "Only new videos" remembers what earlier runs delivered, so a scheduled run returns (and charges for) new videos only.

### What data do you get?

Every row has a `dataType` field: `video`, `comment`, `user`, `danmaku`, `subtitle` or `trendingKeyword`. The dataset has a tab for each type.

| Field | Type | Example |
|---|---|---|
| `bvid`, `aid`, `cid` | string | `BV1chxT6xEyo`, `117512402370778`, `43092804680` |
| `url` | string | `https://www.bilibili.com/video/BV1chxT6xEyo` |
| `title`, `description` | string | original Chinese text |
| `durationSeconds` | number | `263` |
| `publishedAt` | ISO 8601 | `2026-10-27T10:34:07.000Z` |
| `ownerMid`, `ownerName`, `ownerUrl`, `ownerFollowers` | string / number | UP master id, name, space URL, followers |
| `views`, `likes`, `coins`, `favorites`, `shares`, `danmakuCount`, `commentCount` | number | full engagement stats |
| `tags` | string\[] | `["攻略", "单机游戏"]` |
| `coverUrl` | string | https cover image |
| `categoryId`, `categoryName` | number / string | Bilibili partition, e.g. `单机游戏` |
| `parts`, `isOriginal`, `publishLocation` | number / boolean / string | 分P count, 自制 vs 转载, region |
| `detailLevel` | string | `full` (video's own record) or `listing` (search / list page) |
| `source`, `searchQuery`, `position` | string / number | where the row came from and its rank |

Comment rows add `commentId`, `text`, `likes`, `replyCount`, `isReply`, `rootCommentId`, `parentCommentId`, `authorMid`, `authorName`, `authorLevel`, `location`, `isPinned`, `likedByUploader`, `pictures`. User rows add `followers`, `following`, `totalLikes`, `videoCount`, `level`, `isVerified`, `verificationTitle`, `vipLabel`, `liveRoomUrl`, `isLive`. Danmaku rows add `text`, `timeSeconds`, `timeFormatted`, `mode`, `color`, `sentAt` (or an `items` array per video). Subtitle rows add `language`, `isAiGenerated`, `segments[{start, end, text}]` and `fullText`.

Search results and creator lists don't include coins and shares, so those fields are `null` there and never a made-up 0. Turn on **Fetch full video details** to fill them in.

### How much does it cost?

You pay per result (Pay-Per-Event). Nothing is charged for errors, duplicates, skipped "already seen" videos or videos without subtitles.

| Event | Price |
|---|---|
| Actor start | $0.003 per run |
| Result row (any video, comment, reply, user, danmaku or trending row) | **$5.00 per 1,000** |
| + Video detail (videos mode, or "Fetch full video details") | +$4.00 per 1,000 videos |
| + UP master profile | +$4.00 per 1,000 profiles |
| + Danmaku, one row per video | +$7.00 per 1,000 videos |
| + Subtitle / transcript found | +$22.00 per 1,000 transcripts |

On paid Apify plans the per-row price drops automatically (Bronze and above get volume discounts); the Pricing tab shows your exact rate.

Examples:

- **500 search results** for two keywords: $0.003 + 500 × $0.005 = **$2.50**.
- **One video deep-dive** (details, 100 comments with 300 replies, the danmaku pool and the transcript): $0.003 + $0.009 + 400 × $0.005 + $0.012 + $0.027 = **$2.05**.
- **Daily monitor** of one keyword that finds about 30 new videos a day: about **$0.15 a day**.

Set a maximum charge per run in the run options; the Actor stops cleanly when it gets there and keeps everything it collected.

### How to use it

1. Open the Actor and pick **What to scrape** (the default, Popular videos, finishes in a few seconds).
2. Fill the field for that mode: keywords, video links, or UP master UIDs / space URLs.
3. Set **Max results per input**, plus any filters and extras (comments, danmaku, subtitles).
4. Click **Start**. Download the results as JSON, CSV, Excel or HTML, or read them through the API.
5. For monitoring, turn on **Only new videos**, give the monitor a **state key**, and add a schedule.

### Input example

```json
{
  "mode": "search",
  "searchQueries": ["黑神话悟空", "Genshin Impact"],
  "sortBy": "newest",
  "publishedAfter": "7 days",
  "maxResults": 100,
  "fetchFullDetails": true,
  "includeComments": true,
  "maxCommentsPerVideo": 20,
  "onlyNew": true,
  "stateKey": "game-launch-monitor"
}
```

### Output example

```json
{
  "dataType": "video",
  "bvid": "BV1chxT6xEyo",
  "aid": "117512402370778",
  "cid": "43092804680",
  "url": "https://www.bilibili.com/video/BV1chxT6xEyo",
  "title": "奶奶的皱纹里，藏着我一生的甜与暖",
  "description": "",
  "durationSeconds": 263,
  "publishedAt": "2026-10-27T10:34:07.000Z",
  "ownerMid": "239555119",
  "ownerName": "Example UP master",
  "ownerUrl": "https://space.bilibili.com/239555119",
  "ownerFollowers": 47875,
  "views": 1466192,
  "likes": 170483,
  "coins": 78035,
  "favorites": 12144,
  "shares": 1185,
  "danmakuCount": 2028,
  "commentCount": 7963,
  "tags": ["奶奶带大的孩子", "隔辈亲"],
  "coverUrl": "https://i0.hdslb.com/bfs/archive/example.jpg",
  "categoryId": 2154,
  "categoryName": "剧情演绎",
  "parts": 1,
  "isOriginal": false,
  "publishLocation": "浙江",
  "detailLevel": "full",
  "source": "popular",
  "searchQuery": null,
  "position": 1,
  "scrapedAt": "2026-10-28T20:08:42.174Z"
}
```

```json
{
  "dataType": "subtitle",
  "bvid": "BV17Z421K7ib",
  "videoUrl": "https://www.bilibili.com/video/BV17Z421K7ib",
  "title": "Example walkthrough, part 1",
  "language": "ai-zh",
  "languageName": "中文",
  "isAiGenerated": true,
  "availableLanguages": ["ai-zh"],
  "segmentCount": 950,
  "durationSeconds": 3172.04,
  "fullText": "大家好\n我是…",
  "segments": [{ "start": 1.54, "end": 1.9, "text": "大家好" }]
}
```

### Use with the API

cURL (run and get the items in one call):

```bash
curl -X POST "https://api.apify.com/v2/acts/groupoject~bilibili-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"search","searchQueries":["原神"],"maxResults":50,"sortBy":"newest"}'
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("groupoject/bilibili-scraper").call(run_input={
    "mode": "comments",
    "videoUrls": ["https://www.bilibili.com/video/BV1chxT6xEyo"],
    "maxResults": 200,
    "includeReplies": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["dataType"], item.get("text") or item.get("title"))
```

JavaScript:

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('groupoject/bilibili-scraper').call({
    mode: 'user',
    userIds: ['https://space.bilibili.com/546195'],
    maxResults: 30,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use with AI agents (MCP)

Add the Actor to Claude, Cursor or any MCP client through the Apify MCP server:
`https://mcp.apify.com?tools=groupoject/bilibili-scraper`

Example prompt: *"Use the Bilibili Scraper to get the transcript and top 50 comments of BV1g1C6Y2Ef3, then summarise what viewers liked."*

### Integrations

Send results to **Google Sheets**, **Make**, **Zapier**, **n8n**, Slack or your own **webhook** when a run finishes. Pair "Only new videos" with an Apify schedule to get a daily feed of new uploads for a keyword or a creator.

### FAQ

#### Is it legal to scrape Bilibili?

The Actor reads only public data that any visitor can see without logging in: videos, public profiles, comments, danmaku and subtitles. It doesn't access accounts or private content. Personal data in comments (user names, regions) can still fall under laws such as GDPR or China's PIPL, so use it for legitimate purposes and check with your lawyer if you're unsure.

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

No. Everything works without login or cookies, and you don't need to configure proxies.

#### How many results can I get?

Bilibili returns at most 1,000 videos per search keyword; use several keywords or date ranges for more. Creator uploads go back up to 2,500 videos per UP master. Comments and replies page until the thread ends or your limit. Danmaku come from the pool Bilibili serves, usually the latest 1,000–8,000 depending on video length.

#### Why are coins or shares empty for some videos?

Search results and creator lists don't carry coins and shares. Turn on **Fetch full video details**, or use videos or popular mode, to get them.

#### Why did a video give no subtitles?

Many Bilibili videos have no subtitle track (music, gameplay without talking, older uploads). Those videos are listed in the `ERRORS` record with `NO_SUBTITLES` and are not charged.

#### How fast is it?

About 1–3 seconds per page of 20–50 results. A 1,000-video search takes well under a minute. Subtitle lookups are slower (5–15 seconds each), so the Actor runs several in parallel.

#### How do I monitor new videos every day?

Pick search or user mode, set sort order to **Newest**, turn on **Only new videos**, choose a **state key**, and create a schedule. Each run returns only videos that earlier runs haven't delivered.

#### Why did my run stop early?

It stops cleanly when it reaches your maximum charge, gets close to the run timeout, or keeps paying for data lookups that return nothing (for example, a long list of videos that all lack subtitles). The `SUMMARY` record explains which one happened, and every row collected up to that point is kept.

### Related actors

- [YouTube Scraper API](https://apify.com/groupoject/youtube-scraper-api): search results, playlists and video details from YouTube.
- [YouTube Comments Scraper](https://apify.com/groupoject/youtube-comments-scraper-api): comments and replies for YouTube videos and Shorts.
- [YouTube Transcript Scraper](https://apify.com/groupoject/youtube-transcript-scraper): captions and transcripts with timestamps.
- [YouTube Channel Monitor](https://apify.com/groupoject/youtube-channel-monitor): new-video alerts for channels.
- [Reddit Scraper](https://apify.com/groupoject/reddit-scraper): posts, comments and search from Reddit.
- [Google Trends Scraper](https://apify.com/groupoject/trendpulse-keyword-monitor): interest over time and rising queries.

# Actor input Schema

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

popular = Bilibili's current popular (热门) videos; search = videos for keywords; videos = full details for video links or BV/av ids; user = UP master profile and uploaded videos; comments / danmaku / subtitles = that data for video links; trending = the hot-search (热搜) keyword list.

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

Used in search mode. One keyword or phrase per line, in Chinese or English (for example 原神, 黑神话悟空 攻略, machine learning). Bilibili returns at most 1,000 videos per keyword.

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

Used in videos, comments, danmaku and subtitles modes. Accepts bilibili.com/video/BV… links (desktop or mobile, ?p= part numbers kept), b23.tv short links, BV ids (BV1chxT6xEyo) and av ids (av170001).

## `userIds` (type: `array`):

Used in user mode. UP master UIDs (546195) or space.bilibili.com/546195 links.

## `maxResults` (type: `integer`):

Popular / trending: total rows. Search: videos per keyword (Bilibili caps a keyword at 1,000). User: videos per UP master. Comments: top-level comments per video. Danmaku: bullet comments per video. Every saved row is a paid result, so this is your main cost control.

## `sortBy` (type: `string`):

Search mode only. Use "Newest" for monitoring with "Only new videos".

## `durationFilter` (type: `string`):

Search mode only. Filter by video duration.

## `publishedAfter` (type: `string`):

Search, user and popular modes. Keep only videos published on or after this date: YYYY-MM-DD, an ISO date-time, or a relative window such as "7 days" or "24 hours".

## `publishedBefore` (type: `string`):

Search, user and popular modes. Keep only videos published before this date (same formats as above).

## `userVideoSort` (type: `string`):

User mode only. Order in which a creator's uploads are read.

## `includeUserProfile` (type: `boolean`):

User mode: save one profile row per creator (followers, following, total likes, video count, level, verification, live room).

## `includeUserVideos` (type: `boolean`):

User mode: save the creator's uploaded videos (up to "Max results per input").

## `fetchFullDetails` (type: `boolean`):

Search, user and popular modes: look up each video's own record to add coins, shares, likes, all tags, cid, part count and the uploader's follower count. Search and creator lists do not include coins and shares. Adds the "video detail" charge per video.

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

Search, user, popular and videos modes: also save comments for every video found.

## `maxCommentsPerVideo` (type: `integer`):

Top-level comments per video when "Include comments" is on (comments mode uses "Max results per input").

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

Hot = Bilibili's top comments first; Newest = most recent first.

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

Also save replies under each comment (rows with isReply = true), up to "Max replies per comment".

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

Replies saved under each top-level comment when replies are on.

## `includeDanmaku` (type: `boolean`):

Search, user, popular and videos modes: also save each video's danmaku (bullet comments). For multi-part videos this is the first part (or the ?p= part you linked).

## `maxDanmakuPerVideo` (type: `integer`):

Danmaku kept per video, earliest in the video first (danmaku mode uses "Max results per input"). Bilibili serves a pool of the latest ~1,000–8,000 danmaku depending on video length.

## `danmakuFormat` (type: `string`):

One row per video (all danmaku in an items array plus fullText; one paid row plus the danmaku charge) or one row per bullet comment (each bullet is a paid row).

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

Search, user, popular and videos modes: also save the video's subtitle track (creator or AI-generated ai-zh) as timed segments plus full text. Videos without subtitles give no row and are not charged.

## `subtitleLanguage` (type: `string`):

Language code to prefer when a video has several tracks (zh, en, ja, ai-zh…). Falls back to the first available track.

## `onlyNew` (type: `boolean`):

Search and user modes: skip (and don't charge for) videos already delivered by earlier runs with the same state key. Schedule the Actor to get a feed of new uploads. Works best with sort order "Newest".

## `stateKey` (type: `string`):

Name of the memory used by "Only new videos". Use a different key for each independent monitor (for example brand-a, competitor-ups).

## `tikhubApiKey` (type: `string`):

Leave empty to use the Actor's built-in data access. If you have your own TikHub key you can enter it here; it is stored encrypted and never logged.

## Actor input object example

```json
{
  "mode": "popular",
  "searchQueries": [
    "原神"
  ],
  "videoUrls": [
    "https://www.bilibili.com/video/BV1g1C6Y2Ef3"
  ],
  "userIds": [
    "https://space.bilibili.com/546195"
  ],
  "maxResults": 20,
  "sortBy": "relevance",
  "durationFilter": "any",
  "userVideoSort": "newest",
  "includeUserProfile": true,
  "includeUserVideos": true,
  "fetchFullDetails": false,
  "includeComments": false,
  "maxCommentsPerVideo": 20,
  "commentSort": "hot",
  "includeReplies": false,
  "maxRepliesPerComment": 10,
  "includeDanmaku": false,
  "maxDanmakuPerVideo": 1000,
  "danmakuFormat": "perVideo",
  "includeSubtitles": false,
  "subtitleLanguage": "zh",
  "onlyNew": false,
  "stateKey": "default"
}
```

# Actor output Schema

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

All rows; each has a dataType field.

## `summary` (type: `string`):

Rows by type, data-source calls and cost, stop reason.

## `errors` (type: `string`):

Inputs that could not be scraped and videos without subtitles (never charged).

# 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": [
        "原神"
    ],
    "videoUrls": [
        "https://www.bilibili.com/video/BV1g1C6Y2Ef3"
    ],
    "userIds": [
        "https://space.bilibili.com/546195"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("groupoject/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": ["原神"],
    "videoUrls": ["https://www.bilibili.com/video/BV1g1C6Y2Ef3"],
    "userIds": ["https://space.bilibili.com/546195"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("groupoject/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": [
    "原神"
  ],
  "videoUrls": [
    "https://www.bilibili.com/video/BV1g1C6Y2Ef3"
  ],
  "userIds": [
    "https://space.bilibili.com/546195"
  ],
  "maxResults": 20
}' |
apify call groupoject/bilibili-scraper --silent --output-dataset

```

## MCP server setup

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