# Bilibili Danmaku Scraper: Bullet Comments (B站弹幕) (`molded_mountainpass/bilibili-danmaku-scraper`) Actor

Scrape Bilibili (哔哩哔哩) danmaku (bullet comments) with playback timestamps from videos, searches, creators and the popular or ranking feeds. Keyword filter, free per-video density summaries, sentiment and delta mode. No login, no browser.

- **URL**: https://apify.com/molded_mountainpass/bilibili-danmaku-scraper.md
- **Developed by:** [Divya Raj](https://apify.com/molded_mountainpass) (community)
- **Categories:** Social media, Videos, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 4.00 out of 5 stars

## Pricing

from $1.00 / 1,000 danmakus

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 Danmaku Scraper: bullet comments (B站弹幕) with timestamps

Scrape **Bilibili danmaku** (弹幕, bullet comments) from any video, search, creator or the popular and ranking feeds. Every danmaku comes with its playback time, text, colour, display mode and send time, in one clean dataset you can export as JSON, CSV or Excel.

No login, no cookies, no browser. It talks to Bilibili's JSON API directly, so it is fast and costs **$1.00 per 1,000 danmaku**.

Need video stats, comments, replies, subtitles or creator profiles too? Use the full [Bilibili Scraper](https://apify.com/molded_mountainpass/bilibili-scraper). This Actor is its danmaku-only spinoff, with the same client and the same prices.

### What does Bilibili Danmaku Scraper do?

- **Finds videos from anywhere:** video links, BV/AV IDs, `space.bilibili.com` creator pages, `search.bilibili.com` searches, keywords, creator IDs, or the popular and ranking feeds.
- **Gets more danmaku per video:** Bilibili serves two different danmaku sources to anonymous visitors (a lifetime sample and the most recent few thousand). They barely overlap, so the Actor merges both by default. On a 34-minute video with 128,673 lifetime danmaku, that returned 5,416 rows.
- **Keyword filter:** keep only danmaku containing words you choose. Filtering happens before charging, so you only pay for matches.
- **Free per-video summary:** one free row per video with the danmaku count, a 20-slice density timeline, the busiest moment (`peak_time`) and the most repeated phrases. Find a video's highlight without downloading every row.
- **Sentiment analysis:** label each danmaku positive, neutral or negative, with a score from -1 to 1.
- **Only new danmaku:** scheduled runs skip what earlier runs already returned, so monitoring only pays for new bullet comments.
- **Every multi-part video:** scrape P1, P2 and the rest with `allParts`.

### Who uses it

- **Brand and marketing teams:** see how Chinese viewers react to a product, ad or sponsored video, second by second.
- **Researchers:** build danmaku corpora for NLP, sentiment and audience-engagement studies.
- **Creators and agencies:** find the moments viewers react to most, from the density timeline and `peak_time`.
- **Game and anime studios:** track reactions to trailers, launches and episodes (for example search `原神`).

### How to scrape Bilibili danmaku

1. Paste one or more **video links or BV IDs**, or enter **search keywords** or **creator IDs**.
2. Set how many videos per source and how many danmaku you want, and optionally a **keyword filter**.
3. Click **Start**, then download the results as **JSON, CSV or Excel**, or read them through the API.

Example input: the danmaku of the top 10 search results for `原神`, with a free summary per video.

```json
{
  "searchQueries": ["原神"],
  "maxVideosPerSource": 10,
  "danmakuSource": "both",
  "videoSummary": true
}
```

### Output: one row per danmaku

| Field | Meaning |
|---|---|
| `bvid`, `page` | Video and part (P1, P2, …) |
| `time` | Playback position in seconds |
| `content` | Danmaku text |
| `mode`, `fontsize`, `color` | Scrolling, top or bottom; size; RGB colour as an integer |
| `ctime` | When it was sent (Unix seconds) |
| `mid_hash` | Hash of the sender's UID (no personal data) |
| `sentiment`, `sentiment_score` | With `sentimentAnalysis` on |
| `source` | Which input found the video |

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

Pay per result. Summary rows and error rows are free.

| What | Price |
|---|---|
| Danmaku | $1.00 per 1,000 |
| Sentiment label (optional) | $5.00 per 1,000 |
| Actor start | $0.001 per run |

Set a maximum cost per run and the Actor stops cleanly when it is reached.

### Limits worth knowing

- **Anonymous danmaku are a sample.** Bilibili does not give anonymous visitors every danmaku a video has ever had. Merging both sources gets the most it allows.
- **Some videos are region-locked** and answer non-Chinese IPs with an error. Those videos produce a free error row and the run continues.
- **No login is needed.** A `sessdata` cookie is accepted but optional.

### FAQ

**Do I need a Bilibili account?**
No. Danmaku are public, and the Actor never needs a login.

**What is danmaku?**
Danmaku (弹幕, "bullet comments") are the comments that fly across a Bilibili video at the moment a viewer posted them. Each one is tied to a playback time, which makes them ideal for second-by-second reaction analysis.

**Can I get Bilibili comments and replies too?**
Yes, with the full [Bilibili Scraper](https://apify.com/molded_mountainpass/bilibili-scraper). It scrapes comments with full reply threads, videos, subtitles and creator profiles as well as danmaku.

**Can I monitor a video or creator for new danmaku?**
Yes. Turn on `onlyNewItems` and schedule the Actor. Each run returns only danmaku it has not returned before.

**Can I export to Excel or Google Sheets?**
Yes. Every run downloads as JSON, CSV, Excel, XML or RSS, and works with Make, Zapier, n8n and the Apify API.

### 中文简介

B站弹幕爬虫：按视频链接、BV号、搜索关键词、UP主或热门/排行榜采集哔哩哔哩弹幕，含播放时间、颜色、模式和发送时间。无需登录，支持关键词过滤、弹幕密度时间线、情感分析和增量采集。导出 JSON、CSV 或 Excel，每 1,000 条 $1。

### Support

Found a bug or need a field? Open an issue on the Actor's **Issues** tab.

# Actor input Schema

## `startUrls` (type: `array`):

Video URLs (bilibili.com/video/BV…, b23.tv short links), creator pages (space.bilibili.com/123) or search pages (search.bilibili.com/all?keyword=…).

## `videoIds` (type: `array`):

BV ids or av ids.

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

Each keyword is searched and up to 'Max videos per source' results are used.

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

Creator UIDs. Their uploads are used as videos.

## `feed` (type: `string`):

Also take videos from the popular feed or the top-100 ranking.

## `rankingCategory` (type: `integer`):

0 = all. E.g. 1 animation, 3 music, 4 games, 36 knowledge, 188 tech, 160 life, 211 food.

## `maxItems` (type: `integer`):

Hard cap on danmaku rows for the whole run.

## `maxVideosPerSource` (type: `integer`):

Per search keyword, creator or feed.

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

Absolute date (2024-05-01) or relative ('7 days', '12 hours'). Skips videos published earlier; search and creator pagination stop early, which keeps runs cheap.

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

Absolute date (2024-05-01) or relative ('30 days'). Skips videos published later. Search applies it on Bilibili's side, at no extra cost.

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

Order of search results. Bilibili returns at most 1,000 results per search.

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

Only return search results of this length. Bilibili filters them itself, at no extra cost.

## `uploadOrder` (type: `string`):

Order of a creator's uploads. With 'Newest', 'Published after' stops pagination at the first older upload.

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

0 = everything Bilibili serves.

## `danmakuSource` (type: `string`):

Bilibili serves a sample spread over the video's lifetime (protobuf segments) and the most recent pool of a few thousand (XML). They barely overlap, so 'both' returns the most danmaku for one extra request per video.

## `allParts` (type: `boolean`):

Danmaku for every part (P1, P2, …) instead of only the first.

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

Keep only danmaku whose text contains one of these words (case-insensitive). Filtered before charging, so you pay only for matches. Empty = all danmaku.

## `videoSummary` (type: `boolean`):

Before each video's danmaku, output one uncharged 'summary' row: danmaku count, a 20-slice density timeline, the busiest moment (peak_time), the most repeated phrases and text samples. Computed over the collected (and keyword-filtered) danmaku.

## `summarySamples` (type: `integer`):

How many distinct danmaku texts each summary row includes, spread evenly over the video.

## `sentimentAnalysis` (type: `boolean`):

Labels every danmaku positive, neutral or negative with a score from -1 to 1, using an AI model that understands Bilibili slang. Charged per label as a 'sentiment' event.

## `sentimentApiKey` (type: `string`):

A Groq API key (free at console.groq.com), or a key for the provider below. Leave empty to use the actor's built-in key, which is shared by all users and may hit rate limits. Stored encrypted.

## `sentimentModel` (type: `string`):

Model name at the provider. The default is Qwen3 32B on Groq, which reads Chinese well.

## `sentimentApiUrl` (type: `string`):

Any OpenAI-compatible chat completions API. Default: Groq.

## `onlyNewItems` (type: `boolean`):

Skip danmaku already returned by earlier runs with the same sources. You pay only for what is new, which suits scheduled monitoring.

## `deltaKey` (type: `string`):

Optional name to share delta history between tasks. Defaults to a hash of the sources.

## `sessdata` (type: `string`):

Login cookie from a bilibili.com account. Danmaku don't need it; it only raises some of Bilibili's limits. Stored encrypted.

## `proxyStrategy` (type: `string`):

'Auto' starts with no proxy (cheapest) and escalates to datacenter, then residential proxies only if Bilibili starts blocking.

## `proxyCountry` (type: `string`):

Two-letter code, e.g. HK, TW, SG. Empty = any.

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

Used only with the 'Custom' strategy.

## `maxRequestsPerSecond` (type: `integer`):

Upper limit on requests to Bilibili. Higher is faster but triggers more risk-control blocks.

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

How many videos are scraped at the same time (still bounded by the request rate).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.bilibili.com/video/BV1GJ411x7h7"
    }
  ],
  "feed": "none",
  "rankingCategory": 0,
  "maxItems": 10000,
  "maxVideosPerSource": 20,
  "searchOrder": "totalrank",
  "searchDuration": "any",
  "uploadOrder": "pubdate",
  "maxDanmakuPerVideo": 0,
  "danmakuSource": "both",
  "allParts": false,
  "videoSummary": false,
  "summarySamples": 25,
  "sentimentAnalysis": false,
  "sentimentModel": "qwen/qwen3-32b",
  "sentimentApiUrl": "https://api.groq.com/openai/v1",
  "onlyNewItems": false,
  "proxyStrategy": "auto",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestsPerSecond": 4,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `danmaku` (type: `string`):

No description

## `summaries` (type: `string`):

No description

## `runStats` (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 = {
    "startUrls": [
        {
            "url": "https://www.bilibili.com/video/BV1GJ411x7h7"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("molded_mountainpass/bilibili-danmaku-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 = { "startUrls": [{ "url": "https://www.bilibili.com/video/BV1GJ411x7h7" }] }

# Run the Actor and wait for it to finish
run = client.actor("molded_mountainpass/bilibili-danmaku-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 '{
  "startUrls": [
    {
      "url": "https://www.bilibili.com/video/BV1GJ411x7h7"
    }
  ]
}' |
apify call molded_mountainpass/bilibili-danmaku-scraper --silent --output-dataset

```

## MCP server setup

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