# Bilibili Video Scraper & Growth Analytics (`fascinating_lentil/bilibili-video-growth-analyzer`) Actor

Collect Bilibili video views, likes, coins and related videos. Track changes with CSV/JSON exports. No Bilibili API key. B站视频采集与增长监测。

- **URL**: https://apify.com/fascinating_lentil/bilibili-video-growth-analyzer.md
- **Developed by:** [Md Jakaria Mirza](https://apify.com/fascinating_lentil) (community)
- **Stats:** 2 total users, 1 monthly users, 60.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 video observation saveds

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 Video Scraper & Growth Analytics

Collect public Bilibili video views, likes, coins and other available engagement counters. Discover one-hop related videos, track compatible observations and export nine CSV/JSON/Markdown reports. No Bilibili API key, login, cookies or proxy is required.

For US agencies researching China-market creators, Chinese creator and brand teams, and cross-border content researchers. Original Chinese titles are preserved. This is video-level research, not a source of creator follower totals or viewer-country demographics.

This entrypoint collects video-page observations. The separately retained CSV/JSON analyzer uses different inputs; do not mix the two configurations. Selecting a build or running this code does not create a monitoring schedule or change prices. This is an independent tool, not an official Bilibili service.

### Start with one video

```json
{
  "mode": "video-details",
  "videoUrls": ["BV1rpWjevEip"],
  "maxResults": 1,
  "trackChanges": true,
  "monitorName": "us-china-video-watchlist",
  "maxHistoryPoints": 30,
  "reportLanguage": "en"
}
```

Replace the verification seed with a permitted video relevant to your research. It is not a recommendation or a claim about US viewers.

For related discovery, set `mode` to `related-videos` and start with `maxResults: 3`. The seed counts toward the global limit. Each saved video's counters come from its own retrieved page, not from a recommendation card.

### What the Actor does

- Collect available title, video URL, BV/av identity, public uploader ID/name, publication time, duration and engagement counts.
- Return source-reported views, likes, coins, favorites, shares, comments/replies and danmaku counts where available. Comment and danmaku text are not collected.
- Keep exact, rounded and unknown counters distinct. Rounded estimates never become exact growth.
- Save 2–30 acknowledged observations per video when history tracking is enabled. Compare compatible exact observations for deltas, percentages and hourly rates.
- Calculate observed momentum after at least three compatible observations. This is not a prediction.
- Export per-1,000-view ratios and uploader aggregates for the selected videos, not entire-channel metrics, unique viewers or campaign ROI.
- Include retrieval time, source URL, HTTP/cache metadata and a response-body SHA-256. Source counters and raw responses are not independently audited.

Uploader summaries keep unknown or rounded views separate from numeric-sum overflow. An overflow does not turn later exact observations into missing views. If a subtotal exceeds safe precision, it remains blank with `SUM_UNAVAILABLE_EXCEEDS_SAFE_PRECISION` rather than inventing an exact sum.

Use the same `monitorName` sequentially at appropriately spaced intervals. First observations are baselines. Source counter-refresh times are unknown; cache behavior and short intervals can distort rates. Concurrent runs of the same monitor are unsupported because storage updates are not atomic transactions.

English/Chinese report selection changes selected Markdown headings and notices only. CSV/JSON keys and status codes stay English; original titles and uploader names are not automatically translated.

### CSV and research reports

| Artifact | Purpose |
| --- | --- |
| VIDEOS.csv | Metadata, counters, precision and retrieval evidence. |
| CHANGES.csv | Latest compatible changes and comparison caveats. |
| HISTORY.csv | Observation trail with per-observation persistence flags. |
| MOMENTUM.csv | Changes in observed rates after sufficient history. |
| UPLOADERS.csv | Aggregates for the selected videos only. |
| QUALITY.csv | Missing/rounded fields and input/comparison warnings. |
| REPORT.json / REPORT.md | Structured and readable research summaries. |
| RUN_STATUS.json | Request counts, delivery, limits and completion status. |

Review QUALITY.csv before interpreting changes. Formula-prefix protection is applied to string CSV cells. For Chinese text, import CSV as UTF-8.

History advances only after confirmed result-save and accounting acknowledgment. `historyPersisted` describes each individual observation: a failed new history write does not make earlier saved points unpersisted. Tracking-disabled observations are not saved to history. A zero-result report does not claim successful collection.

A storage or report-delivery failure can occur after a confirmed dataset row, charge or history write. Inspect run status and any available FAILURE.json before retrying manually. Where storage remains available, the failure file identifies confirmed delivery and artifacts already saved; a complete storage outage can prevent that file too. No automatic refund is implied by a missing report.

### Inputs and boundaries

Use 1–50 BV IDs, av IDs or canonical HTTPS video URLs. Short links, arbitrary URLs, API endpoints, login/cookies and proxy fields are unsupported. `maxResults` is a ceiling from 1–50, default 5, not a promised quota. `trackChanges` defaults to true; `maxHistoryPoints` is capped at 30.

Use lowercase ASCII letters, digits, hyphens and underscores in `monitorName`. History is isolated by Apify user, Actor, monitor and counter version.

Multipart selectors such as `?p=2` do not request separate part-level counters. `PART_SELECTOR_IGNORED_VIDEO_LEVEL` appears in `inputWarnings` and the input-level QUALITY.csv row, including when the same video was supplied first as a bare BV ID. Resolved duplicate aliases do not add another result or fee within a run.

At an exact spending cap, finishing the entire queued target list is `SUCCEEDED` with `targets-exhausted`. Pending targets without result capacity produce `SPENDING_LIMIT`, not a claim of full collection. Missing related results are not fabricated to fill the limit.

Live checks used 256 MB, a 90-second run timeout and no automatic restart. The intended live release configuration is the same. The local manifest permits 256–512 MB; equivalent economics at 512 MB have not been established by these checks.

The collector checks crawl rules and reads public video-page HTML with embedded data. It stops on disallowed paths, access challenges and denied/rate-limited responses. It does not execute page scripts, use the API host, solve CAPTCHAs, rotate proxies or retry denied access.

If the canonical video page is the recognized empty client-rendered shell, the collector may request the same video's public `/en/video/` HTML once, only when that route also passes crawl rules. Embedded source titles and counters are retained; the route name does not automatically translate them. The recovery counts toward the existing request/time budget. `clientShellResponses` and `localizedPageRequests` disclose it in the reports, and source evidence identifies the actual retrieved URL. Another empty shell, denied access or invalid data remains a failure, never a synthetic result.

Collection is sequential with at least one second between requests, a 12-second request timeout, a 75-second collection budget, a maximum of 105 HTTP requests including policy checks/redirects, and 2 MiB decoded HTML per page. Source changes can interrupt access. This is not keyword search, a full trending feed, creator-profile/follower scraping, transcript extraction or video downloading.

### Clear pay-per-event pricing

Pay-per-event pricing is $2 per 1,000 successfully saved video observations ($0.002 each), plus an automatic $0.001 start event per allocated GB, minimum one. At 256 MB or 512 MB the start event is charged once.

| Outcome at 256 MB | Listed event charges |
| --- | ---: |
| One saved video observation | $0.003 |
| Three saved video observations | $0.007 |
| Failed lookup with no saved observations | $0.001 start; no video-result fee |

A new saved observation is billed again in a later run. History comparison and reports add no extra result fee. There is no extra dataset fee, tier discount or separately user-paid platform usage under this policy. Confirmed results retain their charges if a later operation fails.

The $0.003 minimum allowed spending cap is not a minimum actual charge. Start applies even to a zero-result failure. A cap excludes further results rather than granting an unlimited collection budget.

The separate retained import version charges $0.002 per successfully saved unique entity analysis, not per supplied snapshot. Its labeled synthetic demos save no dataset results and incur only the automatic start event. Those modes are not inputs to this live entrypoint.

### US and Chinese research starters

Three small research starter configurations:

1. Track Bilibili Video Engagement for US Agency Research — one selected video, English report labels and retained history.
2. Discover Bilibili Related Videos for China Research — a seed plus one-hop discovery, up to three observations globally.
3. B站视频数据采集与增长监测｜中英团队报告 — one selected video, Chinese guidance and selected Chinese Markdown labels.

Use these configurations as research starting points. Example-page availability is separate from this README; no automatic monitoring schedule is created by any of these inputs. Start with one selected video, inspect the baseline, then run the same monitor sequentially when you want another observation.

### 中文使用指南：B站视频数据采集与增长监测

输入BV/av编号或完整视频链接，先运行1条观察记录建立基线。保持相同的 `monitorName`，按合理间隔顺序运行，再比较可比记录。至少3次可比观察可用于分析变化速度，不代表预测。名称只支持小写英文字母、数字、连字符和下划线。

记录源页面提供的播放、点赞、投币、收藏、分享、评论数和弹幕数；不采集评论或弹幕正文。缺失值保持未知，近似计数不会冒充精确增长。分P参数被忽略并给出提示，计数为视频级数据。请使用 QUALITY.csv 和 REPORT.json 检查精度与提示，用 HISTORY.csv 查看确认记录。

`reportLanguage: "zh-CN"` 只切换部分Markdown标题、标签和提示。CSV/JSON字段与状态码保持英文，原始中文标题保留，不自动翻译。Excel中请按UTF-8导入CSV。

费用以美元计算：每条成功保存的观察记录$0.002，另加每次启动$0.001（每分配GB一份，最少一份）。256 MB下单条合计$0.003，三条合计$0.007；后续新观察仍计费。零结果失败只收启动费，不收视频结果费。$0.003是允许设置的最低消费上限，并非最低实际收费。

本工具不是B站官方服务，不提供粉丝总数、受众国家判断、关键词搜索、视频下载、商业授权或收益保证。示例不创建定时任务。

### Verified scope — 20 October 2026

**22 October maintenance repair candidate:** the reported automatic test on build 0.7.1 failed with `PUBLIC_STATE_UNAVAILABLE` after receiving an empty canonical-page shell. This was reproduced locally. The browser-selected `/en/video/` page supplied valid embedded source data, so the local candidate adds the bounded HTML recovery above. The earlier checks below predate this source change and do not verify the new cloud build or clear maintenance. No cloud verification or promotion of this candidate is claimed here.

Private live build 0.5.1 passed a one-video baseline, three-video related discovery and matching one-video repeat at 256 MB without a proxy. Output, exact result/start event counts, all nine reports and seed history 1→2→3 reconciled. The baseline and repeat also covered duplicate multipart input and completion at an exact $0.003 event cap.

Those runs took 3.536–5.274 seconds, with peak memory 46.65–58.00 MiB. The tested runtime passed 218 local tests and 13 installed-SDK offline scenarios, including injected history-write and report-delivery failures. Offline injections are not proof of recovery from every real outage. These runtime checks are separate from GitHub CI. Require the actual verify-job result on the exact intended commit; this README is not a live CI-status indicator.

These finite private checks do not prove every video, region, large batch, concurrent workload or future source change. No synthetic data replaces a failed live lookup. Run reports are deployment-neutral and do not claim to evaluate profitability or settled customer payouts.

This is an independent tool, not affiliated with or endorsed by Bilibili. Public access and a crawl-rule check do not establish commercial source-use rights. Evaluate the source-use rights applicable to your intended use. This tool supplies neither permission nor legal clearance, and functioning public access does not establish commercial clearance.

# Actor input Schema

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

Fetch selected videos or one-hop related videos within the same global limit. 已选视频或一跳关联视频，不是关键词搜索。

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

1–50 canonical video references; no short links/custom URLs. Multi-part ?p= selectors are ignored with a report warning: counts are video-level. 输入BV/av或完整视频链接；不采集单个分P数据。

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

One global limit including seeds; fewer may be available. 同次运行共用上限，包含种子视频；固定75秒采集预算仍适用。

## `trackChanges` (type: `boolean`):

Run the same monitor sequentially. First observation is a baseline, not growth; history advances after confirmed save/billing. 同一监测任务请顺序运行，首次记录仅建立基线。

## `monitorName` (type: `string`):

Keep a stable name for comparisons; scoped by user/Actor/monitor/counter version. 仅支持小写英文字母、数字、连字符和下划线，不支持中文名称。

## `maxHistoryPoints` (type: `integer`):

Retain 2–30 acknowledged observations. Momentum needs at least 3 compatible observations. 保留2–30次确认记录，至少3次可比记录才能分析变化速度的改变。

## `reportLanguage` (type: `string`):

Changes selected Markdown headings/labels and input notices. CSV/JSON keys and status codes stay English; original text is not translated. 仅切换部分Markdown标签，非全文翻译。

## Actor input object example

```json
{
  "mode": "video-details",
  "videoUrls": [
    "BV1rpWjevEip"
  ],
  "maxResults": 5,
  "trackChanges": true,
  "monitorName": "bilibili-video-watchlist",
  "maxHistoryPoints": 30,
  "reportLanguage": "en"
}
```

# Actor output Schema

## `report` (type: `string`):

No description

## `readableReport` (type: `string`):

No description

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

No description

## `changes` (type: `string`):

No description

## `history` (type: `string`):

No description

## `momentum` (type: `string`):

No description

## `uploaders` (type: `string`):

No description

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

No description

## `status` (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 = {
    "videoUrls": [
        "BV1rpWjevEip"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fascinating_lentil/bilibili-video-growth-analyzer").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 = { "videoUrls": ["BV1rpWjevEip"] }

# Run the Actor and wait for it to finish
run = client.actor("fascinating_lentil/bilibili-video-growth-analyzer").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 '{
  "videoUrls": [
    "BV1rpWjevEip"
  ]
}' |
apify call fascinating_lentil/bilibili-video-growth-analyzer --silent --output-dataset

```

## MCP server setup

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

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/cMxtzWA5aDuoh1hLC/builds/1RDRm81xYcxBHc0Au/openapi.json
