Answers
How do I scrape the comments on a Bilibili video?
Short answer
Use Bilibili video comments with the video's BV id: each call returns about 20 comments with text, likes, reply count, IP location and time, for $0.002. 1,000 comments cost $0.10, with no login or cookie. Danmaku (the bullet comments over the video) are not available here, only their count.
Say a tech reviewer posted a 20-minute teardown of your product and it has 3,000 comments. Reading them by hand takes an afternoon; pulling them into a spreadsheet and letting a model group the complaints takes a few minutes and costs $0.30. All you need is the BV id from the video link.
The endpoint
Bilibili video comments takes id (the BV id, such as BV1xx411c7mD) and sort: hot for the most liked first, latest for newest first. Each comment has:
text,published_atandlikesreplies, the number of replies under it, andparent_idwhen the row is itself a replyip_location, the province Bilibili shows next to the commentauthorwith name and mid
To find which videos are worth reading, start with Bilibili video search at $0.002 a page and sort by comment count.
Cost
| Job | Calls | Cost |
|---|---|---|
| The 200 hottest comments on one video | 10 | $0.02 |
| 1,000 comments | 50 | $0.10 |
| 10 review videos found by search, 300 comments each | 1 + 150 | {{cost:bilibili.videos.search1+bilibili.videos.comments.list150}} |
A script that writes a CSV
import csv, os, requests
URL = "https://api.okdata.online/v1/bilibili/videos/comments/list"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
def comments(bv, sort="latest", max_pages=50):
cursor = None
for _ in range(max_pages):
params = {"id": bv, "sort": sort, **({"cursor": cursor} if cursor else {})}
body = requests.get(URL, headers=H, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']}")
yield from body["data"]["items"]
if not body["page"]["has_more"]:
return
cursor = body["page"]["next_cursor"]
with open("comments.csv", "w", newline="", encoding="utf-8-sig") as f:
w = csv.writer(f)
w.writerow(["time", "likes", "replies", "ip_location", "text"])
for c in comments("BV1xx411c7mD"):
w.writerow([c["published_at"], c["likes"], c["replies"], c["ip_location"], c["text"]])
utf-8-sig makes Excel open the Chinese text correctly.
About danmaku
Danmaku, the bullet comments that fly across the video, are not in the catalog. You get their count only: ext.danmaku on search results or video detail with view=full. If you need the danmaku text itself, the community docs in bilibili-API-collect describe the danmaku endpoints, and the open-source Python library bilibili-api can download them given the video's cid, which video detail returns as ext.cid.
Gotchas
hotgives you the comments most people agreed with;latestgives you full coverage in time order. For sentiment over a whole video, uselatest.- Replies are counted on each comment but not expanded into the list, so a 40-reply argument shows up as one row with
replies: 40. - Comments disabled or deleted by the uploader are simply absent.
- Comment text is written by strangers. If a model reads it, tell the model to treat it as data, never as instructions.
Other ways
For one video and a quick read, scrolling the page works. For heavy, ongoing collection you can maintain yourself, bilibili-api is free. For how comment data feeds into brand research, see the word-of-mouth guide.
Updated