# Douyin 抖音 Video Scraper - Metadata + MP4 Downloads (`zen-studio/douyin-video-scraper`) Actor

Extract Douyin (抖音) video metadata: statistics, music tracks, hashtags, mentions, chapters, and creator profiles in 56 structured fields. 1,000 videos in ~70 seconds. Optional MP4, cover, and slideshow downloads. Accepts video URLs, share links, and bare aweme IDs.

- **URL**: https://apify.com/zen-studio/douyin-video-scraper.md
- **Developed by:** [Zen Studio](https://apify.com/zen-studio) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 videos

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Douyin Video Scraper (抖音) — Metadata, Music, Hashtags & MP4 Downloads (2026)

<blockquote style="border-left:4px solid #4C945E;background:#F0FDF4;padding:12px 16px">
<span style="font-size:16px;font-weight:700;color:#1C1917">1,000 Douyin (抖音) videos in ~70 seconds</span> <span style="font-size:15px;color:#57534E"> — full video metadata, statistics, music tracks, hashtags, chapters, and creator profiles in clean structured JSON. Optional MP4, cover, and slideshow downloads.</span>
</blockquote>

![Douyin Video Scraper](https://iili.io/BQp2kJV.png)

#### Copy to your AI assistant

````

zen-studio/douyin-video-scraper on Apify. Scrapes Douyin videos with full metadata: statistics, music, hashtags, chapters, video tags, mentions, location, series, plus 42-field authorMeta. Optional MP4/cover/slideshow downloads to KV store (kvUrl returned per file). Call ApifyClient("TOKEN").actor("zen-studio/douyin-video-scraper").call(run\_input={...}), then client.dataset(run\["defaultDatasetId"]).list\_items().items. videoUrls accepts douyin.com/video/<id>, iesdouyin share, v.douyin.com short links, or bare numeric aweme IDs. PPE: $6.99/1k videos, $4.99/1k MP4 downloads, covers+slideshow free. Steeper discounts on Starter/Scale/Business tiers. Token: https://console.apify.com/account/integrations

````

<table>
<tr>
<td colspan="4" style="padding:10px 14px;background:#4C945E;border:none;border-radius:4px 4px 0 0">
<span style="color:#FAFAF9;font-size:14px;font-weight:700;letter-spacing:0.5px">Zen Studio Social & Video</span>
<span style="color:#E8F5E9;font-size:13px">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Structured creator data from every major platform</span>
</td>
</tr>
<tr>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-radius:0 0 0 4px;background:#E8F5E9;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://iili.io/BQdin72.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/douyin-video-scraper" style="color:#4C945E;text-decoration:none;font-weight:700;font-size:14px">Douyin Video</a><br>
<span style="color:#4C945E;font-size:12px;font-weight:600">&#10148; You are here</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://iili.io/BQdin72.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/douyin-profile-scraper" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">Douyin Profile</a><br>
<span style="color:#78716C;font-size:12px">Followers, posts, hashtags</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-dexCSKEZtKS8hg4fT-lD4weyiYga-shigua-____-scraper-logo.jpg" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/xigua-video-search-scraper" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">Xigua Search</a><br>
<span style="color:#78716C;font-size:12px">Keyword + comments + MP4</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-radius:0 0 4px 0;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-TMZRtPvT8IrHSSC5p-VKjaWGjZKw-instagram-automation-api-logo.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/instagram-automation-api" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">Instagram API</a><br>
<span style="color:#78716C;font-size:12px">Engagement, DM, comments</span>
</td>
</tr>
</table>

### How to Scrape Douyin Videos

#### Basic — metadata only

```json
{
  "videoUrls": [
    "https://www.douyin.com/video/7577614489533680959",
    "7630302640823912635"
  ]
}
````

#### With cover images saved to your storage

```json
{
  "videoUrls": [
    "https://www.douyin.com/video/7577614489533680959",
    "https://v.douyin.com/iAbc123/"
  ],
  "shouldDownloadCovers": true
}
```

#### Kitchen-sink — metadata + MP4 + cover + slideshow

```json
{
  "videoUrls": ["7577614489533680959"],
  "shouldDownloadVideos": true,
  "shouldDownloadCovers": true,
  "shouldDownloadSlideshowImages": true
}
```

### Input Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `videoUrls` | string\[] | *required* | Douyin video URLs, share links, short links, or bare numeric aweme IDs. |
| `shouldDownloadVideos` | boolean | `false` | Save MP4 video files to your key-value store. Adds $4.99 per 1,000 successful downloads. Image-text posts have no MP4. |
| `shouldDownloadCovers` | boolean | `false` | Save each video's cover image (JPEG) to your key-value store. Free. |
| `shouldDownloadSlideshowImages` | boolean | `false` | For image-text posts, save every slide image to your key-value store. Free. |
| `videoKvStoreName` | string | — | Optional named key-value store for downloads. Leave empty to use the run's default store. |
| `proxyConfiguration` | object | Apify Residential | Defaults to China residential with Hong Kong fallback. Override only if you have a specific proxy requirement. |

#### Accepted video input formats

| Format | Example |
|---|---|
| Browser address bar URL | `https://www.douyin.com/video/7577614489533680959` |
| App share link (auto-resolved) | `https://v.douyin.com/iAbc123/` |
| Legacy share URL | `https://www.iesdouyin.com/share/video/7577614489533680959/` |
| Bare numeric aweme ID | `7577614489533680959` |

### What Data Can You Extract from Each Douyin Video?

One row per video with deeply nested rich blocks. The headline numbers:

- **56 top-level fields per video** — identity, captions, timestamps, locality, content flags, type labels, plus eleven nested object/array blocks.
- **42 author fields** under `authorMeta` — covering everything from total likes received to school, badge label, custom username, cross-platform IDs, and five avatar sizes.
- **25 video media fields** under `videoMeta` — multi-quality variants (H.264, H.265, low-bitrate), bit-rate ladder, dimensions, sprite preview, and `cdnUrlExpiresAt` so you know when CDN links die.
- **45 music fields** under `musicMeta` — full track + artist info, owner attribution, durations, audition snippets, commerce flags.
- **13 engagement counters** under `statistics` — likes, comments, shares, plays, downloads, forwards, collects, plus admire and live-watch counts.

#### Per-video fields (top level)

- **Identity** — `id`, `url`, `shareUrl`, `type` (`video` / `imageText` / `story`), `awemeType` + `awemeTypeLabel` (`video`, `imageText`, `ad`, `forward`, `duet`, `story`, …), `mediaType` + `mediaTypeLabel` (`video`, `imageText`, `image`, `audio`), `inputUrl`
- **Content** — `text`, `caption`, `itemTitle`, `previewTitle`, `descLanguage`
- **Timing & locality** — `createTime` (unix), `createDate` (ISO), `region` (creator IP), `city` + `cityCode` (upload location, GB/T 2260)
- **Flags** — `isPinned`, `isAd`, `isPgc`, `isShared`, `isStory`, `is24Story`, `is25Story`, `isFirstVideo`, `isLifeItem`, `isKaraoke`, `isDuetSing`, `isFantasy`, `isInScope`, `isImageBeat`, `isVr`

#### Author / creator fields (`authorMeta`, ~40 fields)

`id`, `secUid`, `name`, `username`, `customUsername`, `verified`, `verificationReason`, `signature` (bio), five avatar sizes (`avatarThumb`, `avatarMedium`, `avatar168`, `avatar300`, `avatarLarge`), `bgImage`, `followingCount`, `followersCount`, `followersCountStr`, `totalLikesReceived`, `likesGivenCount`, `awemeCount`, `gender`, `language`, `country`, `ipLocation`, `verifyType`, `customVerifyText`, `enterpriseVerifyReason`, `userAge`, `birthday`, `constellation`, `isLiving`, `roomId`, `isStar`, `usesSeries`, `withShopEntry`, `commerceUserLevel`, `school`, `customUsernameUpdatedAt`, `shareUrl`, `shareQrCodeUri`, `crossPlatform`, `mcnInfo`.

#### Video media (`videoMeta`)

Multi-quality playback URLs (`playUrl`, `downloadUrl`, `playUrlH264`, `playUrlH265`, `playUrlLowBitrate`), full bit-rate ladder (`bitRates[]` with quality, fps, codec flag), dimensions (`width`, `height`, `ratio`, `format`), four cover variants (`cover`, `coverOriginalScale`, `originCover`, `dynamicCover`, `animatedCover`), sprite-sheet preview (`bigThumbs`), encoder hints (`isBytevc1`, `isHdr`, `useStaticCover`, `horizontalType`, `isLongVideo`, `hasWatermark`), and **`cdnUrlExpiresAt`** — the unix timestamp when the playback URLs stop working.

#### Music / audio (`musicMeta`)

Track record: `id`, `title`, `author`, `album`, `artists[]`, `artistUserInfos[]`, `musicianUserInfos[]`, plus `duration`, `playUrl`, `coverThumb`, `coverMedium`, `coverLarge`, ownership flags (`isOriginal`, `isPgc`, `isCommerce`), owner attribution (`ownerId`, `ownerHandle`, `ownerNickname`, `secUid`).

#### Engagement (`statistics`)

`diggCount`, `commentCount`, `shareCount`, `collectCount`, `downloadCount`, `playCount`, `forwardCount`, `admireCount`, `whatsappShareCount`, `liveWatchCount`, `exposureCount`, `loseCount`, `loseCommentCount`. Note: `playCount` is server-hidden by Douyin and returns `0`.

#### Optional downloads

When you toggle them on, downloaded media lands in your key-value store and the row's `videoFile` / `coverFile` / `slideshowFiles` fields each carry:

```json
{
  "kvStoreKey": "7577614489533680959.mp4",
  "kvStoreId": "GcaUbB3ejAQUjie4o",
  "kvUrl": "https://api.apify.com/v2/key-value-stores/GcaUbB3ejAQUjie4o/records/7577614489533680959.mp4",
  "sizeBytes": 5328417,
  "mimeType": "video/mp4",
  "sourceUrl": "https://v5-hl-mly-ov.zjcdn.com/..."
}
```

`kvUrl` is the public Apify API URL of the stored bytes — visit it while logged into Apify (or fetch it with your token) to get the file. When downloads are off (or fail), those fields are `null`.

#### Output Example

Every top-level field below is always present in every row. Arrays and
nested objects are trimmed for readability — production rows contain
the full content (e.g. `videoMeta` has 25 sub-fields, `authorMeta` has
42, `musicMeta` has 45, `permissions` has 23).

```json
{
  "id": "7577614489533680959",
  "url": "https://www.douyin.com/video/7577614489533680959",
  "shareUrl": "https://www.iesdouyin.com/share/video/7577614489533680959/?...",
  "type": "video",
  "awemeType": 0,
  "awemeTypeLabel": "video",
  "mediaType": 4,
  "mediaTypeLabel": "video",
  "isStory": false,
  "text": "这个贵州五线小城，凭什么是中国"吃商"最高的城市？\n#抖音美食班当季新菜单 #贵州美食 #老吃家",
  "caption": "糟了，捅了贵州老吃家的窝了！",
  "itemTitle": "这个贵州五线小城，凭什么是中国"吃商"最高的城市？",
  "previewTitle": "这个贵州五线小城，凭什么是中国"吃商"最高的城市？",
  "descLanguage": "zh",
  "createTime": 1764320400,
  "createDate": "2025-11-28",
  "region": "CN",
  "city": "Shanghai",
  "cityCode": "310000",
  "isPinned": false,
  "isAd": false,
  "isPgc": false,
  "isShared": false,
  "is24Story": false,
  "is25Story": false,
  "isFirstVideo": false,
  "isLifeItem": true,
  "isKaraoke": false,
  "isDuetSing": false,
  "isFantasy": false,
  "isInScope": false,
  "isImageBeat": false,
  "isVr": false,
  "authorMeta": {
    "id": "75736792009",
    "secUid": "MS4wLjABAAAAjjwfy25gmtDlk8Wg6FNIBzHdHicG6BpZZNvWoTLL8S4",
    "name": "盗月社食遇记",
    "username": "124700482",
    "customUsername": "daoyueshe",
    "verified": true,
    "signature": "❤️心里有光，哪儿都美❤️",
    "avatarLarge": "https://p26.douyinpic.com/aweme/1080x1080/aweme-avatar/...",
    "totalLikesReceived": 17589628,
    "awemeCount": 685,
    "gender": "male",
    "country": "CN",
    "isLiving": false
  },
  "videoMeta": {
    "duration": 1082500,
    "width": 1280,
    "height": 720,
    "ratio": "720p",
    "format": "mp4",
    "isLongVideo": true,
    "isHdr": false,
    "isBytevc1": false,
    "hasWatermark": true,
    "cdnUrlExpiresAt": 1777980189,
    "playUrl": "https://v5-hl-mly-ov.zjcdn.com/.../?...",
    "downloadUrl": "https://v5-hl-mly-ov.zjcdn.com/.../?...",
    "playUrlH265": "https://v5-hl-mly-ov.zjcdn.com/.../?...",
    "bitRates": [
      { "quality": "720_1_1", "bitRate": 1175087, "isH265": true, "fps": 30, "qualityType": 11, "url": "..." }
    ],
    "cover": "https://p3-sign.douyinpic.com/tos-cn-i-dy/...?...",
    "originCover": "https://p5-ex-gddgtc-sign.douyinpic.com/tos-cn-p-0015/...~tplv-dy-360p.webp?...",
    "dynamicCover": "https://p3-sign.douyinpic.com/obj/tos-cn-i-dy/...?..."
  },
  "musicMeta": {
    "id": "7577614774507424547",
    "title": "@盗月社食遇记创作的原声",
    "author": "盗月社食遇记",
    "isOriginal": true,
    "duration": 1082,
    "playUrl": "https://lf9-music-east.douyinstatic.com/obj/ies-music-hj/7577614877490023225.mp3",
    "ownerId": "75736792009",
    "ownerHandle": "daoyueshe",
    "ownerNickname": "盗月社食遇记",
    "secUid": "MS4wLjABAAAAjjwfy25gmtDlk8Wg6FNIBzHdHicG6BpZZNvWoTLL8S4"
  },
  "statistics": {
    "diggCount": 4037193,
    "shareCount": 5135670,
    "commentCount": 162235,
    "collectCount": 855021,
    "playCount": 0,
    "downloadCount": 634,
    "forwardCount": 0,
    "admireCount": 0
  },
  "permissions": {
    "canDuet": true,
    "canStitch": false,
    "canDownload": false,
    "canShare": true,
    "canComment": true,
    "canRepost": true,
    "canSave": true,
    "canShowComment": true,
    "isPrivate": false,
    "isProhibited": false,
    "isInReviewing": false,
    "isDeleted": false,
    "isReviewed": true,
    "withGoods": false
  },
  "interaction": {
    "canComment": true,
    "canShowComment": true,
    "canShare": true,
    "canForward": true,
    "commentDisabled": false
  },
  "anchors": [
    { "type": 5001, "title": "贵州美食店打卡", "url": "https://www.douyin.com/poi/...", "iconUrl": "https://..." }
  ],
  "commerce": {
    "isAd": false,
    "isCommerceItem": false,
    "starAtlasOrderId": null,
    "branded": false,
    "withGoods": false
  },
  "risk": {
    "type": 0,
    "tag": null,
    "warn": false,
    "noticeText": null
  },
  "share": {
    "title": "盗月社食遇记发布了一个抖音作品...",
    "desc": "短视频生成日记！",
    "shareUrl": "https://www.iesdouyin.com/share/video/7577614489533680959/",
    "shareUrlSigned": "https://www.iesdouyin.com/share/video/7577614489533680959/?signed=...",
    "shareWeiboUrl": "https://www.iesdouyin.com/.../?platform=weibo",
    "shareQqUrl": "https://www.iesdouyin.com/.../?platform=qq",
    "shareQzoneUrl": "https://www.iesdouyin.com/.../?platform=qzone"
  },
  "xiguaCrossPost": {
    "isOnXigua": false,
    "xiguaItemId": null,
    "xiguaShareUrl": null
  },
  "aiMetadata": {
    "aiGeoHot": 1,
    "aiGeoNote": 1,
    "aiSmartdoc": 3,
    "aiNoteV2": 1,
    "aiNoteVertical": 1,
    "rawSeo": null,
    "rawExtra": null
  },
  "images": [],
  "mentions": [
    { "secUid": "MS4wLjABAAAA...", "userId": "98123450123", "nickname": "@朋友A" }
  ],
  "hashtags": [
    { "id": "7572059655971538944", "name": "抖音美食班当季新菜单" },
    { "id": "1594485689837575", "name": "贵州美食" },
    "... +3 more"
  ],
  "videoTags": [
    { "name": "美食", "level": 1 },
    { "name": "美食探店", "level": 2 },
    { "name": "餐厅探店", "level": 3 }
  ],
  "chapters": [
    { "startMs": 30000, "title": ""吃商"最高的城市", "coverUrl": "https://p26-sign.douyinpic.com/...", "detail": null },
    { "startMs": 47000, "title": "36块8的自助烤小肠！", "coverUrl": "https://p26-sign.douyinpic.com/...", "detail": "还有20多种肉，这物价惊呆我" },
    "... +14 more"
  ],
  "series": {
    "id": "7486681757459154981",
    "name": "吃垮中国街头美食",
    "episode": 8,
    "total": 10,
    "coverUrl": "https://p3-sign.douyinpic.com/obj/douyin-user-image-file/...?...",
    "shareUrl": "https://www.iesdouyin.com/share/mix/detail/7486681757459154981/",
    "updateTime": 1774195445
  },
  "location": {
    "poiId": "6601234567890123456",
    "poiName": "老凯里酸汤鱼（南门店）",
    "address": "贵州省贵阳市南明区...",
    "latitude": 26.5783,
    "longitude": 106.7135,
    "city": "贵阳市",
    "province": "贵州省"
  },
  "videoFile": {
    "kvStoreKey": "7577614489533680959.mp4",
    "kvStoreId": "GcaUbB3ejAQUjie4o",
    "kvUrl": "https://api.apify.com/v2/key-value-stores/GcaUbB3ejAQUjie4o/records/7577614489533680959.mp4",
    "sizeBytes": 215476832,
    "mimeType": "video/mp4",
    "sourceUrl": "https://v5-hl-mly-ov.zjcdn.com/.../?..."
  },
  "coverFile": {
    "kvStoreKey": "7577614489533680959.jpg",
    "kvStoreId": "GcaUbB3ejAQUjie4o",
    "kvUrl": "https://api.apify.com/v2/key-value-stores/GcaUbB3ejAQUjie4o/records/7577614489533680959.jpg",
    "sizeBytes": 32366,
    "mimeType": "image/jpeg",
    "sourceUrl": "https://p3-sign.douyinpic.com/tos-cn-i-dy/...?..."
  },
  "slideshowFiles": null,
  "inputUrl": "7577614489533680959"
}
```

> Notes on optional / context-dependent fields:
>
> - `images` is empty for plain video posts and populated (with `width`/`height`/`url`) for image-text posts (`type = "imageText"`).
> - `slideshowFiles` is `null` for video posts and populated only when **Download slideshow images** is on AND the post is image-text.
> - `videoFile` and `coverFile` are `null` unless **Download MP4 videos** / **Download cover images** are toggled on.
> - `location` is `null` when no POI is attached.
> - `mentions`, `chapters`, `series`, `anchors` are commonly empty arrays / `null` for casual posts.

### Important: URL Durability

Different URL types in the output have very different lifespans. Plan your downstream pipeline accordingly.

| Field | Lifespan | Note |
|---|---|---|
| `id`, `url` (canonical video URL) | **Permanent** | `https://www.douyin.com/video/<id>` — never expires. The reliable reference. |
| `shareUrl`, `share.shareUrl` | **Permanent** | `https://www.iesdouyin.com/share/video/<id>/` — also permanent. |
| `share.shareUrlSigned` | **~24 hours** | Personalised share URL with tracking signature; the unsigned `share.shareUrl` is the long-term version. |
| `authorMeta.shareUrl` | **Permanent** | Profile share URL. |
| `authorMeta.avatarThumb` … `avatarLarge` (5 sizes) | **Permanent** | CDN-direct, no signature. |
| `musicMeta.playUrl`, `musicMeta.coverLarge` | **Permanent** | CDN-direct, no signature. |
| `videoMeta.cover`, `videoMeta.originCover`, `videoMeta.dynamicCover`, `videoMeta.animatedCover`, `images[].url`, `chapters[].coverUrl`, `series.coverUrl` | **~14–30 days** | Signed CDN URLs (`*-sign.douyinpic.com`). The query string holds the signature; download or re-upload to your own storage if you need them long-term. |
| `videoMeta.playUrl`, `videoMeta.downloadUrl`, `videoMeta.playUrlH264`, `videoMeta.playUrlH265`, `videoMeta.playUrlLowBitrate`, `videoMeta.bitRates[].url` | **~1 hour** | Short-lived video CDN URLs. The exact expiry time is in **`videoMeta.cdnUrlExpiresAt`** (unix-seconds) — check it before downloading. |

The `id` and `url` fields are the only truly permanent references. Build your downstream pipeline around them, then re-resolve fresh media URLs whenever you need them — or enable `shouldDownloadVideos` / `shouldDownloadCovers` to keep copies in your own storage.

### Advanced Usage

#### Save downloads to a named key-value store

```json
{
  "videoUrls": ["7577614489533680959", "7630302640823912635"],
  "shouldDownloadVideos": true,
  "shouldDownloadCovers": true,
  "videoKvStoreName": "douyin-archive-2026-q4"
}
```

Pair the run with a daily schedule and the named store accumulates a stable archive across runs, instead of being wiped with each run's default storage.

#### Force a specific proxy country

```json
{
  "videoUrls": ["7577614489533680959"],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "HK"
  }
}
```

The actor defaults to China residential with a Hong Kong fallback. Override only when you have a specific egress requirement.

#### Bulk-archive an image-text post (slideshow)

```json
{
  "videoUrls": ["https://www.iesdouyin.com/share/video/7630302640823912635/"],
  "shouldDownloadSlideshowImages": true,
  "shouldDownloadCovers": true
}
```

For image-text posts, every slide is saved as a separate file in the key-value store (`<aweme_id>_slide_1.jpg`, `<aweme_id>_slide_2.jpg`, …). Plain video posts ignore this toggle.

### Pricing — Pay Per Event (PPE)

You pay per video scraped, with optional add-ons for downloaded media. Apify subscribers get steeper discounts on every tier.

| | **Free** | **Starter** | **Scale** | **Business** |
|---|---|---|---|---|
| **Video scraped** (one row in your dataset) | **$6.99** / 1k | $4.99 / 1k | $4.49 / 1k | $3.99 / 1k |
| **MP4 download** (one saved video file) | $4.99 / 1k | $3.99 / 1k | $3.49 / 1k | $2.99 / 1k |
| **Cover image** | Free | Free | Free | Free |
| **Slideshow images** | Free | Free | Free | Free |

Two trivial platform events also fire (`apify-actor-start` once per run, `apify-default-dataset-item` once per row at $0.01 / 1,000) — covered by the free Apify tier in practice.

### FAQ

**How many fields are returned per video?**
56 top-level fields, plus 11 nested rich blocks. The biggest are `authorMeta` (42 author fields), `musicMeta` (45 track fields), `videoMeta` (25 media fields), `permissions` (23 flags), and `statistics` (13 counters).

**What types of inputs are accepted?**
Browser address-bar URLs (`douyin.com/video/<id>`), legacy share URLs (`iesdouyin.com/share/video/<id>/`), app share short links (`v.douyin.com/...`, auto-resolved), and bare numeric aweme IDs. You can mix all of them in one `videoUrls` array.

**How long do download URLs last?**
The CDN URLs in `videoMeta` (playback / download / multi-bitrate) typically live about an hour — the exact expiry is in `videoMeta.cdnUrlExpiresAt`. Cover and avatar URLs live ~14–30 days. The post `url` is permanent. If you need long-term media, enable `shouldDownloadVideos` / `shouldDownloadCovers` to copy the bytes into your own storage.

**Do video downloads work for image-text posts?**
No. Image-text posts have no MP4. Use `shouldDownloadSlideshowImages` instead — that saves every slide image (one file per slide).

**Where are downloaded files saved?**
By default, into the run's own key-value store, which you can find on the run's *Storage* tab. Set `videoKvStoreName` to a stable name (e.g. `douyin-archive`) to accumulate downloads across runs in one named store instead.

**How fresh is the data?**
Live — every field is fetched on demand at run time. No caching.

**Are statistics live?**
Yes. `diggCount`, `commentCount`, `shareCount`, `collectCount`, `playCount`, etc. are pulled live with each run. Note that `playCount` is often `0` — Douyin hides the play count from third-party clients on most videos.

**What's the difference between `hashtags` and `videoTags`?**
`hashtags` are the `#tag`s the creator typed in the caption. `videoTags` is Douyin's own 3-level content classification — e.g. `美食` (level 1, top-level category) → `美食探店` (level 2) → `餐厅探店` (level 3, leaf). The classification is server-assigned and is one of the more interesting signals on the platform.

**What's the difference between `permissions` and `interaction`?**
`permissions` are author-set + platform-set visibility flags (can the post be downloaded, duetted, stitched, shared, commented). `interaction` covers the engagement layer — comment-input placeholder text, AB-test flags, audio-comment permissions, image-challenge config.

**What's the difference between `text`, `caption`, `itemTitle`, and `previewTitle`?**
Douyin returns up to four caption variants per post. `text` is the full creator-typed description (with hashtags inline). `caption` is the trimmed version Douyin shows in some feeds. `itemTitle` is the headline-style title (often only set on PGC content). `previewTitle` is the share-card preview text. They overlap heavily — pick whichever fits your use case.

**Can I scrape comments / replies / followers / liked videos?**
Not in this actor. Per-video metadata + author profile + downloads only. Other actors in this collection cover comments, profile-level data, and follower lists separately.

**Does the actor work for any Douyin video?**
Public videos only. Private posts, deleted videos, region-locked posts (where the creator's region or the post's geofence excludes our egress), and accounts that have blocked external access are not addressable.

**What's the maximum number of videos per run?**
10,000 per run. Inputs are deduplicated by aweme ID so duplicates cost nothing.

### Support

- **Bugs**: Issues tab
- **Features**: Issues tab

### Legal Compliance

Extracts publicly available data from Douyin (抖音). Users must comply with Douyin's terms of service and applicable data protection regulations (GDPR, CCPA).

***

*Structured Douyin video metadata — engagement, music, hashtags, chapters, full creator profile — for any public video, in clean JSON. Optional MP4, cover, and slideshow downloads.*

# Actor input Schema

## `videoUrls` (type: `array`):

Add one or more Douyin videos you want to scrape.<br><br>Accepted formats:<ul><li>Browser address bar: <code>https://www.douyin.com/video/7577614489533680959</code></li><li>App share link: <code>https://v.douyin.com/iAbc123/</code></li><li>Legacy share: <code>https://www.iesdouyin.com/share/video/7577614489533680959/</code></li><li>Bare numeric aweme ID: <code>7577614489533680959</code></li></ul>If both <b>Video URLs</b> and <b>Start URLs</b> are set, <b>Video URLs</b> wins.

## `shouldDownloadVideos` (type: `boolean`):

Save the MP4 file for each video to your key-value store. Adds <b>$4.99 per 1,000 successful downloads</b>. Image-text posts have no MP4 — use <b>Download slideshow images</b> instead.

## `shouldDownloadCovers` (type: `boolean`):

Save each video's cover image (JPEG) to your key-value store. <b>Free.</b>

## `shouldDownloadSlideshowImages` (type: `boolean`):

For image-text posts, save every slide image to your key-value store. <b>Free.</b> Has no effect on plain video posts.

## `videoKvStoreName` (type: `string`):

Save downloaded MP4s, covers, and slideshow images to a <b>named, persistent</b> key-value store instead of the run's default one. Useful for archiving (the named store survives forever, the default one is cleaned up with the run) and for combining downloads from many runs into one bucket you can reuse later.<br><br><b>Naming rules:</b> lowercase letters, digits, and dashes only.<br><br><b>Common patterns:</b><ul><li><code>douyin-videos</code> — single shared archive</li><li><code>douyin-2026-q2</code> — partition by quarter</li><li><code>douyin-cooking-creators</code> — partition by topic / niche</li></ul>Browse and re-download anything you've saved at <a href="https://console.apify.com/storage/key-value" target="_blank">console.apify.com/storage/key-value</a>.<br><br>Leave empty to use this run's default store.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.douyin.com/video/7577614489533680959",
    "7630302640823912635"
  ],
  "shouldDownloadVideos": false,
  "shouldDownloadCovers": false,
  "shouldDownloadSlideshowImages": false,
  "videoKvStoreName": ""
}
```

# Actor output Schema

## `videos` (type: `string`):

Link to the dataset containing all scraped Douyin videos.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoUrls": [
        "https://www.douyin.com/video/7577614489533680959",
        "7630302640823912635"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zen-studio/douyin-video-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "videoUrls": [
        "https://www.douyin.com/video/7577614489533680959",
        "7630302640823912635",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("zen-studio/douyin-video-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.douyin.com/video/7577614489533680959",
    "7630302640823912635"
  ]
}' |
apify call zen-studio/douyin-video-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=zen-studio/douyin-video-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Douyin 抖音 Video Scraper - Metadata + MP4 Downloads",
        "description": "Extract Douyin (抖音) video metadata: statistics, music tracks, hashtags, mentions, chapters, and creator profiles in 56 structured fields. 1,000 videos in ~70 seconds. Optional MP4, cover, and slideshow downloads. Accepts video URLs, share links, and bare aweme IDs.",
        "version": "0.0",
        "x-build-id": "PfbS5zYhrKf5voqg0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/zen-studio~douyin-video-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-zen-studio-douyin-video-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/zen-studio~douyin-video-scraper/runs": {
            "post": {
                "operationId": "runs-sync-zen-studio-douyin-video-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/zen-studio~douyin-video-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-zen-studio-douyin-video-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "videoUrls": {
                        "title": "🎬 Video URLs or aweme IDs",
                        "type": "array",
                        "description": "Add one or more Douyin videos you want to scrape.<br><br>Accepted formats:<ul><li>Browser address bar: <code>https://www.douyin.com/video/7577614489533680959</code></li><li>App share link: <code>https://v.douyin.com/iAbc123/</code></li><li>Legacy share: <code>https://www.iesdouyin.com/share/video/7577614489533680959/</code></li><li>Bare numeric aweme ID: <code>7577614489533680959</code></li></ul>If both <b>Video URLs</b> and <b>Start URLs</b> are set, <b>Video URLs</b> wins.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "shouldDownloadVideos": {
                        "title": "📥 Download MP4 videos",
                        "type": "boolean",
                        "description": "Save the MP4 file for each video to your key-value store. Adds <b>$4.99 per 1,000 successful downloads</b>. Image-text posts have no MP4 — use <b>Download slideshow images</b> instead.",
                        "default": false
                    },
                    "shouldDownloadCovers": {
                        "title": "🖼️ Download cover images",
                        "type": "boolean",
                        "description": "Save each video's cover image (JPEG) to your key-value store. <b>Free.</b>",
                        "default": false
                    },
                    "shouldDownloadSlideshowImages": {
                        "title": "🎴 Download slideshow images",
                        "type": "boolean",
                        "description": "For image-text posts, save every slide image to your key-value store. <b>Free.</b> Has no effect on plain video posts.",
                        "default": false
                    },
                    "videoKvStoreName": {
                        "title": "Custom key-value store name",
                        "type": "string",
                        "description": "Save downloaded MP4s, covers, and slideshow images to a <b>named, persistent</b> key-value store instead of the run's default one. Useful for archiving (the named store survives forever, the default one is cleaned up with the run) and for combining downloads from many runs into one bucket you can reuse later.<br><br><b>Naming rules:</b> lowercase letters, digits, and dashes only.<br><br><b>Common patterns:</b><ul><li><code>douyin-videos</code> — single shared archive</li><li><code>douyin-2026-q2</code> — partition by quarter</li><li><code>douyin-cooking-creators</code> — partition by topic / niche</li></ul>Browse and re-download anything you've saved at <a href=\"https://console.apify.com/storage/key-value\" target=\"_blank\">console.apify.com/storage/key-value</a>.<br><br>Leave empty to use this run's default store.",
                        "default": ""
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
