# Changelog of Bilibili Comments & Danmaku Scraper API, No Login – B站 哔哩哔哩 (`deadc0dex/bilibili-scraper`) Actor

- **URL**: https://apify.com/deadc0dex/bilibili-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/deadc0dex/bilibili-scraper.md

## Changelog

### 2.1.0 – 2026-10-16 (search depth past the 1,000-result cap; same prices, events, inputs, listing and default output)

- **Search past Bilibili's ~1,000 results per query:** when a query's 20 pages are exhausted and `maxItemsPerInput`/`maxItems` ask for more (up to 5,000 per keyword), the Actor sweeps publish-date windows newest first inside `dateFrom`/`dateTo` (a window that is itself capped is split down to 1 day before its pages are read; sparse windows widen up to 1 year). Same order and filters; duplicates are skipped free; the summary `notes` say how many windows/requests the sweep used. Locally 原神 1,300 videos: 1,300 distinct in 30 requests, 21 s (2.0.3 stopped at ~964–1,021 distinct).
- Capabilities `limits.searchDepth` documents the sweep.
- Docs: the 2.0.2–2.0.3 fix line above is now dated and shipped in a build (it was only in the source).

### 2.0.0 – 2026-10-15 (research workflow, trust fields, snapshots, insights; same prices, events and default output; builds 2.0.1–2.0.5, live 2.0.3 `GaETkx5obJTZbDFjO`)

- **New operation `keywordComments`** (aliases `keyword_comments`, `comment_research`): keyword → top `maxVideos` videos (sortBy, dateFrom/dateTo, minViews, durationFilter, expandQuery) → `commentsPerItem` comments (`commentSort` hot|newest) → replies (`replyDepth` 0|1, `repliesPerComment`) → free insights row per keyword. `matchTerms` keeps matching top-level comments/danmaku (filters after fetching). Without keywords but with `urls` it runs `comments` on them (routing bug in the unreleased v2 draft fixed: it ran `videoDetails`).
- **Trust fields on every row:** `isPartial`, `unavailableFields[]`, `collectionWarnings[]`; summary adds `requested`, `perInput[]` (returned per input, status), `pagesFetched`, `isPartial`.
- **Computed video metrics:** `likesPer1kViews`, `commentsPer1kViews`, `engagementRate`, `danmakuPerMinute`, `detailLevel` (formulas in `capabilities.computedMetrics`).
- **Snapshot mode:** `deltaKey` + `trackMetrics: true` → `viewsDelta`, `likesDelta`, `commentsDelta`, `danmakuDelta`, `favoritesDelta`, `coinsDelta`, `sharesDelta`, `engagementRateDelta` (creators: `followersDelta`, `likesTotalDelta`, `videosCountDelta`), `snapshotAt`, `previousSnapshotAt`, `hoursSincePrevious`.
- **Free insights row** (`include: ["insights"]`, default on for keywordComments): top terms (CJK bigrams merged into trigrams when the trigram explains every use, e.g. 评论区 instead of 论区), emotes, matchTerms counts, most-liked comments, top videos, heuristic lexicon sentiment (no LLM), danmaku peak minute and a **per-video danmaku profile** (`timelinePerMinute`, `peakMinute`, `poolFetched` vs `returned`, `uniqueSenders` with include author).
- **Billing map ready for a later price change:** each row type maps to a chain of event names (`video-basic`/`video-enriched` → `result`); the first event that exists in the live pricing is charged, so today every video row is still `result` ($0.005). No price or event changed.
- Fix (2.0.2–2.0.3, 2026-10-15): `keywordComments` with only `urls` now keeps its own defaults when it falls back to comments (`commentsPerItem` as the per-video limit, default 10; insights row on; replies on with 2 per comment). It returned 20 comments and no insights row in 2.0.1.
- New input fields: `maxVideos`, `commentsPerItem`, `replyDepth`, `repliesPerComment`, `commentSort`, `insights`, `trackMetrics`, `matchTerms`. All v1.x inputs and the compact default output keep working (new fields are only added).

### 1.4.0 – 2026-10-13 (agent-native polish; same prices, events, inputs and default output)

- **Copy-paste example input for every operation**: README "For AI agents" table and `exampleInput` on each operation of the free `capabilities` row (same list, unit-tested against the input schema).
- Accurate texts: `include: details` costs 1 batched request per 50 videos in compact/lean mode (was documented as 1 per video); the 512 MB hint for big full-mode runs states the measured 1.7–2.9× speed-up; README speed line uses platform numbers.
- Store listing (title "Bilibili Comments & Danmaku Scraper API, No Login – B站 哔哩哔哩", description listing the data types agents search for: video comments, replies, danmaku, search videos, video details, user profiles, creator videos, followings, popular & hot videos, weekly must-watch, precious, ranking, hot search, live rooms). Two listing loops; the Store search index refreshes after a build (docs-only builds 1.4.1–1.4.3, 1.4.5). A revert to the v1.3 loop-2 listing (build 1.4.4) measured worse than the loop-2 listing under the refreshed index, so the loop-2 listing was restored.

### 1.3.0 – 2026-10-13 (live build 1.3.4 `iMHCt1JnAiW8EpLfH`; limits removed where public, faster heavy runs; same prices and events; v1.2 inputs and default output unchanged)

- **New operation `followings`** (关注列表): the accounts a creator follows, from Bilibili's public app endpoint (the web endpoint needs a login). User rows billed as `profile`, with new keys `followingOf` and `followedAt`. Bilibili shows logged-out visitors the newest 250 (5 pages × 50); creators who hide the list get a NO_RESULTS row that says so.
- **Ranking fallback rows complete:** when the web ranking is risk-controlled, coins, shares, description, width, height and partsCount are filled from the public batch video-info endpoint (2 requests per 100 rows); the summary note names all six fields and how many rows were filled.
- **`trend.isCommercial` works** (was always null): the hotword list (same keywords, same order) is read in parallel and its commercial flag merged.
- **`include: details` in compact/lean mode is batched:** 1 request per 50 videos instead of one view call per video (field-identical on a 50-video check). Heavy compact run (300 videos + details/owner/topComments) 106 s → 69 s, −35 % CU, side by side (37.5 s in the release regression).
- **Full mode writes its own dataset batches** (serialised once, uncompressed, ≤ 8 MB per request, SDK fallback): −12 % to −48 % time/CU on the 300-row full case in two side-by-side runs (1.3.1: 212 vs 242 s; 1.3.4: 110 vs 210 s); heavy runs vary ±40 % run to run. Most full-mode bytes are Bilibili's collection list (`ugc_season`), which is part of the raw record; the summary now suggests 512 MB for big full runs (measured 72 s vs 105–212 s at 256 MB; CU 0.0100 vs 0.0077–0.0147).
- Listing/README: one README section per operation named with the words agents search for (video comments, danmaku, search videos, video details, user profile, creator videos, followings, popular videos, weekly/precious, ranking, hot search, live rooms); input field titles name the operations they feed.
- Summary `timingsMs.cpu` (process CPU ms). Capabilities `notAvailable` lists the login-only data re-checked on 2026-10-13 (subtitles, fan lists, commenter IP region, danmaku history).

### 1.2.0 – 2026-10-13 (token-efficient output, verified data, weekly/ranking fixes; same prices and events; all v1.1 inputs and default output unchanged; builds 1.2.1–1.2.6, live 1.2.6 `ER1Q5MN9OBfIMLlA2`)

- **Heavy full-mode runs (1.2.6):** `outputMode: "full"` writes rows in batches of 25 (was 200) and runs at most 8 requests in parallel (was 16); 300 full rows with details+owner+topComments 187 s → 168 s, −10 % CU, −19 % peak memory vs 1.2.5 in a side-by-side run.
- **New `outputMode: "lean"`** (opt-in): `type` + `id` + curated fields per row kind, null/empty/false omitted, envelope (operation, input, queryUsed, fetchedAt) once in the summary row, `url` derivable from `id` (patterns in the summary and capabilities), text cut to `maxTextChars` (default 300, `truncated: true`), dates `YYYY-MM-DDTHH:MMZ` UTC. Lean also skips enrichment requests its fields do not need (e.g. tags). Measured: −64 to −84 % tokens per row (median −77 %); table −71 to −90 % (median −83 %). **`leanFormat: "table"`** adds one TSV block per row kind (header once) to the summary row and key-value record `LEAN_TABLE`; rows are still pushed and billed the same. New input `maxTextChars` (any mode).
- **Weekly (每周必看) fixed:** the web endpoint answers -352 to most guest IPs; the Actor now reads the app weekly list (order, recommend reason, `config.media_id`) and the issue's public media list (full stats), with the web endpoint as fallback.
- **Ranking fixed:** when the web ranking answers -352 the app ranking (separate risk control) is used at once instead of ~20 s of retries that ended FAILED. `rankingCategory` also accepts names (gaming, music, tech, …).
- **New operation `precious`** (入站必刷, ~100 all-time must-watch videos, full stats).
- **Competitor parity:** `deltaKey` monitoring mode (only rows not returned before; skipped rows free), `allParts` for danmaku of multi-part videos, `danmakuSource: "segments"` (XML pool + 6-minute protobuf segments, deduplicated: e.g. 2,943 vs 1,200 rows on one part), `userVideos` with `sortBy: "views"`.
- **Data fixes (field audit against independent sources):** `categoryName` was null on videoDetails/userVideos rows (Bilibili stopped sending tname) → v1 zone name table; `categoryId` is now the v1 zone id on every operation (videoDetails used tid_v2); creator uploads stopped at 100 with a NOT_FOUND row (page size 100 + cursor = -400) → page size 50 after the first page; `articlesCount` was always 0 (card) → creator navnum (only requested when the field is wanted); BGM pseudo-tags ("发现《…》") and duplicate tags removed; width/height swapped for rotated (portrait) uploads; `isOriginal` documented (copyright 3 = not declared → null).
- **Faster start:** source bundled into one file with esbuild at build time (in-process startup ~0.45–1.1 s → ~0.3 s); up to 16 requests in parallel (adaptive backoff unchanged; tag-heavy runs ~30 % faster).
- **Dry run:** `estimatedRows`, `estimatedSeconds`, realistic caps for weekly/precious/ranking/danmaku. Summary `nextSteps` suggests lean mode on big compact runs.

### 1.1.0 – 2026-10-13 (efficiency + discoverability; same inputs, outputs and prices; builds 1.1.1–1.1.7, live 1.1.7 `zKvLPo3k6Is1d0Gg8`)

- **Faster:** default calls ~2–4 s (were 3–8 s); 200 search results 43 s → ~4 s; 50 trending videos 27 s → ~4.5 s; 200 comments 24 s → ~5 s; 200 danmaku 21 s → ~2 s.
- **Batched output:** rows are written and charged in batches (`Actor.pushData(rows, event)`), in the background while the next page loads, instead of two API calls per row. Same per-row prices and `chargedEventCounts`.
- **Scope efficiency:** `fields[]` now also limits requests. Tags, ownerFollowers, topComments and view-only stats are fetched only when their field is requested (`popular` 50 with `fields:["title","views"]` = 1 request instead of 51). Search rows reuse their own tags with `include: ["details"]`.
- **Fewer requests per page:** search up to 50 results per request, popular 50, creator uploads 100, comments 30 (were 20/20/20/20); danmaku resolves the part id with the small `pagelist` call instead of the full video view; one shared WBI key fetch.
- **No guest-session setup on the default path:** search, video view, popular and tags go cookie-less first (the guest cookie session is now the fallback), saving 4 requests at start.
- **Parallel requests:** up to 8 in flight (was 4, serialised by a 250 ms global delay). `requestDelayMs` default 250 → 0; the Actor raises the delay to 250 ms and halves parallelism automatically after the first rate-limit / risk-control answer.
- **HTTP:** Node's built-in fetch (keep-alive, gzip/br) for direct requests; got-scraping is only loaded when a proxy is used. The Apify proxy is set up lazily (only after a block).
- **Lighter runtime:** `apify/actor-node:22-slim` base, `npm ci`, node started directly (no npm wrapper), V8 heap capped at 75 % of run memory. Peak memory ~70 MB → ~35–45 MB. Default run memory 512 → 256 MB (`minMemoryMbytes` 128).
- **Safety:** run deadline stops new work 20 s before the run timeout (partial rows + summary instead of TIMED-OUT). Summary row adds `timingsMs` (startup, first row, total).
- **include comments:** each video's first comment page is prefetched in parallel (rows still come video by video), and one write batch can mix videos and comments: 40 trending videos + 5 comments each ~6 s locally (was one request after another).
- **Filters before enrichment:** `minViews` / `minLikes` / dates / dedupe are checked on list data before any per-video request; rows that cannot be afforded under `maxItems` / `maxCostUsd` are not enriched.
- **Fixes:** summary `billedEvents` / `chargedUsd` now read the SDK's charge counter (the batched charge result could be counted twice on the platform; the platform's `chargedEventCounts` was always right). Ranking fallback is now WBI-signed cookie-less (the guest-session call gets -352). Hard watchdog on every HTTP request (one platform run stalled with requests in flight). topComments fetch uses a 5-comment page.
- **Store text:** title, description, SEO title/description and README headings now lead with "Bilibili comments", "Bilibili danmaku" and "videos" (the phrases agents search).

### 1.0.0 – 2026-10-12 (agent-native rebuild; final build 1.0.6, ID R3sGPtSeKhY0rwgDf)

- **14 operations in one Actor** (`operation`, default `auto`): search, videoDetails, comments, replies, danmaku, related, userProfile, userVideos, searchUsers, popular, weekly, ranking, hotSearch, liveRoom, plus free `capabilities`. New inputs `users[]` and `ids[]` (auto-routed by shape: `BV…:commentId`, `mid:…`, space/live links).
- **Agent control:** `include[]` (tags, details, owner, parts, topComments, comments, replies, danmaku, author, liveRoom), `fields[]` projection, `outputMode` compact|full (full adds `raw`), filters before billing (`dateFrom`/`dateTo` incl. relative `7d`, `minViews`, `minLikes`, `sortBy`, `durationFilter`, `dedupe`), limits (`maxItemsPerInput`, `maxItems` = run total, `maxCostUsd`), `dryRun` (free plan row with estimated cost).
- **English→Chinese query expansion** (`expandQuery`, default on): shared curated dictionary `work/actors/_shared/query_expansion/en_zh.json` (~940 entries), copied to `src/data/en_zh.json` (`npm run sync-dict`); keywords ≤2 chars stay literal; Chinese searched first, original fills the shortfall; rows show `queryUsed`.
- **Output contract:** every row starts `type, operation, input, queryUsed, id, url, fetchedAt, rank`; kinds video / comment / danmaku / user / trend / liveRoom; free `error` rows (`errorCode`, `errorMessage`, `suggestedFix`; new codes NOT_SUPPORTED, INTERNAL_ERROR), free `summary` row last (counts, billedEvents, chargedUsd, stopReason, warnings, nextSteps), `plan`, `capabilities`. Output field `mode` → `operation`, `scrapedAt` → `fetchedAt` (breaking for v0.x output consumers); `bvid` now canonical (derived from aid).
- **Pricing:** new PPE events `comment` $0.001, `danmaku` $0.0001, `profile` $0.003 (creator or live room), `trend` $0.001; `result` $0.005/video and `apify-actor-start` unchanged. Submitted 2026-10-12 22:58 IST via API; no paying users, so effective immediately (no 14-day notice needed).
- **Endpoints:** cookie-less WBI comments (`/x/v2/reply/wbi/main`, 20/page, paginated – guest cookies cap comments at 3), replies (`/x/v2/reply/reply`), danmaku XML (`/x/v1/dm/list.so`), related, user card, medialist uploads (space arc search is 412/-352 for guests), user search, hot search (`search/square`, fallback `hotword`), live rooms; weekly now WBI-signed (unsigned gets -352); offline BV↔AV conversion.
- Input schema rewritten (28 fields, 20 most important first, every enum value explained, ≤500 chars, prefill `keywords: ["原神"]`), dataset schema with all kinds (no required keys, nullable types) + views per kind, output schema `results` + `runSummary`. Store title/description/SEO rewritten; README "For AI agents" section.
- Backward compatible inputs: `mode` (wins over the injected `operation: auto` default), `searchKeywords`, `videoUrls`, `searchOrder`, `searchDuration`, `fetchDetails`, `includeComments`, `includeTags`, `maxCommentsPerVideo`, `includeCommentAuthor`, legacy per-keyword `maxItems`.

### 0.3.0 – 2026-10-12 (agent optimisation; build 0.3.2)

- Every input optional (`mode` auto – Bilibili: added `auto`, no longer required; explicit modes still work); misplaced inputs auto-corrected (site URL in `keywords` → fetched, plain word in `urls` → searched); explicit mode with missing input falls back to the given input.
- Out-of-range numbers clamped instead of rejected (schema max/min removed; ranges in descriptions) – agents don't see schema min/max.
- New `type: "error"` dataset rows with `errorCode` / `errorMessage` / `suggestedFix` (never billed); input, not-found and no-result problems now end SUCCEEDED with these rows; status message lists codes + first fix; RUN_SUMMARY has `errorRows`, `notes`.
- Dataset schema: error fields, `type` enum incl. `error`, Errors view; output schema descriptions updated.
- Input field descriptions rewritten (enum values explained inline because MCP drops enumTitles; formats and examples); flagship-only prefill.
- Store description/SEO description rewritten (input → output first; correct prices); exampleRunInput set; default run memory 512 MB.
- README: "For AI agents" section (MCP tool name, task → input table, cost, runtime, error codes); fixed stale `affectionate_greengage` username in API/MCP examples.
- Fix: ranking mode – Bilibili now returns -352 to WBI-signed guest calls on `/x/web-interface/ranking/v2`; plain cookie-less request with rank-page referer tried first.
- PPE event names and prices unchanged.

### 0.2.0 – 2026-10-12 (agent-ready release, builds 0.2.1–0.2.4)

- **Inputs renamed to arrays agents use:** `keywords[]` (was `searchKeywords`) and `urls[]` (was `videoUrls`); old names still accepted as aliases.
- `mode` is required with **no default** (MCP marks it REQUIRED); prefill examples for mode, keywords, urls, maxItems.
- Default `maxItems` 50 → **10**; in search mode it now applies **per keyword**.
- Output: every item has the same 36 keys in every mode (null / \[] when not available); dataset schema now has title, description and example per field and validates the real output.
- Added `.actor/output_schema.json` (videos dataset + RUN_SUMMARY record), required for Store publishing and shown to agents.
- Speed: videos enriched 4 at a time with a race-safe rate limiter; optional session steps (bili_ticket, buvid activation) run in parallel with 8 s timeouts; request timeout 30 → 15 s; requests go direct first and switch to Apify Proxy on the first block (custom proxy / proxy group = always proxy). Default 10-video runs went from 15–58 s to ~5–9 s on the platform.
- Status messages: progress during the run and a final "Finished: N videos scraped (mode). K input(s) skipped (not billed)"; invalid input fails fast with an example in the message.
- `videoDetails` `rank` = position in the `urls` input.
- Description / title rewritten agent-first (outputs first, ≤300 chars); README rewritten (quick start table, input/output JSON, pricing, limits, FAQ).
- Actor default run memory 4096 → 512 MB (`defaultMemoryMbytes` + Actor defaultRunOptions).
- PPE events unchanged: `actor-start` (charged only if configured; Apify's synthetic `apify-actor-start` also works) + `result` per video.

### 0.1.0 – 2026-10-12

- First release.
- Modes: keyword video search, video details (URL / BV / av / b23.tv), popular/trending (热门), weekly must-watch (每周必看), category Top-100 ranking (排行榜, 2025+ category ids).
- Optional top public comments (guest limit ≈3 per video), commenter names off by default.
- WBI signing (w_rid/wts), guest cookies (buvid3/buvid4/b_nut/\_uuid), buvid activation and bili_ticket to avoid search captchas; fallback to combined search for page 1.
- Retries with exponential backoff and session/proxy rotation on -352/-412/v_voucher; request throttling.
- Pay-per-event charging: `actor-start` + `result` per video, stops at the run's max charge.
- Dataset schema with Videos / Full details / Top comments views.
