# Bilibili Video Search, Ranking & Metadata Scraper (`nimbryxo-studio/bilibili-video-search-ranking-and-metadata-scraper`) Actor

Search Bilibili videos by keyword, look up specific videos by URL or ID, or pull the popular feed and partition ranking charts, with view, like and danmaku counts.

- **URL**: https://apify.com/nimbryxo-studio/bilibili-video-search-ranking-and-metadata-scraper.md
- **Developed by:** [Nimbryxo-studio](https://apify.com/nimbryxo-studio) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Video Search, Ranking & Metadata Scraper

Bilibili is one of China's largest video platforms, and this actor reads its public video data four ways: keyword search, direct lookup by video URL/BV ID/AV ID, the site-wide popular feed, or a partition's ranking chart.

### What this actor does

- Switches between four modes via `mode`: `search`, `byVideoUrl`, `popular`, and `ranking`.
- Searches by keyword with sort order (total rank, most viewed, newest, most danmaku, rating score), a partition filter, and a duration-range filter.
- Fetches specific videos directly by full URL, bare BV ID, or numeric AV ID.
- Pulls the site's popular feed or one of 15 ranking charts (site-wide plus 14 partitions such as anime, music, game and food).
- Filters results in every mode by minimum view count or a title/description/author keyword.
- Omits any field a given video doesn't have, so which fields appear depends on the mode (see the notes under the table).

### Output per video

| Field | Description |
|---|---|
| `bvid` | Bilibili's BV-format video ID. |
| `aid` | Bilibili's numeric video ID (AV ID). |
| `title` | Video title, with search-highlight markup stripped. |
| `description` | Video description. |
| `author` | Uploader's display name. |
| `authorMid` | Uploader's numeric member ID. |
| `viewCount` | Total play count. |
| `danmaku` | Danmaku (bullet comment) count. |
| `replyCount` | Comment count. |
| `favorites` | Favorite/collection count. |
| `likeCount` | Like count. |
| `coinCount` | Coin count (Bilibili's tipping currency). |
| `shareCount` | Share count. |
| `duration` | Video length in seconds. |
| `durationText` | Video length formatted as `H:MM:SS`. |
| `coverUrl` | Cover image URL. |
| `publishTime` | Publish timestamp, UTC ISO format. |
| `publishDate` | Publish date (`YYYY-MM-DD`), only on reduced search records (see below). |
| `typeName` | Partition/category label. |
| `uploadRegion` | Uploader's declared location, when published. |
| `pageCount` | Number of parts, on multi-part uploads only (not in `search` mode). |
| `resolution` | Video resolution (e.g. `1920x1080`), when available (not in `search` mode). |
| `tags` | Up to 15 tags attached to the video (search mode only). |
| `videoUrl` | Canonical URL of the video on bilibili.com. |
| `sourceUrl` | The page or chart the record was read from (the video page in `search` mode, the popular/ranking chart or lookup request in other modes). |
| `recordType` | `"video"` for a normal record, `"error"` for an error record (see below). |
| `scrapedAt` | UTC timestamp of when the record was scraped. |

If Bilibili's regular search results can't be loaded for a page, the actor reads the public search page instead. Those reduced search records carry only `bvid`, `videoUrl`, `title`, `author`, `publishDate`, `coverUrl`, `viewCount`, `danmaku`, `duration` and `durationText`, and the `order`, `tids` and `duration` filters are not applied to them.

### Error records

The dataset can also contain records with `recordType: "error"`, written at the end of the run and not counted toward `maxItems`. They have `errorType` (`invalid_input`, `not_found` or `fetch_error`), `message`, `sourceUrl` (the input or request that failed) and `scrapedAt`. They appear for an unresolvable video URL or BV ID, a video that can't be found, an empty search query, missing lookup inputs, or a search/popular/ranking request that fails.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | String (select) | `search` | `search`, `byVideoUrl`, `popular`, or `ranking`. |
| `searchQuery` | String | `python` | Keyword to search. Used in `search` mode; an empty query produces an `invalid_input` error record. |
| `videoUrls` | List of strings | `[]` | Bilibili video URLs (`https://www.bilibili.com/video/BV...`). Used in `byVideoUrl` mode. The URL must contain a BV ID; `b23.tv` short links and `av`-style URLs come back as error records. |
| `bvids` | List of strings | `[]` | Bare BV IDs. Used in `byVideoUrl` mode. |
| `aids` | List of strings | `[]` | Numeric video IDs (AV IDs). Used in `byVideoUrl` mode; non-numeric entries are skipped. |
| `rid` | String (select) | `0` | Ranking partition (15 options, e.g. anime, music, game). Used in `ranking` mode. |
| `order` | String (select) | `totalrank` | Search sort: `totalrank`, `click`, `pubdate`, `danmaku`, or `scores`. Used in `search` mode. |
| `tids` | String (select) | `0` | Restrict search results to one partition. Used in `search` mode. |
| `duration` | String (select) | `0` | Restrict search results by length: all, under 10 min, 10-30 min, 30-60 min, over 60 min. Used in `search` mode. |
| `minViewCount` | Integer | – | Drop videos with fewer views than this (videos without a view count are dropped too). Applies to every mode. |
| `containsKeyword` | String | – | Only keep videos whose title, description, or author contains this substring (case-insensitive). Applies to every mode. |
| `maxItems` | Integer | `20` | Maximum video records to return (1–500). `search` and `popular` read at most 10 result pages and `ranking` reads one chart, so the real ceiling can be lower. |

#### Example: most-viewed Python tutorials

```json
{
  "mode": "search",
  "searchQuery": "python",
  "order": "click",
  "minViewCount": 100000,
  "maxItems": 15
}
```

#### Example: 30-60 minute food videos from the food partition

```json
{
  "mode": "search",
  "searchQuery": "美食",
  "tids": "211",
  "duration": "3",
  "maxItems": 10
}
```

#### Example: a specific video by URL

```json
{
  "mode": "byVideoUrl",
  "videoUrls": ["https://www.bilibili.com/video/BV1wD4y1o7AS/"]
}
```

#### Example: music partition ranking chart

```json
{
  "mode": "ranking",
  "rid": "3",
  "maxItems": 20
}
```

### Use cases

- **Creator discovery** — search a niche keyword to find active uploaders and their typical view counts.
- **Trend tracking** — pull a partition's ranking chart on a schedule to see which content is climbing.
- **Content research** — compare titles, durations and engagement across the videos a keyword surfaces.
- **Catalog lookups** — resolve a known list of BV IDs or video links into full metadata in one run.
- **Category benchmarking** — compare average view/like/danmaku counts across different partitions via `ranking`.

### FAQ

**Do I need a Bilibili account?** No. Every mode reads public video data only.

**What's the difference between `tids` in search mode and `rid` in ranking mode?** They use the same partition ID list, but `tids` narrows a keyword search to one partition while `rid` selects which partition's ranking chart to fetch — `ranking` mode has no keyword at all.

**Why is `tags` only present on search-mode records?** Bilibili's search results API returns tags directly on each result; the popular, ranking and direct-video lookups don't expose that field on the same payload.

**Why do I get fewer videos than `maxItems`?** Search and the popular feed stop after 10 result pages, a ranking chart is a single fixed list, and `minViewCount`/`containsKeyword` drop records after they are fetched. Any of these can leave you below the cap.

**What happens if I pass an invalid BV ID or URL?** That entry produces a record with `recordType: "error"` instead of being silently dropped, so you can see exactly which inputs failed. Non-numeric `aids` entries are the exception: they are skipped without an error record.

**Why do some search records have `publishDate` instead of `publishTime`?** Those are the reduced search records read from Bilibili's public search page when the regular results can't be loaded; that page only shows a calendar date. Every other video record carries the full `publishTime` timestamp when Bilibili provides one.

**Can I fetch a specific uploader's full video list?** No, not in this version — only search, direct video lookup, popular feed, and partition rankings are supported.

**Is this affiliated with Bilibili?** No. This is an independent tool and is not affiliated with, endorsed by, or sponsored by Bilibili or its operators.

# Actor input Schema

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

What to fetch.

## `searchQuery` (type: `string`):

Keyword, e.g. `python` or `美食`.

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

Bilibili video URLs, e.g. https://www.bilibili.com/video/BV1xx411c7mD/

## `bvids` (type: `array`):

Bilibili BV IDs, e.g. BV1xx411c7mD

## `aids` (type: `array`):

Bilibili numeric video IDs (aid), e.g. 170001

## `rid` (type: `string`):

Bilibili partition id (mode=ranking).

## `order` (type: `string`):

Search result ordering (mode=search).

## `tids` (type: `string`):

Narrow search results to one Bilibili partition, same ids as ranking (mode=search).

## `duration` (type: `string`):

Keep only videos within this length range (mode=search).

## `minViewCount` (type: `integer`):

Drop videos with fewer views.

## `containsKeyword` (type: `string`):

Only keep videos whose title, description or author contains this substring (case-insensitive).

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "python",
  "videoUrls": [],
  "bvids": [],
  "aids": [],
  "rid": "0",
  "order": "totalrank",
  "tids": "0",
  "duration": "0",
  "maxItems": 20
}
```

# Actor output Schema

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

Dataset containing all scraped Bilibili videos.

# 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": "search",
    "searchQuery": "python",
    "videoUrls": [],
    "bvids": [],
    "aids": [],
    "rid": "0",
    "order": "totalrank",
    "tids": "0",
    "duration": "0",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("nimbryxo-studio/bilibili-video-search-ranking-and-metadata-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": "search",
    "searchQuery": "python",
    "videoUrls": [],
    "bvids": [],
    "aids": [],
    "rid": "0",
    "order": "totalrank",
    "tids": "0",
    "duration": "0",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("nimbryxo-studio/bilibili-video-search-ranking-and-metadata-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": "search",
  "searchQuery": "python",
  "videoUrls": [],
  "bvids": [],
  "aids": [],
  "rid": "0",
  "order": "totalrank",
  "tids": "0",
  "duration": "0",
  "maxItems": 20
}' |
apify call nimbryxo-studio/bilibili-video-search-ranking-and-metadata-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nimbryxo-studio/bilibili-video-search-ranking-and-metadata-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/f6Gftf5vOWMMfxpe1/builds/O2KhKWh7174T7lI50/openapi.json
