🎵 Douyin User Post Videos | An account's posts, with the counters Douyin actually gives Give it a sec_uid, profile URL or short_id and get every post as a row: description, likes, comments, shares, collects, duration, music, publish time and link — plus a per-account summary with median likes, the…
The run can no longer be killed by the key-value store. Under
LIMITED_PERMISSIONS — how Apify's automated QA and every API-triggered run
starts an Actor — opening the store is refused with HTTP 403
(KeyValueStoreCollectionClient.getOrCreate, path /v2/key-value-stores).
That call sat in a || fallback chain and was never inside a try/catch of
ours, so the throw ended the run with exit code 91 and a reported FAILED run
with zero items. Every store open now goes through a wrapper that returns a
no-op store instead of throwing, so the free-run counter and the run SUMMARY
degrade and the actual work proceeds.
The gate store's name-to-id lookup no longer depends on the store still being
on the first page. There is no GET-by-name endpoint, so the lookup pages
through /v2/key-value-stores; it used a fixed limit=50, which silently
stopped containing gate stores once the account passed 50 of them — and the
account creates a new default store on every run, so that list grows on its
own. The lookup now pages (100 per page, up to 20 pages).
Medians on an even-sized sample returned the upper-middle element, not the
median. arr[Math.floor(arr.length / 2)] yields the larger of the two middle
values, which biases the number upward — the exact bias a median exists to
remove. It now averages the two middle values.
[0.3] - 2026-10-09
Changed
README: added three sections before Quick start - what you can use it for, who it fits, and who it does not fit. The last section now names the Actor's real limits (what it cannot reach, which field is unavailable, which reading of a metric is wrong), so a buyer can tell whether it is the wrong tool before paying.
[0.2] - 2026-10-08
KV writes and status messages can no longer hang the run. Under
LIMITED_PERMISSIONS these calls do not merely fail — they can return a
promise that never resolves. Measured on a live run of a sibling Actor:
results were fetched successfully, then the following setValue never
returned and the run sat for 49 minutes before being aborted with an empty
dataset and a paid bill, and not one error in the log. try/catch cannot
help there — it catches a rejection, not a promise that never settles. Every
bookkeeping write now races a 15s timeout and reports the failure as
non-fatal, so a stuck store costs one summary field instead of the whole run.
0.1 (2026-10-05)
Initial release. One dataset row per Douyin post: description with a caption-less flag, digg/comment/share/collect counts, the For-You recommend count, duration converted from milliseconds, video-vs-image detection, ad-post flag, music title, publish time and a working link, with the source account attached.
The summary reports, per account: posts collected, the account's own post total and coverage when the lookup provides them, median and total likes, median comments and recommends, video/image split, ad-post count, posts-without-caption count, the five most-liked posts, and a viewsNote.
Input accepts sec_uids, douyin.com/user/<sec_uid> profile URLs and numeric short_ids (resolved through the provider's profile lookup first, with the resolved nickname carried onto every row), up to 20 accounts and 200 posts each; newest or popular order.
Measured quirks handled: all engagement lives in statistics (never at the top level) and statistics.play_count is always 0 — Douyin does not expose views, so viewCount is null with viewsAvailable: false rather than a false zero; has_more is 0/1; paging uses the millisecond max_cursor and stops when it does not advance; collect_stat sits outside statistics; and the short_id profile lookup returns only a minimal 7-field profile (no follower count, signature or post total), which is reported as null with profileFieldsAvailable naming what the lookup actually carried.
Free tier: 5 runs/day (counter persisted in a cross-run named KV store).