# Bilibili Scraper: videos, comments, danmaku, users & search (`pikoulas/bilibili`) Actor

Scrape Bilibili (哔哩哔哩, B站) videos with views, likes, coins, favorites, shares, danmaku and tags, comments with replies, danmaku (bullet comments), UP主 profiles and uploads, video search past 1,000 results, user search and the Popular list. No login, no cookies, no browser.

- **URL**: https://apify.com/pikoulas/bilibili.md
- **Developed by:** [Spyridon Pikoulas](https://apify.com/pikoulas) (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 $1.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

## Bilibili Scraper

Scrape videos, comments, danmaku, UP主 profiles and search results from Bilibili (哔哩哔哩, B站),
without an account, cookies or a browser:

- **Videos:** any video by its URL, ID (BV1xx411c7mD, av170001) or b23.tv short link, with its
  views, likes, coins, favorites, shares, danmaku and comment counts, tags, parts and uploader.
- **Search:** videos for a keyword, in Chinese or any language, by relevance, most played, newest,
  most danmaku or most favorited, filtered by duration, category and date. Bilibili shows 1,000
  results per search; past that, the run searches date ranges and keeps going. Users (UP主) can be
  searched by keyword too.
- **Users (UP主):** a profile's followers, following, video count, total likes, level,
  verification and live room, and their uploads, newest or most played first.
- **Comments:** the comments of every video, hot or newest first, pinned ones first, with their
  replies.
- **Danmaku (弹幕):** the bullet comments of every video, with their time in the video, in
  timeline order.
- **Popular:** the videos of Bilibili's Popular page (综合热门), in its order.

Every video comes with its title, description, date, duration, category, tags, uploader and
avatar, cover, parts (with their durations), resolution, collection, subtitle languages,
reprint, interactive and charge-only flags, highest rank, and Bilibili's note under it. Every
comment comes with its text, author and their level, likes, reply count, date, pictures, and the
comment it answers, so threads can be rebuilt.

It is fast: 1,500 videos from one search took 17 seconds, and 142 videos with every detail
(from two users' uploads, a search and the Popular list) took 58 seconds. It costs **$1 per 1,000
videos or users**, $0.30 per 1,000 comments and $0.05 per 1,000 danmaku.

### What people use it for

- **Influencer (KOL) discovery in China:** the UP主 of a niche, with their followers, likes and
  what their videos get.
- **Market and brand research:** what Chinese viewers watch and say about a product, a game or a
  brand, with full comment threads and danmaku.
- **Content and trend analysis:** what does well in a category or on the Popular page, by views,
  coins and favorites.
- **Datasets for AI and sentiment analysis:** Chinese comments and danmaku at scale.
- **Monitoring:** new videos for a keyword or from a list of creators since a date.

### How to scrape Bilibili

1. Click **Try for free**; Apify's free plan covers a first run.
2. Enter **Videos**, **Users** or **Search terms**, or turn on the Popular list, and how many
   results you want.
3. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or read them through
   the API.

An input with more options:

```json
{
  "videos": ["https://www.bilibili.com/video/BV1DeaV6uEG1", "av170001"],
  "users": ["https://space.bilibili.com/546195", "2"],
  "maxVideosPerUser": 50,
  "userVideosSort": "click",
  "searchTerms": ["原神", "sourdough"],
  "searchSort": "click",
  "searchDuration": "10to30",
  "maxResultsPerSearch": 200,
  "publishedAfter": "2026-01-01",
  "includePopular": true,
  "maxPopularVideos": 100,
  "maxCommentsPerVideo": 100,
  "commentsSort": "hot",
  "maxRepliesPerComment": 10,
  "maxDanmakuPerVideo": 500
}
```

A Bilibili URL works in any of the lists: a space URL gives the user, a search.bilibili.com URL
the search. Set `searchType` to `users` to search for UP主: each comes with their profile and
uploads. Set `maxVideosPerUser` to 0 for profiles only, or turn off `includeUserDetails` for
uploads only. Turning off `includeVideoDetails` makes searches, uploads and the Popular list much
faster, with what the lists show: search results then have views, likes, favorites, danmaku,
comments and tags but no coins or shares; uploads have views and danmaku.
`searchCategoryId` takes Bilibili's category IDs: 4 games, 17 single-player games, 36 knowledge,
76 food, 188 tech, 3 music, 129 dance, 160 life, 1 animation.

### Output

A video:

```json
{
  "type": "video",
  "id": "BV1DeaV6uEG1",
  "aid": 117348539370363,
  "url": "https://www.bilibili.com/video/BV1DeaV6uEG1",
  "title": "主播退坑4年后回归原神，竟然......",
  "description": "审核辛苦",
  "publishedAt": "2026-09-28T12:04:59Z",
  "durationSeconds": 346,
  "category": "网络游戏",
  "categoryId": 65,
  "views": 85594,
  "likes": 4078,
  "coins": 457,
  "favorites": 471,
  "shares": 431,
  "danmaku": 231,
  "comments": 1344,
  "highestRank": null,
  "tags": ["原神六周年", "游戏杂谈", "原神回坑", "原神", "原神至冬"],
  "uploaderId": "33621433",
  "uploaderName": "小狮子piano",
  "uploaderUrl": "https://space.bilibili.com/33621433",
  "uploaderAvatar": "https://i1.hdslb.com/bfs/face/608c3f526f9eab18ee9b73b212dc67ed45a7353e.jpg",
  "cover": "https://i1.hdslb.com/bfs/archive/cdd33ba451677a7f5974e806c364157f1945d5dc.jpg",
  "partsCount": 1,
  "parts": [{"cid": 42277799526, "page": 1, "title": "主播退坑4年后回归原神，竟然......", "durationSeconds": 346}],
  "cid": 42277799526,
  "width": 1920,
  "height": 1080,
  "isReprint": false,
  "isInteractive": false,
  "isChargeOnly": false,
  "collection": null,
  "collectionId": null,
  "subtitleLanguages": [],
  "note": "个人观点，仅供参考",
  "location": null,
  "input": "原神",
  "position": 2
}
```

A user (`"type": "user"`):

```json
{
  "type": "user",
  "id": "546195",
  "url": "https://space.bilibili.com/546195",
  "name": "老番茄",
  "sign": "新浪微博：_老番茄_",
  "sex": "男",
  "level": 6,
  "avatar": "https://i0.hdslb.com/bfs/face/bc5ca101313d4db223c395d64779e76eb3482d60.jpg",
  "followers": 20805336,
  "following": 6,
  "videos": 678,
  "articles": 0,
  "likes": 195266674,
  "isVerified": true,
  "verification": "2025百大UP主、2025年度商业影响力奖UP主、2022年度联合创作奖UP主",
  "verificationType": "person",
  "isVip": true,
  "vipType": "annual",
  "isSeniorMember": false,
  "birthday": null,
  "school": null,
  "liveRoomId": null,
  "liveRoomUrl": null,
  "liveRoomTitle": null,
  "isLive": null,
  "topPhoto": null,
  "tags": null,
  "input": "https://space.bilibili.com/546195"
}
```

A comment, here a reply:

```json
{
  "type": "comment",
  "id": "315356677217",
  "videoId": "BV1DeaV6uEG1",
  "videoTitle": "主播退坑4年后回归原神，竟然......",
  "text": "商单应该是商单，但是确实一回坑就能去至冬啊",
  "author": "我该以何见亻尔",
  "authorId": "1241947195",
  "authorLevel": 6,
  "authorAvatar": "https://i1.hdslb.com/bfs/face/8574705b40250617680037313a7500d9e1f2c271.jpg",
  "authorIsVip": false,
  "authorIsUploader": false,
  "likes": 7,
  "replyCount": 0,
  "publishedAt": "2026-09-28T12:13:39Z",
  "isReply": true,
  "rootId": "318911462880",
  "parentId": "318911462880",
  "isPinned": false,
  "isLikedByUploader": false,
  "pictures": [],
  "input": "https://www.bilibili.com/video/BV1DeaV6uEG1"
}
```

A danmaku:

```json
{
  "type": "danmaku",
  "id": "2210561664876077568",
  "videoId": "BV1DeaV6uEG1",
  "videoTitle": "主播退坑4年后回归原神，竟然......",
  "cid": 42277799526,
  "part": 1,
  "text": "大家好，蜗牛叉哥",
  "timeSeconds": 0.501,
  "mode": 5,
  "fontSize": 25,
  "color": "#ffaa02",
  "sentAt": "2026-09-28T15:51:25Z",
  "pool": 0,
  "senderHash": "fe2a14c0",
  "input": "https://www.bilibili.com/video/BV1DeaV6uEG1"
}
```

Each reply comes right after its comment. `rootId` is the comment a reply sits under and
`parentId` the one it answers. A danmaku's `mode` is 1 to 3 for scrolling, 4 for bottom and 5 for
top; `senderHash` is Bilibili's hash of the sender's user ID, not the ID itself. `input` says which
video, user, search or `popular` an item came from, and `position` gives a video's place in its
search, uploads or the Popular list.

### Use it as an API

One call runs it and returns the results as JSON (for runs under 5 minutes; longer ones start a
run and read its dataset). Apify's Python and JavaScript clients, and its Make, Zapier and n8n
integrations, work the same way.

```bash
curl -X POST "https://api.apify.com/v2/acts/pikoulas~bilibili/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms": ["原神"], "maxResultsPerSearch": 10, "maxCommentsPerVideo": 20}'
```

AI agents can call it as a tool through Apify's MCP server: `https://mcp.apify.com?tools=pikoulas/bilibili`.

### How much does it cost to scrape Bilibili?

You pay **$0.001 per video or user**, which is $1 per 1,000, **$0.0003 per comment** ($0.30 per
1,000) and **$0.00005 per danmaku** ($0.05 per 1,000). Runs that go through Apify's residential
proxy also pay its traffic, $0.0012 per 100 KB; a video with its details is 8 to 50 KB, which
adds $0.0001 to $0.0006 per video. There are no monthly fees.

### Good to know

- No proxy is needed for most runs. Bilibili's risk control refuses IPs that ask too fast, one
  kind of request at a time; the run keeps to a few requests a second, pauses when refused, and
  then switches to Apify's residential proxy by itself.
- Bilibili shows up to 1,000 results per search. For more, a video search is split into date
  ranges (from `publishedAfter`, or Bilibili's first day, to `publishedBefore` or now), newest
  first. A user search gives at most 1,000 users.
- Danmaku: Bilibili gives the latest few thousand of each part of a video (3,555 of a 34-minute
  video's 8,838), however many there are.
- Comments: every comment and reply can be scraped, logged out (1,327 of 1,327 on a test video,
  and 3,330 replies of one comment).
- `category` is empty for videos given by URL, as Bilibili names categories only in lists;
  `categoryId` is always there.
- A user's birthday, school, live room and top photo come from a second request that Bilibili's
  risk control refuses now and then; those fields are then empty, and the rest of the profile is
  there.
- Subtitles and Bilibili's ranking page need a login, so they aren't included;
  `subtitleLanguages` lists the languages a video has subtitles in.
- A video found by several searches, users or lists is given once per run. Deleted, hidden and
  missing videos and users are skipped, and the log names them. Nothing was region-blocked in
  tests from Europe.

### FAQ

#### Is it legal to scrape Bilibili?

It collects only what Bilibili shows publicly, without logging in. Scraping public data is
generally legal, but personal data is protected by laws such as the GDPR, the CCPA and China's
PIPL, and Bilibili's terms may limit how you use what you collect. If you're unsure, ask a
lawyer; Apify's [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/) is a good
start.

#### Does it need a Bilibili account or cookies?

No. Everything it gives is what Bilibili shows to a visitor who isn't logged in.

#### Something missing or not working?

Open an issue on the **Issues** tab with the input you used, or ask there for a field you need.

# Actor input Schema

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

Video URLs (bilibili.com/video/..., m.bilibili.com, b23.tv short links) or IDs (BV1xx411c7mD, av170001). Each comes with its details, and its comments and danmaku as set below.

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

Space URLs (space.bilibili.com/33621433) or user IDs (UID, mid). Gives each user's profile and uploads, as set below.

## `maxVideosPerUser` (type: `integer`):

Uploads from each user, in the order below. 0 for the profile only.

## `userVideosSort` (type: `string`):

Newest first, or most played first.

## `includeUserDetails` (type: `boolean`):

One item per user: followers, following, video count, likes, level, verification, VIP, sign, birthday, school, live room. Off: their videos only.

## `searchTerms` (type: `array`):

Keywords searched on Bilibili, in Chinese or any language (原神, 美食, iPhone 17). search.bilibili.com URLs work too.

## `searchType` (type: `string`):

Videos, or users (UP主), each with their profile and uploads as set above.

## `maxResultsPerSearch` (type: `integer`):

Videos or users from each search. Bilibili shows up to 1,000 per search; past that, the run searches day ranges and gives thousands (videos only).

## `searchSort` (type: `string`):

The order of a video search.

## `searchDuration` (type: `string`):

Search filter on the video's length.

## `searchCategoryId` (type: `integer`):

Search filter on Bilibili's category (tid): 4 games, 17 single-player games, 36 knowledge, 76 food, 188 tech, 3 music, 129 dance, 160 life, 1 animation. Empty for all. The categoryId of the videos found is in the same tree.

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

Only videos published on or after this date (YYYY-MM-DD, UTC), in searches, users' uploads and the Popular list. Uploads read newest first stop once they get past it; videos given by URL are taken whatever their date.

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

Only videos published on or before this date (YYYY-MM-DD, UTC).

## `includePopular` (type: `boolean`):

The videos of Bilibili's Popular page (综合热门), in its order.

## `maxPopularVideos` (type: `integer`):

Bilibili lists about 650.

## `includeVideoDetails` (type: `boolean`):

Coins, shares, likes, favorites, tags, parts, collection and subtitle languages of every video searches, users and the Popular list give (a request or two each). Off: what the lists show, which is faster: search has views, likes, favorites, danmaku, comments and tags; users' uploads views and danmaku. Videos given by URL always get details.

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

Comments of every video, replies included. 0 for none.

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

Hot (most liked) comments first, or newest first. Pinned comments come first.

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

Replies under each comment, oldest first. 0 for none.

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

Danmaku (弹幕, bullet comments) of every video, with their time in the video, in timeline order. Bilibili gives the latest few thousand of each part. 0 for none.

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

Not needed for most runs. When Bilibili's risk control refuses the run's IP, the run switches to Apify's residential proxy by itself.

## Actor input object example

```json
{
  "videos": [
    "https://www.bilibili.com/video/BV1xx411c7mD"
  ],
  "users": [
    "https://space.bilibili.com/33621433"
  ],
  "maxVideosPerUser": 20,
  "userVideosSort": "pubdate",
  "includeUserDetails": true,
  "searchType": "videos",
  "maxResultsPerSearch": 20,
  "searchSort": "totalrank",
  "searchDuration": "any",
  "includePopular": false,
  "maxPopularVideos": 20,
  "includeVideoDetails": true,
  "maxCommentsPerVideo": 0,
  "commentsSort": "hot",
  "maxRepliesPerComment": 0,
  "maxDanmakuPerVideo": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `users` (type: `string`):

No description

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

No description

## `danmaku` (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 = {
    "videos": [
        "https://www.bilibili.com/video/BV1xx411c7mD"
    ],
    "users": [
        "https://space.bilibili.com/33621433"
    ],
    "maxVideosPerUser": 20,
    "maxResultsPerSearch": 20,
    "maxPopularVideos": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("pikoulas/bilibili").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 = {
    "videos": ["https://www.bilibili.com/video/BV1xx411c7mD"],
    "users": ["https://space.bilibili.com/33621433"],
    "maxVideosPerUser": 20,
    "maxResultsPerSearch": 20,
    "maxPopularVideos": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("pikoulas/bilibili").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 '{
  "videos": [
    "https://www.bilibili.com/video/BV1xx411c7mD"
  ],
  "users": [
    "https://space.bilibili.com/33621433"
  ],
  "maxVideosPerUser": 20,
  "maxResultsPerSearch": 20,
  "maxPopularVideos": 20
}' |
apify call pikoulas/bilibili --silent --output-dataset

```

## MCP server setup

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

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/fuBKPIwgFP7ICv4sP/builds/Ksm22GgtyrmVmIyyN/openapi.json
