# Bilibili Scraper (`mina_safwat/bilibili-scraper`) Actor

Scrapes Bilibili without login: videos with views, likes, coins, favorites, shares, danmaku, tags and uploader followers, from video links, uploader pages or keyword searches.

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

## Pricing

$2.00 / 1,000 results

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

### What does Bilibili Scraper do?

**Bilibili Scraper** collects video data from [Bilibili](https://www.bilibili.com) (哔哩哔哩, B站),
China's biggest video site, **without logging in**. Paste **video links**, **uploader (UP主)
spaces** or **search pages**, or type **keywords**, and get one clean row per video with
**views, likes, coins, favorites, shares, danmaku and comments**, plus the **title,
description, tags, category, duration, cover, publish time, copyright type** and the
**uploader's name and follower count**. Uploader links can also add a profile row with
followers, following, video count, total likes, level and verification.

Every video row has the **same complete set of fields**, whether it came from a link, an
uploader or a search: coins and shares are not left empty for search results.

Try it with the prefilled input: click **Start** and 11 videos arrive in a few seconds.
Because it runs on the Apify platform, you also get API access, scheduled runs,
integrations (Google Sheets, Make, Zapier, webhooks), run monitoring, and automatic retries
through Apify Proxy if Bilibili refuses a request.

### Why scrape Bilibili?

- **Influencer (KOL) research**: compare uploaders by followers, total likes and the
  engagement of their newest or most popular videos.
- **Brand and campaign tracking**: find every video about your product, game or brand and
  follow its views, likes, coins and comments.
- **Market and trend research**: see what Chinese Gen-Z audiences watch, by keyword,
  category, duration or date range.
- **Content strategy**: study titles, tags, categories, video length and publishing times
  of top videos in your niche.
- **Data for analysis and AI**: export structured video metadata at scale.

### How to scrape Bilibili videos

1. Open a Bilibili video, an uploader's space or a search, and copy the address. The text
   the app's **Share** button copies works too.
2. Paste it into **Bilibili links**, one per line. Or type words into **Search keywords**.
3. Set **Max videos per uploader or search**, and choose the order you want.
4. Click **Start**. When the run finishes, download the results.

### Input

Everything is set on the Input tab. The links the Actor understands:

| You paste | You get |
|---|---|
| A video: `https://www.bilibili.com/video/BV1p7411Y7BC`, `av84887919`, an `m.bilibili.com` link, a `b23.tv` short link, or the app's share text | That video |
| An uploader: `https://space.bilibili.com/546195`, `m.bilibili.com/space/…` or `uid:546195` | Their videos, plus a profile row |
| A search page: `https://search.bilibili.com/all?keyword=…` | Its results, with the order, duration, category and date filters set on the page |

In JSON, the input looks like this:

```json
{
    "startUrls": [
        "https://www.bilibili.com/video/BV1p7411Y7BC",
        "https://space.bilibili.com/546195",
        "https://search.bilibili.com/all?keyword=%E6%97%85%E8%A1%8C&order=click&duration=2"
    ],
    "searchKeywords": ["lofi", "原神 攻略"],
    "maxVideos": 50,
    "searchSort": "relevance",
    "uploaderSort": "newest",
    "includeUploaderInfo": true
}
```

| Field | What it does |
|---|---|
| `startUrls` | Video, uploader and search links (see the table above). Bare ids such as `BV1p7411Y7BC` or `uid:546195` work too. |
| `searchKeywords` | Words to search for, in Chinese or any other language. |
| `maxVideos` | Stops after this many videos for each uploader, search link and keyword. Default: 50. A video link always gives its one video. |
| `searchSort` | Order of keyword results: `relevance` (default), `newest`, `mostViewed`, `mostDanmaku`, `mostFavorited` or `mostComments`. Search links keep their own order. |
| `uploaderSort` | Which of an uploader's videos come first: `newest` (default), `mostViewed` or `mostFavorited`. |
| `includeUploaderInfo` | Adds one profile row for each uploader link. Default: on. |
| `proxyConfiguration` | Optional; leave it empty (see the FAQ). |

### Output

Each video becomes one row. Here is a real one, with its description shortened:

```json
{
    "type": "video",
    "bvid": "BV1p7411Y7BC",
    "aid": 84887919,
    "url": "https://www.bilibili.com/video/BV1p7411Y7BC",
    "title": "最强自夸王！！！！！",
    "description": "歌曲：《自夸小队》\n作词/演唱：某幻君，老番茄，中国boy超级大猩猩，花少北…",
    "coverUrl": "https://i2.hdslb.com/bfs/archive/202bc40ecf4991d21df91f52a2d112eddb977de1.jpg",
    "durationSeconds": 231,
    "partCount": 1,
    "publishedAt": "2020-01-25T12:00:12+08:00",
    "category": "原创音乐",
    "categoryV2": "鬼畜调教",
    "copyright": "original",
    "tags": ["发现《自夸小队》", "阴阳怪气", "花少北", "老番茄", "某幻君", "上海ZOO", "中国boy", "自夸小队", "干杯计划", "RAP"],
    "viewCount": 41487287,
    "likeCount": 1970526,
    "coinCount": 1797096,
    "favoriteCount": 910435,
    "shareCount": 249890,
    "danmakuCount": 461655,
    "commentCount": 61758,
    "uploader": {
        "mid": 1577804,
        "name": "某幻君",
        "url": "https://space.bilibili.com/1577804",
        "avatarUrl": "https://i2.hdslb.com/bfs/face/a7eda2f97431d13f89a43b310262d1b19be83c01.jpg",
        "followerCount": 9000635
    },
    "searchRank": null,
    "sourceInput": "https://www.bilibili.com/video/BV1p7411Y7BC/?spm_id_from=333.1007",
    "scrapedAt": "2026-10-08T12:59:06.319415+00:00"
}
```

And an uploader's profile row:

```json
{
    "type": "uploader",
    "mid": 546195,
    "name": "老番茄",
    "url": "https://space.bilibili.com/546195",
    "avatarUrl": "https://i0.hdslb.com/bfs/face/bc5ca101313d4db223c395d64779e76eb3482d60.jpg",
    "bio": "新浪微博：_老番茄_",
    "level": 6,
    "followerCount": 20828051,
    "followingCount": 6,
    "videoCount": 680,
    "likeCount": 195733344,
    "isVerified": true,
    "verification": "2025百大UP主、2025年度商业影响力奖UP主、2022年度联合创作奖UP主",
    "sourceInput": "https://space.bilibili.com/546195",
    "scrapedAt": "2026-10-08T12:59:06.713493+00:00"
}
```

The Output tab has two views, **Videos** and **Uploader profiles**. You can download the
dataset in various formats such as JSON, HTML, CSV, or Excel.

### Data fields

Video rows (`type` is `video`):

| Field | Description |
|---|---|
| `bvid`, `aid` | The video's BV id and av number. |
| `url` | Link to the video. |
| `title`, `description` | As written by the uploader. `description` is `null` when there is none. |
| `coverUrl` | The cover image. |
| `durationSeconds` | Length in seconds (all parts together). |
| `partCount` | Number of parts (分P). |
| `publishedAt` | When it was published, in China Standard Time (UTC+8), ISO 8601, for example `2020-01-25T12:00:12+08:00`: the time Bilibili shows on the video page. |
| `category` | Bilibili's category (zone, 分区) name, such as `单机游戏`. |
| `categoryV2` | The category in Bilibili's newer zone list, such as `旅游记录`. |
| `copyright` | `original` (自制), `repost` (转载) or `unspecified` when the uploader did not say. |
| `tags` | The video's tags. |
| `viewCount`, `likeCount`, `coinCount`, `favoriteCount`, `shareCount`, `danmakuCount`, `commentCount` | Exact counters. A counter Bilibili hides is `null`. |
| `uploader` | The uploader's `mid`, `name`, `url`, `avatarUrl` and `followerCount`. |
| `searchRank` | The video's place in the search results, from 1; `null` for videos from links and uploaders. |
| `sourceInput` | The link or keyword the video was found through. |
| `scrapedAt` | When the row was saved (UTC). |

Uploader rows (`type` is `uploader`): `mid`, `name`, `url`, `avatarUrl`, `bio`, `level`,
`followerCount`, `followingCount`, `videoCount`, `likeCount` (total likes on their videos),
`isVerified`, `verification` (the verification title), `sourceInput` and `scrapedAt`.

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

Bilibili Scraper uses **pay-per-event** pricing: you pay for each row saved (each video or
uploader profile). See the **Pricing** tab for the exact
price.

- Links that return nothing are **never saved as rows, so they are not charged**.
- If you set a maximum cost for a run, the Actor stops as soon as it is reached.
- The Actor uses plain, fast requests and no browser. In our tests 1,000 videos took three
  to four minutes, and the prefilled input under ten seconds.

### Tips for scraping Bilibili

- **Filter with a search link.** Open [Bilibili search](https://search.bilibili.com), set the
  order, duration, category (分区) or publish date there, and paste the address. The filters
  are kept.
- **Go past 1,000 search results.** Bilibili's search stops at about 1,000 videos per search.
  For more, run the same keyword with several date ranges (search links with different
  publish dates).
- **Get an uploader's best videos**: set `uploaderSort` to `mostViewed` or `mostFavorited`.
- **Monitor uploaders**: schedule a daily run with `uploaderSort: newest` and a small
  `maxVideos` to collect their latest videos and stats.
- **Only need videos?** Turn off `includeUploaderInfo`; video rows still carry the uploader's
  name and follower count.
- Each video is saved only once per run, even when several inputs lead to it.

### FAQ, disclaimers and support

**What can't it scrape?** Comments and danmaku texts, live rooms, anime, films and TV series
(番剧/bangumi), and videos that Bilibili shows only to logged-in users, to the uploader, or
not in the region it sees. Such links are listed with the reason in the `FAILED_INPUTS`
record.

**What happens to links that return nothing?** They are not saved as rows, so you are not
charged for them. Each one is listed with its reason in the `FAILED_INPUTS` record of the
run's key-value store, and the run's status message gives the counts. A run fails only when
every input failed because Bilibili could not be reached.

**Do I need a proxy?** No. Bilibili answers the Actor directly. Bilibili limits how fast one
address may ask, so on big runs the Actor also sends requests through Apify's datacenter
proxy, and retries a request that Bilibili keeps refusing through Apify's residential proxy
as a last resort.

**Why do some of an uploader's videos name another uploader?** Bilibili lists videos made
together (合作) on the page of every uploader who took part. The `uploader` field always names
the video's owner, so you can filter on it.

**Why are some search results only loosely related?** Like Bilibili's own search, rare or
misspelled keywords are filled up with loosely related videos. The Actor saves what
Bilibili's search returns, in its order.

**Why are categories in Chinese?** They are Bilibili's own names. `category` uses the zone
list most tools know, and `categoryV2` the newer one Bilibili's website now shows.

**Is it legal to scrape Bilibili?** This Actor reads only public video pages and profiles
that Bilibili shows to any visitor without logging in. Video data and uploader profiles can
still contain personal data, so you are responsible for making sure your use complies with
Bilibili's Terms of Service and with data protection laws such as the GDPR and China's PIPL.
If in doubt, ask a lawyer.

**Found a problem or need a custom solution?** Open an issue on the **Issues** tab and we
will look into it. Custom scrapers and data feeds are available on request.

# Actor input Schema

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

One per line. A video link (https://www.bilibili.com/video/BV1p7411Y7BC, an av number, an m.bilibili.com link, a b23.tv short link, or the whole text the app's Share button copies) gives that video. An uploader's space (https://space.bilibili.com/546195) gives their videos. A Bilibili search page (https://search.bilibili.com/all?keyword=…) gives its results, with the order, duration, category and date filters you set there. Bare ids such as BV1p7411Y7BC, av84887919 or uid:546195 work too. Links that cannot be used are listed in the FAILED_INPUTS record.

## `searchKeywords` (type: `array`):

Words to search Bilibili's videos for, one keyword per line, in Chinese or any other language. Each keyword gives videos in the order chosen under Search order.

## `maxVideos` (type: `integer`):

Stops after this many videos for each uploader link, search link and keyword. A video link always gives its one video. Bilibili's search goes no deeper than about 1,000 videos per search.

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

The order of the videos found for search keywords. Search links keep the order set on the link.

## `uploaderSort` (type: `string`):

Which of an uploader's videos come first, so that the limit above picks their latest or their most popular ones.

## `includeUploaderInfo` (type: `boolean`):

Adds one row for each uploader link with the uploader's follower count, following count, number of videos, total likes, level, verification and bio. Video rows always name their uploader and follower count.

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

Leave this empty: Bilibili answers the Actor directly. On big runs, and whenever Bilibili refuses a request, the Actor also uses Apify's datacenter proxy on its own, and Apify's residential proxy as a last resort. Choose a proxy here only to send every request through it.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.bilibili.com/video/BV1p7411Y7BC"
  ],
  "searchKeywords": [
    "lofi"
  ],
  "maxVideos": 10,
  "searchSort": "relevance",
  "uploaderSort": "newest",
  "includeUploaderInfo": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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": [
        "https://www.bilibili.com/video/BV1p7411Y7BC"
    ],
    "searchKeywords": [
        "lofi"
    ],
    "maxVideos": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("mina_safwat/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 = {
    "startUrls": ["https://www.bilibili.com/video/BV1p7411Y7BC"],
    "searchKeywords": ["lofi"],
    "maxVideos": 10,
}

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

```

## MCP server setup

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