Douyin 抖音视频 Video Scraper - Metadata & No-Watermark URL
Pricing
from $2.99 / 1,000 videos
Douyin 抖音视频 Video Scraper - Metadata & No-Watermark URL
抖音视频详情 for any public Douyin (抖音) post: description, publish time, length, likes, comments, shares, saves, hashtags, music, cover and the watermark-free play URL. Paste video links, /note/ album links, v.douyin.com share links or bare IDs. No login.
Pricing
from $2.99 / 1,000 videos
Rating
0.0
(0)
Developer
Lantern Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
Douyin 抖音视频 Video Scraper
Read the full public detail (抖音视频详情) of any Douyin (抖音) post: description, publish time, length, likes, comments, shares, saves, hashtags, music, cover image and the watermark-free MP4 play URL - exact numbers, not Douyin's rounded 9.8万. Paste video links, /note/ album links, v.douyin.com share links or bare IDs; no login, no cookies, no account of your own. $2.99 per 1,000 videos, plus $0.005 per run. See Pricing.
Input:
{"videoUrls": ["https://www.douyin.com/video/7683413288402612731","https://v.douyin.com/iJSMnqRm/"]}
Output - one row per video (recordType: "video"), plus one free row per input line and a RUN_SUMMARY. Sample from a real run; nickname partially masked, URLs shortened:
{"recordType": "video","platform": "douyin","dataSource": "guest_web","awemeId": "7683413288402612731","url": "https://www.douyin.com/video/7683413288402612731","postType": "video","desc": "果树补钙用绿陇糖醇钙,移动性强,好吸收!#糖醇钙 #果树种植 #农资肥料 #钙肥","createTime": 1788934062,"publishedAt": "2026-09-09T06:07:42+00:00","durationSec": 38.4,"author": {"nickname": "绿陇***","secUid": "MS4wLjABAAAA…","uid": "1051…","douyinId": "lvlong2018","url": "https://www.douyin.com/user/MS4wLjABAAAA…","verified": true},"diggCount": 41,"commentCount": 2,"shareCount": 3,"collectCount": 6,"playCount": null,"hashtags": ["糖醇钙", "果树种植", "农资肥料", "钙肥"],"musicTitle": "@绿陇生物创作的原声","musicAuthor": "绿陇***","coverUrl": "https://p3-pc-sign.douyinpic.com/…","videoPlayUrl": "https://v3-web.douyinvod.com/…","imageUrls": [],"location": null,"input": "https://www.douyin.com/video/7683413288402612731","videoStatus": "available","accessMode": "direct","collectionStatus": "complete","partial": false,"partialReason": null,"elapsedMs": 1842,"collectedAt": "2026-10-24T05:41:12+00:00"}
Limits:
- Public data only. The Actor reads what Douyin shows a signed-out visitor and never logs in. No comments, no private or login-only posts, and nothing about the author beyond the public display name and IDs on the post.
- No MP4 is downloaded.
videoPlayUrlis the watermark-free stream Douyin's own player uses, handed to you as a link. It is signed and short-lived, so fetch it soon after the run and send adouyin.comreferer. Copying the bytes through Apify storage would bill you for video traffic you may not want. - Every row says how complete it is. A post Douyin would not describe - taken down, private, withheld - is reported as such with the reason, never as a video with zero likes.
- Your limits stop collection and appear in the row: the
maxUpstreamRequestsrequest ceiling, the residential-fallback budget (maxFallbackVideos) and the maximum charge per run (see Pricing).
What it does
- Reads each post's detail the way Douyin's own video page shows it, and writes exactly one row per video - even for a post that could not be read.
- Accepts every link shape Douyin hands out:
/video/<id>,/note/<id>and/slides/<id>,v.douyin.comshare links (followed to the post),?modal_id=<id>links, and bare numeric IDs. - Costs one Douyin request per video. A run of 100 videos is one browser session and 100 requests.
- Deduplicates inside a run: the same post asked for twice is fetched once and charged once, and the second line is reported as a
duplicate. - Handles 图文 (image-album) posts: their pictures come back in
imageUrls, and they carry novideoPlayUrlbecause Douyin serves none. - Marks a row
partialwith a reason when the post was not read: your request limit, your cost limit, or a refusal by Douyin. - Runs without a proxy by default. If Douyin refuses the request for a post, that one post is retried through an Apify residential proxy exiting in China (limited per run, can be turned off). A post Douyin does answer about - gone, private, withheld - is never retried, because no exit changes that answer.
- Stops minting fresh visitor sessions once a run has seen two posts refused and none answered: Douyin withholds from every visitor, not from one session, so a third page load would only buy the same answer. Each post is still asked once, so each keeps its own evidence.
- Writes a
RUN_SUMMARY- last row of the dataset and a key-value record - with the totals, the requests sent against the ceiling in force, and why the run stopped.
What it does not do
- No video files. The play URL is handed over; nothing is downloaded or re-hosted, so you are never billed for video traffic.
- No keyword search. Bring links or IDs. To find videos by keyword first, use the Douyin keyword search Actor.
- No comments - use the Douyin comments Actor. No account profile numbers - use the Douyin profile Actor.
- No play counts. Douyin's web API answers a constant
0for plays whatever the real number, soplayCountisnullrather than a figure the platform never stated. - No private data. Only what Douyin's own video page shows. No email, no phone, no personal name - just the author's public display name, their public IDs and the badge Douyin itself displays.
- No login-only or age-restricted posts, no live streams, no scheduling built in.
Input
| Field | Default | Meaning |
|---|---|---|
videoUrls | - | Video links (https://www.douyin.com/video/7...), album links (/note/7...), share links (https://v.douyin.com/...), links carrying modal_id=..., or bare numeric video IDs. |
maxUpstreamRequests | worked out from your input | Hard ceiling on Douyin requests for the whole run, retries included. Leave empty and the Actor derives one, so a run is never unbounded. |
proxyConfiguration | no proxy | Standard Apify proxy setting for all requests. |
residentialFallback | true | Retry a refused video through a residential proxy in China. |
maxFallbackVideos | 3 | Videos per run that may use that fallback, at most 20. 0 turns it off. |
requestDelaySecs | 1 | Minimum pause between two requests from one visitor session. |
maxIdentityRotations | 6 | Fresh visitor sessions a run may mint after a refusal. |
msTokenWaitSecs | 20 | How long a new visitor page may take to receive its security token. |
Output
Three row kinds in the default dataset, so three different facts can never be mistaken for each other.
recordType | One per | Charged |
|---|---|---|
video | video looked up | only when it carries data |
input_status | input line - what it resolved to (found, duplicate, invalid_url, not_collected) | never |
RUN_SUMMARY | run, as the last row (also in the key-value store) | never |
Fields on a video row:
| Field | Meaning |
|---|---|
awemeId | Douyin's own post ID, as a string - it is past the JavaScript safe integer range. |
url, postType | The post's page, and whether it is a video or an image_album (图文). |
desc | The description exactly as Douyin shows it, hashtags included. Douyin has one description field; there is no separate title. |
createTime, publishedAt | The author's publish time, as Unix epoch seconds and as UTC ISO 8601. |
durationSec | Video length in seconds. null for an album. |
author | nickname, secUid (the permanent MS4w... ID), numeric uid, douyinId (抖音号), profile url, verified. |
diggCount, commentCount, shareCount, collectCount | Likes, comments, shares and saves - exact, not rounded to 万. |
playCount | Always null; see What it does not do. |
hashtags | Hashtags without the leading #, in Douyin's order. |
musicTitle, musicAuthor | The track on the post, and who Douyin credits. |
coverUrl, coverUrls | The cover image, and every cover mirror Douyin served to fail over between. |
videoPlayUrl | The watermark-free MP4 stream. Signed and short-lived; expects a douyin.com referer. |
imageUrls | Every picture of an album post, in page order. Empty for a video. |
location | The place name on the post, when the author attached one. |
input, collectedAt, elapsedMs | Your input line, when the row was collected (UTC, ISO 8601), and time spent on it. |
videoStatus | available, unavailable, deleted, private or unknown. See below. |
accessMode | direct, custom_proxy or residential_fallback. |
collectionStatus, partial, partialReason | How complete the row is, and why not. |
A row never carries an invented value: a field Douyin stated nothing about is null, not 0 and not an empty string. A missing like count and a like count of zero are different facts.
Video status
videoStatus | Meaning |
|---|---|
available | The post was read. The only status that is charged. |
unavailable | Douyin answered but would not describe the post - withdrawn, under review, or withheld. Not "an empty video". |
deleted, private | Douyin said so explicitly. Whatever metadata it still returned is kept, flagged. |
unknown | The request was refused, or the run stopped before sending it. |
What partial means
partial is true whenever collectionStatus is not complete, and partialReason says why:
| Reason | Meaning |
|---|---|
cap:maxUpstreamRequests=N | The run's request ceiling stopped it - yours, or the one derived from your input. RUN_SUMMARY.upstreamCapSource says which. |
cap:maxTotalChargeUsd | Your Maximum cost per run was reached; rows past it are not stored. |
cap:maxInputs=N | More input lines than one run accepts; the rest are listed, not collected. |
blocked:<accessMode>:... | Douyin refused the request on that exit, after fresh visitor sessions. The text keeps the classification and Douyin's own status code. |
detail:filtered:<Douyin's wording> | Douyin answered about the post but would not describe it, in its own words. |
detail:is_delete, detail:private_status | Douyin says the post is deleted or private. |
fallback_cap:maxFallbackVideos=N | The post was refused and the run had used up its residential retries. |
input:no_aweme_id | No Douyin post ID in that input line. |
input:duplicate_in_run | The same post was already collected earlier in this run. |
collectionStatus is complete when the post was read, blocked when Douyin refused the request, and not_collected when nothing could be read or nothing was attempted.
Pricing
Pay per event: $2.99 per 1,000 videos, plus $0.005 for each run. Apify platform usage, including the browser session and the residential fallback, is included; these two events are the whole price.
| Event | Price | Charged for |
|---|---|---|
result | $0.00299 ($2.99 per 1,000) | Each row that carries a video. |
run-start | $0.005, once per run | The signed-out browser session every run opens before it reads any post. |
A row that only reports a failure - an input line with no post ID, a duplicate, a post Douyin would not describe, a post the run never reached - is written free. A run that reads no post at all still pays the $0.005 session.
The session is a flat fee per run, not per video, so a batch costs less per video than many small runs: 10 videos cost $0.035 ($0.0035 each), 100 videos cost $0.304 ($0.0030 each), 1,000 videos cost $2.995.
To cap a run, set Maximum cost per run in the run options. When the cap is reached the Actor stores no further rows, stops before the next video, marks what it cut short partial with cap:maxTotalChargeUsd, and records it in RUN_SUMMARY.
Resources
- Runs with 1 GB memory by default; 1-8 GB can be chosen in the run options. A visitor session is minted in a real browser, which needs 1 GB.
- A run opens a visitor session first (about 20-40 seconds), then takes a couple of seconds per video.
Notes
- Respect Douyin's terms and local law, and only collect what you need. Nicknames and descriptions are personal data in many jurisdictions.
- Douyin changes its web client often.
RUN_SUMMARYreports request outcomes per endpoint, so a change shows up there first.