Bilibili 哔哩哔哩 B站 Scraper: All Comments per Video, No Login
Pricing
from $2.50 / 1,000 videos
Bilibili 哔哩哔哩 B站 Scraper: All Comments per Video, No Login
All comments of any Bilibili (B站, 哔哩哔哩) video: up to 100,000 per video with replies, a sentiment score per comment, daily tracking of only new comments. Plus videos from search, channels or Popular with stats and creator profiles. No login. $6.40 per 1,000 comments.
Pricing
from $2.50 / 1,000 videos
Rating
0.0
(0)
Developer
Misha Ershov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
25 days ago
Last modified
Categories
Security
Limited permissionsShare
Bilibili Scraper: All Comments per Video, No Login
Bilibili videos from keyword search, a creator's channel or the Popular feed with their stats (views, likes, coins, favorites, shares, danmaku, comments), comments with replies of a video (20 per page, up to every root comment of a video, no login) and creator profiles. One row per item, with an onlyNew mode that returns only videos and users you have not received in an earlier run. No login, no cookies.
What you can do
- Collect all comments of a video, up to 100,000 per video (
maxCommentsPerVideo), with replies. - Sort them with
commentsOrder: as Bilibili returns them, most liked first or most replied first. - Watch progress and time left in the run status ("N/M comments, ~X min left").
- Get a sentiment (positive, negative, neutral) and a score from -1 to 1 for every comment and reply (
analyzeSentiment). - Compare videos in one table with a summary row per video (
videoSummary). - Scrape several videos in one run (
videoUrls). - Track new comments: each scheduled run returns and bills only the comments posted since the previous one (
onlyNewComments).
Input
| Field | Default | Meaning |
|---|---|---|
mode | search | search videos by keyword, popular feed, videos given BV ids or URLs, users creators by keyword or id, creatorVideos all videos of the given creators |
keywords | [] | search words. Mode search: video search. Mode users: creator search |
searchOrder | totalrank | totalrank, click, pubdate, dm, stow. Mode creatorVideos accepts pubdate, click, stow and falls back to pubdate |
durationFilter | all | all, under10, 10to30, 30to60, over60 (minutes) |
videoUrls | [] | mode videos: BV ids or any URL containing one. Entries without a BV id are skipped and logged |
userIds | [] | modes users and creatorVideos: user ids or space.bilibili.com/<id> URLs |
maxResults | 100 | 1 to 1000, per keyword (search, users) or in total (popular) |
fetchDetails | false | search and popular: open every video page for coins, shares, tags and uploader followers |
includeComments | false | mode videos (or search/popular/creatorVideos with fetchDetails): add up to maxCommentsPerVideo root comments per video, 20 per page, no login. The pinned comment comes first. In search, popular and creatorVideos modes also turn on fetchDetails. |
maxCommentsPerVideo | 20 | with includeComments: root comments per video (1-100000); the pinned comment counts toward the limit. 20 = one page = one request per video |
commentsSort | popular | with includeComments: popular (most liked first) or newest (latest first) |
commentsOrder | api | with includeComments: api (as Bilibili returns them, see commentsSort), likes or replies. The last two first collect all root comments of a video, then output them sorted, with a commentRank place number |
analyzeSentiment | false | with includeComments: adds sentiment and sentimentScore to every comment and reply. See Sentiment |
videoSummary | false | with includeComments: one extra row per video with type videoSummary (counts, likes, top comment, sentiment shares, time span). Not charged |
parallelVideos | 3 | how many videos are collected at the same time (1-10); each video still loads its pages one by one with a pause. 1 = one video after another |
onlyNew | false | skip videos and users from earlier runs with the same mode, keywords, order, length and ids |
onlyNewComments | false | with includeComments: return only comments posted since the previous run with this option, per video. The first run collects as usual; comments are read newest first. See Track new comments |
maxRepliesPerComment | 0 | with includeComments: also fetch up to this many replies (0-500) under each top comment; full reply threads, no login needed. Each reply is a row with type: "reply" and parentCommentId, billed as a comment event (same price as a comment). 0 = off |
proxyConfiguration | Apify datacenter | for search, popular, comments and users. Video pages always use Apify residential proxy |
Mode search needs keywords, mode videos needs videoUrls, mode users needs keywords or userIds, mode creatorVideos needs userIds.
Otherwise the run ends with exit code 1 and a clear status message, nothing is charged.
Example input for all videos of one creator, newest first:
{"mode":"creatorVideos","userIds":["546195"],"maxResults":60}
Output
Every row has a type: video, comment, reply or user. Fields Bilibili does not return are null, never 0.
Search results have no coins and shares: they are null unless fetchDetails is on.
Video row:
{"type": "video", "bvid": "BV1rpWjevEip", "aid": 113006243481679, "url": "https://www.bilibili.com/video/BV1rpWjevEip","title": "【全748集】目前B站最全最细的Python零基础全套教程", "author": "Python官方课程", "authorId": 3546597933714079,"authorUrl": "https://space.bilibili.com/3546597933714079", "authorFollowers": 801387, "category": null,"tags": ["编程语言", "程序员"], "durationSec": 143894, "publishedAt": "2024-08-22T14:59:18Z","views": 20709271, "likes": 570226, "coins": 406862, "favorites": 876897, "shares": 102796, "danmaku": 132790,"comments": 359670, "coverUrl": "http://i2.hdslb.com/bfs/archive/a979056b1a32012cdd00d48fbc3732d253e30620.jpg","source": "video", "keyword": null, "rank": 1, "scrapedAt": "2026-10-13T09:00:00Z"}
Comment row:
{"type": "comment", "bvid": "BV1rpWjevEip", "commentId": 247714016448, "authorName": "爱劳动的noise","authorId": 1242205079, "authorLevel": 4, "text": "...", "likes": 7508, "replies": 1148,"postedAt": "2024-11-21T13:52:41Z", "videoTotalComments": 359670, "pinned": false}
User row:
{"type": "user", "userId": 546195, "name": "老番茄", "url": "https://space.bilibili.com/546195","bio": "新浪微博:_老番茄_", "avatarUrl": "http://i0.hdslb.com/bfs/face/bc5ca101313d4db223c395d64779e76eb3482d60.jpg","level": 6, "followers": 20840932, "videoCount": 681, "likesTotal": 196027733, "verified": true,"verifiedTitle": "2025百大UP主、2025年度商业影响力奖UP主、2022年度联合创作奖UP主", "isLive": null, "keyword": null}
pinned is true for the comment the uploader pinned to the top of the video and false for all others; the pinned comment comes first.
title has Bilibili's highlight tags removed and HTML entities decoded. publishedAt and postedAt are UTC.
rank is the 1-based position in the source list. durationSec is in seconds.
Compare videos
Put several videos in one run and switch on videoSummary (and analyzeSentiment for the sentiment shares):
{"mode":"videos","videoUrls":["BV1rpWjevEip","BV1GJ411x7h7","BV1xx411c7mD"],"includeComments":true,"maxCommentsPerVideo":500,"videoSummary":true,"analyzeSentiment":true}
Each video gets one extra row with type: "videoSummary" after its comments: videoTitle, videoTotalComments,
commentsCollected, repliesCollected, avgLikes, medianLikes, topCommentText, topCommentLikes,
mostRepliedCommentText, mostRepliedCommentReplies, positiveShare, negativeShare, neutralShare,
firstCommentAt, lastCommentAt, collectSeconds. The shares are null when sentiment is off. A video with no
comments still gets its row with commentsCollected: 0. To see all videos side by side, open the dataset in Console and
choose the Video summary view (videoSummary).
Track new comments
Switch on onlyNewComments and run the Actor on a schedule (for example once a day). The first run collects as usual
(up to maxCommentsPerVideo, newest first) and remembers where it stopped for every video. Each next run reads the comments
newest first, stops as soon as it reaches a comment it has already seen, and returns and bills only the new ones.
Replies, sentiment and commentsOrder work as usual on the new comments.
{"mode":"videos","videoUrls":["BV1rpWjevEip","BV1GJ411x7h7","BV1xx411c7mD"],"includeComments":true,"onlyNewComments":true,"maxCommentsPerVideo":500,"videoSummary":true}
- The record is kept per video, under the key
comments-<BV id>in the key-value storebilibili-scraper-stateon your account. It does not depend on the mode or the keywords, so you can change the list of videos and every video keeps its own place. - With
videoSummary, the summary row hasnewSince(time of the newest comment of the previous run,nullon the first run) andnewComments. - If more than
maxCommentsPerVideonew comments appeared since the last run, the newest ones are returned and a warning is logged; raise the limit for busy videos. - If the run stops at your charge limit in the middle of a video, that video's record is not moved, so the unread new comments come in the next run.
- To start over for a video, delete the key
comments-<BV id>in thebilibili-scraper-statestore. - Do not switch on
onlyNewfor comment monitoring: it skips videos you have already received, and so their new comments. RUN_SUMMARYhasonlyNewComments,videosFirstRun,videosWithNewandvideosNoNew.
Export to Excel, CSV or Google Sheets
- Console: open the run, go to the Output or Storage tab and use Export to download the dataset as Excel, CSV, JSON or XML.
- Google Drive: in the Integrations tab of the Actor add "Upload results to GDrive" and pick the file format; see https://docs.apify.com/integrations/drive.
- Google Sheets: connect the Actor through Make or Zapier and use the "Bulk Add Rows" action.
How long does it take
Requests are paced (0.7 to 1.0 s each, to stay clear of bans), measured on Apify:
- Without replies: about 7 to 9 root comments per second. 5,000 comments take roughly 10 minutes.
- Up to 3 replies per comment (
maxRepliesPerComment1-3): almost free in time when Bilibili's comment page already carries those replies (it usually sends the first 2 to 3 "hot" replies of a thread). A comment whose page preview is shorter than what you asked for costs one extra request. - More than 3 replies per comment: about 1 second for every comment that has replies. Example: 200 comments, all with replies, 10 replies each = 200 extra requests at about 0.85 s = about 3 minutes on top of roughly 30 seconds for the comments, so about 3.5 minutes.
- Replies taken from the page are Bilibili's "hot" replies, not the oldest or newest ones; fine for a sample of the thread.
- The number of comments Bilibili shows for a video includes replies. The status therefore reads like "BV1...: 300 comments of at most ~336 (Bilibili's 908 includes replies), up to ~1 min left"; the time left is an upper bound.
Videos are collected 3 at a time (change it with parallelVideos), so one run with 5 videos takes about as long as 2 videos one after another.
Rows of different videos can be interleaved in the dataset; every row carries its bvid, and the order inside one video does not change.
RUN_SUMMARY has parallelVideos and wallSeconds (the whole run), while commentSeconds stays the sum over videos.
Measured on Apify: 5 videos, 200 comments each plus up to 2 replies (1,730 rows) took 206 s one video at a time,
84 s with parallelVideos: 3 (the default) and 60 s with parallelVideos: 5. The price per row is the same, whatever you choose.
The default run timeout is 1 hour. If the estimate does not fit, the log says so; raise Timeout in Run options or lower maxCommentsPerVideo.
RUN_SUMMARY has repliesFromPreview (reply rows taken from the comment page) and replyRequests (separate reply requests).
Sentiment
With analyzeSentiment every comment and reply gets sentimentScore (-1 to 1) and sentiment: positive from 0.4,
negative up to -0.4, neutral in between. Chinese text is scored offline with SnowNLP; English text with a small word list
(positive words minus negative words). Emote codes like [doge] are ignored; a comment with nothing but emotes gets null.
Treat the result as a guide, not as a verdict: SnowNLP was trained on product reviews, so slang and sarcasm are often
misjudged, and the English word list is deliberately simple.
How the run works
Bilibili answers errors with HTTP 200 and a non-zero code (for example -352), or with HTTP 412. Any of these
counts as a failed request and is retried up to 3 times, each on a new proxy session. A keyword that still fails is
logged (keyword X: bilibili code N), counted in RUN_SUMMARY.failed and skipped; the other keywords go on.
If a video page cannot be read after 3 attempts, the row is still returned without details, billed as video,
and counted in detailsFailed. Search stops at maxResults, at the last page or at an empty page; videos are
deduplicated by bvid within a run. Requests are paced (about one per second). RUN_SUMMARY holds bySource
(pages, items and stoppedBy per keyword), pushed by type, failed, detailsFailed, charged per event and
stoppedBy (maxResults, numPages, budget or end).
FAQ
Do I need a Bilibili account? No. No login or cookies are used.
How many comments can I get? 20 root comments per page, up to 100,000 per video (maxCommentsPerVideo), so every root comment of almost any video, sorted by popularity or newest, with no Bilibili login. About 9 comments per second: for thousands of comments raise the run timeout in Run options (5,000 comments take roughly 10 minutes). Replies are fetched separately with maxRepliesPerComment. Bilibili may end the list earlier than the total comment count shows.
Why is fetchDetails slower? Video pages are served to residential IPs only, so each video costs one residential request and its row is billed as video-details.
Pricing: one event per row: video (search or popular, no details), video-details (video page opened), comment, user. Every comment and every reply is one comment event; the default of 20 comments per video means up to 20 comment events per video, so raise maxCommentsPerVideo only if you need more.
Missing something? Open an issue — we add fields on request.
Development
cd partner_actors/dima/bilibili-scraperpython3 -m pytest -q