Douyin Live Recorder - Real-Time Chat, Gifts & MP4 Capture
Pricing
from $0.85 / 1,000 recording seconds
Douyin Live Recorder - Real-Time Chat, Gifts & MP4 Capture
Extract real-time chats, gifts, likes, joins, follows, and viewer counts from Douyin (抖音) live broadcasts. Save the stream as MP4 segments. Polymorphic JSON dataset, one row per event. SD to Full HD recording. Free tier included.
Pricing
from $0.85 / 1,000 recording seconds
Rating
0.0
(0)
Developer
Zen Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Douyin Live Recorder | Real-time Chat, Gift & Viewer Stream + MP4 Capture (2026)
15+ event types streamed in real time, optional MP4 capture in SD–Full HD — chats, gifts, likes, joins, follows, viewer counts, room rankings, and stream control signals. One row per event. The most complete Douyin (抖音) live recorder on Apify.

| Zen Studio China Suite • Profiles, posts, transcripts, and live broadcasts from 抖音 — plus search from 小红书 | |||
|
46 author fields + post lists |
Full video metadata by URL |
Subtitles + ASR + translation |
500 Xiaohongshu notes / 30s |
Copy to your AI assistant
zen-studio/douyin-live-recorder on Apify. Streams real-time chat/gift/like/join/viewer-count events from Douyin (抖音) live broadcasts as type-discriminated rows, with optional MP4 recording. Call ApifyClient("TOKEN").actor("zen-studio/douyin-live-recorder").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. liveUrl accepts a live.douyin.com URL, share link, profile URL, or "auto". Full spec: GET https://api.apify.com/v2/acts/zen-studio~douyin-live-recorder/builds/default (Bearer TOKEN) → inputSchema, actorDefinition.storages.dataset, readme. Token: https://console.apify.com/account/integrations
Key Features
- 15+ event types in real time — chat, gift, like, member join, follow, share, fansclub, emoji, viewer count, room stats, room ranking, room messages, stream adaptation, control signals
- Optional MP4 recording — SD1, SD2, HD1, or Full HD segments uploaded to the key-value store every 1–60 minutes
- Recording-only mode — set
captureEvents: falseto skip the event stream entirely and just save the MP4. You only pay for recording time - One row per event — polymorphic dataset,
typeis the discriminator. Filter chats withtype = "chat", gifts withtype = "gift", etc. - Pick the events you want —
excludeEventslets you skip event types upfront (droplikeif you only need chats and gifts, for example). Wire-noise types are filtered internally - Six input formats — paste a
live.douyin.comURL, app share link, profile URL, UserSecID, numeric user id, orautofor a demo room - Reconnect-safe — capped exponential backoff; transient WS drops are recovered transparently and reflected in the summary's
reconnect_count - Free tier — 5 lifetime runs, 5 minutes per run, recording disabled. No credit card required
How to Record Douyin Live Broadcasts
Basic — pick a currently-live demo room
{"liveUrl": "auto","runTime": 5}
Record a specific broadcast
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 60}
Save the stream as MP4
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 30,"recordVideo": true,"videoQuality": "HD1","uploadEvery": 5}
Resolve a broadcaster by profile URL
{"liveUrl": "https://www.douyin.com/user/MS4wLjABAAAAY4cTwy_eXrFLF9JiUjt4QHb3-6c2vKE-bI0Xy_T2WCw","runTime": 60}
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
liveUrl | string | "auto" | A Douyin live broadcast: live.douyin.com URL, bare numeric web id, v.douyin.com share link, profile URL, UserSecID, or numeric user id. Use auto for a demo room. |
runTime | integer | 0 | Minutes to stay connected. 0 = until the broadcaster ends the stream. Range 0–240. |
captureEvents | boolean | true | When off, the actor skips the chat / gift / like event stream entirely and only saves the MP4. Requires recordVideo: true. |
excludeEvents | array | [] | Event types to drop from the dataset. Wire-noise types (system, stream_adaptation, connection_state) are filtered internally and never appear regardless of this setting. |
recordVideo | boolean | false | When on, the stream is recorded as MP4 segments and uploaded to the run's key-value store. |
videoQuality | enum | "HD1" | Recording quality: SD1, SD2, HD1, or FULL_HD1. Ignored when recordVideo is off. |
uploadEvery | integer | 5 | Minutes per MP4 segment before rotation. Range 1–60. Set to 60 (or match runTime) for one consolidated file. Ignored when recordVideo is off. |
What Data Can You Extract from Douyin Live Broadcasts?
Every run produces a polymorphic dataset. The first row is room_info, the last row is summary, and everything in between is one row per live event.
Per-event row types
chat— user nickname, fans-club name + level, pay-grade level, gender, full chat contentgift— gift name, diamond count, combo count, sender + recipient nicknames, total / repeat countslike— sender, click count, room totalmember— viewer who just joined, member count, enter typesocial— follow / share actions, follow countviewer_count— current viewers, total users, popularity, anchor-side breakdownfansclub— fansclub event type and contentemoji_chat— emoji id and default textroom_stats— display labels (short / middle / long) and valueroom_rank— top contributors with rank positionroom_message— system top messages with biz scenestream_adaptation— resolution / aspect-ratio changes during the streamcontrol— broadcaster status changes (status3= stream ended)
Output Example
[{"type": "room_info","room_id": "7644153789288680238","web_rid": "457647640330","broadcaster": { "nickname": "林悦" },"title": "我是林悦,音乐的悦","user_count_text": "206","raw_url": "https://live.douyin.com/457647640330"},{"type": "chat","msg_id": "7644159790989972516","room_id": "7644153789288680238","web_rid": "457647640330","user": {"user_id": "4215971040468057","short_id": "33364754953","sec_uid": "MS4wLjABAAAAJ7L2GblVdXfdUjKx8g76iSv25rT3_3eiro_DxOXcFFms54WHBidCTpLgAR0HYFJ-","display_id": "12D798","nickname": "你若成风","gender": 1,"fans_club_name": "悦悦有","fans_club_level": 13,"pay_grade_level": 32},"content": "我好像认识你!"},{"type": "gift","msg_id": "7644159811234567890","room_id": "7644153789288680238","web_rid": "457647640330","user": { "nickname": "热心观众", "pay_grade_level": 18 },"gift_id": "12345","gift_name": "小心心","gift_diamond_count": 1,"gift_describe": "送给主播一颗小心心","combo_count": 5,"repeat_count": 5,"total_count": 5,"send_type": 1},{"type": "like","user": { "nickname": "粉丝-A" },"count": 3,"total": 12847},{"type": "member","user": { "nickname": "新观众" },"member_count": 2225,"enter_type": 1,"action": 1},{"type": "viewer_count","current_viewers": 2225,"total_users": 48172,"popularity": 9831,"current_viewers_text": "2,225","total_users_text": "48,172"},{"type": "room_stats","display_short": "人气","display_middle": "在线人气 2225","display_long": "当前在线人气 2225","display_value": 2225},{"type": "room_rank","ranks": [{ "rank": 1, "user": { "nickname": "榜一大哥" }, "score_text": "12.4w" },{ "rank": 2, "user": { "nickname": "土豪二" }, "score_text": "8.1w" },{ "rank": 3, "user": { "nickname": "粉丝三" }, "score_text": "5.6w" }]},{"type": "summary","room_id": "7644153789288680238","web_rid": "457647640330","capture_events": true,"duration_seconds": 3600.0,"produced_output": true,"connection_opened": true,"reconnect_count": 0,"total_events": 28828,"event_counts": {"chat": 8420,"like": 11230,"member": 7104,"gift": 982,"viewer_count": 612,"room_stats": 480},"recording_segments": 12,"recording_total_bytes": 1283456789,"recording_total_duration_s": 3597.4,"recording_stop_reason": "deadline_reached","reason_for_exit": "runtime_cap","record_video_requested": true,"record_video_effective": true,"video_quality": "HD1"}]
Recording manifest (run OUTPUT)
The run's OUTPUT manifest is the canonical way to find the recordings. It always has the shape below — recordings is an empty array on runs that didn't capture any video:
{"results": "https://api.apify.com/v2/datasets/.../items","recordings": [{"key": "recording_376034101029_0001.mp4","seq": 1,"started_at_ms": 1779796533135,"ended_at_ms": 1779796833135,"duration_s": 300.0,"bytes": 104857600,"quality": "HD1","kv_url": "https://api.apify.com/v2/key-value-stores/.../records/recording_376034101029_0001.mp4"}]}
Did the run succeed? (produced_output and reason_for_exit)
The summary row carries two fields that make it easy to filter for "this run delivered value":
produced_output—trueiff at least one live event arrived OR at least one MP4 segment was uploaded. Use this as the canonical success filter across all three modes (events-only, events + recording, recording-only).connection_opened— whether the live connection opened. Alwaysfalsein recording-only mode by design. Use this when you specifically need to know about the event-stream side.
The reason_for_exit enum tells you why the run ended:
| Value | Meaning |
|---|---|
stream_ended | The broadcaster ended the stream (a control event with status: 3 was received). |
runtime_cap | The run hit your requested runTime and exited cleanly. |
charge_limit_reached | A pay-per-event billing cap was reached. |
recorder_failed | The recorder gave up — repeated stream-URL fetches, ffmpeg failures, or KV upload failures. The MP4 segments that did upload are still in the key-value store. |
disconnect_unrecoverable | The live connection failed to reconnect after multiple attempts with zero events received. |
transport_closed | The live connection closed for an unattributed reason. |
Advanced Usage
Record until the broadcaster ends the stream
Set runTime: 0 and the actor stays connected until the broadcast ends. Apify's hard timeout of 4 hours still applies.
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 0}
Recording-only mode (skip the event stream)
Save the broadcast as MP4 without paying for the event firehose. Useful when you only need video for later review or transcription. The dataset gets room_info + summary and nothing else; the run's OUTPUT manifest lists every recorded segment.
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 60,"captureEvents": false,"recordVideo": true,"videoQuality": "HD1"}
Free tier doesn't allow recording-only — recording is disabled on the free preview, so the run would do nothing.
High-bitrate archival capture
Pick the highest quality and short segments for granular replay.
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 120,"recordVideo": true,"videoQuality": "FULL_HD1","uploadEvery": 1}
Pull viewer-count timeseries only
Skip every event except viewer counts. The dataset shrinks dramatically and only carries current_viewers, total_users, and popularity rows with ms-precise timestamps.
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 60,"excludeEvents": ["chat", "gift", "like", "member", "social","fansclub", "emoji_chat", "control","room_stats", "room_rank", "room_message"]}
Chat-and-gift focus
Drop everything except chat, gift, social (follows), and room ranks — the rows that matter for live-commerce analysis.
{"liveUrl": "https://live.douyin.com/376034101029","runTime": 60,"excludeEvents": ["like", "member", "viewer_count","fansclub", "emoji_chat", "control","room_stats", "room_message"]}
Bulk-resolve a profile URL with an unknown room id
Paste the broadcaster's profile URL or numeric user id. The actor resolves to the current live room or fails cleanly if the broadcaster isn't streaming.
{"liveUrl": "1929015166249580","runTime": 30}
Pricing — Pay Per Event (PPE)
You only pay for connection time and recording time.
| Event | Per second | Per minute |
|---|---|---|
| Metadata seconds (event capture) | $0.0015 | $0.09 |
| Recording seconds (MP4) | $0.00085 | $0.051 |
Cost Examples
| Run | Metadata | Recording | Total |
|---|---|---|---|
| 10 minutes, events only | $0.90 | — | ~$0.90 |
| 30 minutes, events + HD recording | $2.70 | $1.53 | ~$4.23 |
| 60 minutes, events + HD recording | $5.40 | $3.06 | ~$8.46 |
| 60 minutes, recording-only at Full HD | — | $3.06 | ~$3.06 |
Free tier — 5 lifetime runs, 5 minutes per run, recording disabled. No credit card required. Use it to validate the event shape and decide if the pricing fits before scaling up.
Cost Optimization
- Set
runTimeto bound the connection. Open-ended runs are easy to forget about. - Need MP4 only? Run with
captureEvents: false, recordVideo: true— recording-only at $0.051/min is the cheapest mode (no metadata billing). - Need events only? Leave
recordVideo: false— events-only at $0.09/min skips the recording cost. - Want both? Combined is ~$0.141/min ($8.46/hour).
- Use SD1 / SD2 quality when the goal is archival, not playback fidelity.
FAQ
Which live broadcasts can I record?
Any public Douyin (抖音) live broadcast. Paste a live.douyin.com URL, an app share link, a profile URL, a UserSecID, a numeric user id, or use auto for a demo room.
How fresh is the data? Every event is streamed in real time. Rows land in the dataset within seconds of the event firing in the live room.
What happens if the broadcaster goes offline mid-run?
The actor emits a control row with status: 3 and then exits cleanly with reason_for_exit: "stream_ended" on the summary row.
What happens if the live connection drops temporarily?
The actor reconnects with capped exponential backoff (2s, 4s, 8s, 16s, 30s). The summary's reconnect_count reflects how many drops happened during the run.
What happens if Apify migrates my run to a new host (long runs)?
The actor detects the restart, writes a single migration_notice row to the dataset, preserves whatever MP4 segments did upload before the migration, and exits without re-doing work or re-billing. Re-trigger the run for a fresh, complete capture if you need uninterrupted coverage. Runs shorter than ~20 minutes rarely see migrations.
Can I filter the dataset by event type?
Yes. The type column is the discriminator. Use type = "chat" for chat-only views, type = "gift" for tips, type = "viewer_count" for timeseries, and so on.
What's the free tier? 5 lifetime runs, capped at 5 minutes each, recording disabled. The cap resets only by upgrading to a paid plan.
How do I download the MP4 recordings?
The run's OUTPUT manifest lists every segment with a kv_url. Each URL is a direct download for the MP4 file. Segment length is controlled by uploadEvery (1–60 minutes).
Can I record commercial / restricted broadcasts? The actor only attaches to publicly visible broadcasts. Private or password-gated rooms aren't accessible.
Why is metadata_seconds_charged 0 on my local run?
Pay-per-event billing only fires on the Apify platform. Local runs and pre-publication runs show 0 here — the actor still emits everything, you just don't get charged.
Support
- Bugs: Issues tab
- Features: Issues tab
Legal Compliance
Extracts publicly available data from public live broadcasts. Users must comply with Douyin's terms of service and applicable data protection regulations (GDPR, CCPA). Do not record private, restricted, or copyright-protected content without authorization.
Real-time chat, gift, like, join, and viewer-count capture from Douyin (抖音) live broadcasts, with optional MP4 recording in SD–Full HD.