# Bilibili On-screen video comments API (bilibili.danmaku)

- Canonical page: https://everyinfra.com/en/bilibili-api/danmaku
- Endpoint: POST https://api.everyinfra.com/api/v1/social with {"platform": "bilibili", "action": "danmaku", "params": {...}}
- Price: $0.000556 per call ($0.56 per 1,000 requests); failed calls and empty results are not charged
- Returns: list, default 50, max 200 per call
- Mode: sync; add "mode": "async" for slow tasks

Bilibili On-screen video comments reads the danmaku of one video: the short remarks viewers send while watching, which appear over the picture at a set moment of playback. Each row carries the text, the playback position in `video_time` and `video_time_seconds`, the display `mode` (scrolling, top or bottom), the `color`, the `pool` and the time it was sent. Creators, marketers and researchers use it to find the moments that drew reactions, check how viewers took a sponsored segment, or study how audiences talk.

`url` needs a full video address whose path holds the BV ID, such as https://www.bilibili.com/video/<BV ID>, and on a video with several parts the rows come from the first part. The same link also serves the Bilibili Comments and Subtitles capabilities, so one list of video links covers the discussion below a video, its on-screen comments and a transcript of its speech.

## Health

- Live health (24h percent, hourly and daily trends): https://api.everyinfra.com/api/v1/social/availability?platform=bilibili&action=danmaku

## Parameters

| name | type | required | default | description |
|---|---|---|---|---|
| url | not declared | yes | not declared | Specifies a full Bilibili video URL, formatted as https://www.bilibili.com/video/<BVID>. The url parameter fetches video comments on comments, first-part timed comments on danmaku, and audio transcription on subtitles, treating each as distinct text sources. The danmaku action must be able to extract a valid BV ID from the provided path. |
| limit | integer (1–200) | no | 50 | The most rows to return in this call, an integer from 1 to 200. The default applies when you leave it out, and a call can return fewer rows. Larger values return 422 before any charge. |

## Response fields (items in `results`)

| field | meaning |
|---|---|
| id | The record's unique ID on the platform. Unique only within one platform; IDs can repeat across platforms. |
| text | Body text with HTML removed, returned in full and never cut short (on a few platforms the list results themselves carry only an excerpt; the platform's field notes say so). |
| video_id | platform-native meaning |
| video_time | platform-native meaning |
| video_time_seconds | platform-native meaning |
| mode | platform-native meaning |
| color | platform-native meaning |
| pool | platform-native meaning |
| sent_at | platform-native meaning |
| platform | Source platform identifier, the same as platform in the request (for example xiaohongshu, tiktok). |

## Example

```bash
curl -X POST 'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer $EVERYINFRA_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "platform": "bilibili",
  "action": "danmaku",
  "params": {
    "url": "https://www.bilibili.com/video/BV1DYjA6KEJ7"
  }
}'
```

```python
import os
import requests

response = requests.post(
    "https://api.everyinfra.com/api/v1/social",
    headers={"Authorization": f"Bearer {os.environ['EVERYINFRA_API_KEY']}"},
    json={
        "platform": "bilibili",
        "action": "danmaku",
        "params": {
            "url": "https://www.bilibili.com/video/BV1DYjA6KEJ7",
        },
    },
    timeout=120,
)
print(response.status_code)
print(response.json())
```

## Response example

Real response to the example request above, captured 2026-10-24T22:01:06Z. `results` and `count` are real with personal information (names, handles, avatars, profile links, contact details) removed; the list keeps the first 2 of 50. `id`, `billing` and `quota` differ on every call, so only their shape is shown.

```text
{
  "id": "req_…",
  "platform": "bilibili",
  "action": "danmaku",
  "results": [
    {
      "id": "•••",
      "text": "前排提醒：請不要刷cp",
      "video_id": "BV1DYjA6KEJ7",
      "video_time": "0:00",
      "video_time_seconds": 0,
      "mode": "top",
      "color": "#E70012",
      "pool": "normal",
      "sent_at": "2026-06-18T13:00:52+00:00",
      "platform": "bilibili"
    },
    {
      "id": "•••",
      "text": "《请输入文本》",
      "video_id": "BV1DYjA6KEJ7",
      "video_time": "0:03",
      "video_time_seconds": 3.522,
      "mode": "top",
      "color": "#00A0EA",
      "pool": "normal",
      "sent_at": "2026-06-19T06:06:24+00:00",
      "platform": "bilibili"
    }
  ],
  "count": 50,
  "billing": {
    "charged": …,
    "charged_usd": …,
    "balance_after_usd": …,
    …
  },
  "quota": { … }
}
```

## FAQ

### How do I find the moments viewers reacted to most?

Group the rows by `video_time_seconds` into short windows, such as ten seconds each, and count the comments in every window. Spikes mark the scenes that set viewers off; read the `text` inside those windows to learn why. Comparing the spikes with the video's chapters or sponsor slot shows which parts landed.

### What is the difference between `video_time_seconds` and `sent_at`?

`video_time_seconds` is where in the video a comment appears, counted in seconds from the start of playback. `sent_at` is when the viewer posted it. The first tells you which scene people reacted to; the second tells you whether the reaction came on release day or months later.

### How do I tie on-screen comments to the video's other data?

`video_id` holds the BV ID on every row. Use it as the key when you join these rows with Bilibili Subtitles results for the same video, which carry the BV ID in `video_id` as well, or with the counts that Bilibili Video details returns for the same link.

## Also

- Capability catalog (no key): https://api.everyinfra.com/api/v1/social/catalog?platform=bilibili
- OpenAPI: https://everyinfra.com/openapi.json · Agents guide: https://everyinfra.com/agents.md
