# Douyin Scraper — Hot Trends, Videos & TikTok China Data (`bovi/douyin-scraper`) Actor

Collect Douyin hot-search topics with ranks, hot values, views, video counts, IDs, timestamps, and quality fields. Run with hot_search; other modes require real logged-in cookies. Pricing: $0.00049 per result on Free.

- **URL**: https://apify.com/bovi/douyin-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Social media, Marketing
- **Features:** Limited permissions
- **Stats:** 90 total users, 6 monthly users, 89.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.48 / 1,000 hot search topics

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Douyin Scraper for Hot Trends and Videos

Douyin Scraper extracts Douyin (抖音) hot-search topics, videos, user posts, comments, and metadata from Douyin endpoints. Use `hot_search` for trending topics; other modes require a real logged-in session through cookie inputs, while Free runs cap `maxItems` at 10, retain one input ID or keyword, and return zero comments.

- Monitor ranked topics with hot values, views, video counts, and event times.
- Extract video metadata and engagement fields for content intelligence.
- Review comments, authors, likes, replies, and timestamps.
- Run keyword, user-video, comment, and video-detail jobs through one Actor.

### What you get

Normalized records include `parse_confidence` and `warnings`. Missing source values are `null`.

| Record type | Fields | Type | What they contain |
|---|---|---|---|
| Hot-search identity | `rank`, `sentence_id`, `word` | `rank`: integer; others: string | Topic rank, ID, and text (`hot_search`) |
| Hot-search metrics | `hot_value`, `view_count`, `video_count`, `discuss_video_count` | integer | Hot value, views, associated and discussion videos |
| Hot-search metadata | `word_type`, `label` | integer | Topic type and label |
| Hot-search timing | `event_time`, `scraped_at` | ISO 8601 string | Event and scrape times |
| Hot-search quality | `parse_confidence`, `warnings` | number; array of strings | Completeness and missing-field warnings |
| Video identity | `aweme_id`, `desc` | — | Video ID and caption |
| Video author | `author_uid`, `author_nickname`, `author_sec_uid` | — | Author IDs and display name |
| Video engagement | `digg_count`, `comment_count`, `share_count`, `play_count`, `collect_count` | — | Likes, comments, shares, plays, and saves |
| Video media | `video_url`, `cover_url` | — | Video and cover URLs |
| Music | `music_title`, `music_author`, `music_url` | — | Music title, author, and URL |
| Video metadata | `create_time`, `duration_ms`, `is_top`, `hashtags` | — | Creation time, duration, pinned status, and hashtags |
| Video quality | `scraped_at`, `parse_confidence`, `warnings` | — | Scrape time, completeness, and warnings |
| Comment identity | `comment_id`, `aweme_id`, `text` | — | Comment ID, video ID, and text |
| Comment author | `author_uid`, `author_nickname` | — | Author ID and display name |
| Comment engagement | `digg_count`, `reply_count` | — | Comment likes and replies |
| Comment metadata | `create_time`, `scraped_at` | — | Creation and scrape times |
| Comment quality | `parse_confidence`, `warnings` | — | Completeness and warnings |

### Sample output

The sample below is one real hot-search record from the dataset sample.

```json
{
  "rank": 2,
  "sentence_id": "2736348",
  "word": "BLG战胜T1挺进决赛",
  "hot_value": 12135561,
  "view_count": 68973633,
  "video_count": 15,
  "discuss_video_count": 1,
  "word_type": 1,
  "event_time": "2026-11-08T13:00:17+00:00",
  "label": 3,
  "scraped_at": "2026-11-09T06:58:08.913182+00:00",
  "parse_confidence": 1,
  "warnings": []
}
```

### Pricing

Billing uses events. `hot-search-result` is charged for each trending topic. `video-result` is charged for video records and each pushed comment in `comments` mode. `apify-actor-start` is charged when the Actor starts; its event count depends on Actor memory, with one event per GB and a minimum of one event.

#### Live event prices

| Event | Plan | Price per event |
|---|---|---:|
| `apify-actor-start` | Free plan | $0.00005 |
| `apify-actor-start` | Bronze plan | $0.0000495 |
| `apify-actor-start` | Silver plan | $0.000049 |
| `apify-actor-start` | Gold plan | $0.0000485 |
| `apify-actor-start` | Platinum plan | $0.000048 |
| `apify-actor-start` | Diamond plan | $0.0000475 |
| `hot-search-result` | Free plan | $0.00049 |
| `hot-search-result` | Bronze plan | $0.0004851 |
| `hot-search-result` | Silver plan | $0.0004802 |
| `hot-search-result` | Gold plan | $0.0004753 |
| `hot-search-result` | Platinum plan | $0.0004704 |
| `hot-search-result` | Diamond plan | $0.0004655 |
| `video-result` | Free plan | $0.00099 |
| `video-result` | Bronze plan | $0.0009801 |
| `video-result` | Silver plan | $0.0009702 |
| `video-result` | Gold plan | $0.0009603 |
| `video-result` | Platinum plan | $0.0009504 |
| `video-result` | Diamond plan | $0.0009405 |

1,000 hot-search results = $0.49005 on Free, assuming one Free-plan Actor Start event: $0.49 for results plus $0.00005 for the start event. 10,000 hot-search results = $4.90005 on Free, assuming one Free-plan Actor Start event: $4.90 for results plus $0.00005 for the start event.

The $5 credit covers **10,203 hot-search results** after one Free-plan Actor Start event.

Apify Free plan includes **$5 of monthly platform usage credit**. This Actor does not use the Pay per event + usage option, so compute, proxy traffic, and storage are not billed separately.

### How to use

1. **Choose** `hot_search`, `search`, `user_videos`, `comments`, or `video_detail`.
2. **Add** `keywords`, `sec_user_ids`, or `aweme_ids` for the selected mode.
3. **Configure** an Apify residential proxy with country `CN`.
4. **Provide** `msToken`, `ttwid`, or `svWebId` values when available for session-based modes.
5. **Set** `maxItems` or `maxComments`, then start the run.
6. **Repeat** the run through Apify Schedules; daily is a reasonable starting point for hot-search monitoring.

```json
{
  "mode": "hot_search",
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "CN"
  }
}
```

Export the dataset as JSON or CSV, or read it through the Apify dataset API.

### Input parameters

| Parameter | What it does | Default |
|---|---|---|
| `mode` | Selects `hot_search`, `search`, `user_videos`, `comments`, or `video_detail`; invalid values become `hot_search`. | `hot_search` |
| `keywords` | Search terms for `search`; each runs separately up to the item limit. | No value; empty list |
| `sec_user_ids` | Douyin `sec_user_id` strings for `user_videos`. | No value; empty list |
| `aweme_ids` | Video IDs for `comments` or `video_detail`. | No value; empty list |
| `maxItems` | Limits videos in `search` and `user_videos`, and hot-search records on non-paying runs. Range: 1–10000. | `50` |
| `maxComments` | Limits comments per video in `comments`. Range: 1–5000; non-paying runs set it to `0`. | `50` |
| `msToken` | Optional real `msToken` cookie for session-based modes. | Not set |
| `ttwid` | Optional `ttwid` cookie; if omitted, the Actor attempts to obtain one automatically. | Not set |
| `svWebId` | Optional real `s_v_web_id` cookie for session-based modes. | Not set |
| `proxyConfiguration` | Configures the Apify proxy. | CN `RESIDENTIAL` prefill; CN residential fallback |

### Limits and edge cases

| Condition | What the buyer sees | What to do |
|---|---|---|
| A Free or otherwise non-paying run is used | `maxItems` is capped at 10, one keyword, user ID, or video ID is retained, and `maxComments` becomes `0` | Use a paid Apify plan for more inputs or comments |
| `comments` runs on a non-paying plan | Zero comments and an explanation that comments are not returned on free runs | Use a paid Apify plan |
| A required mode input is missing | Succeeded with zero records; `OUTPUT` contains `no_keywords`, `no_sec_user_ids`, or `no_aweme_ids` | Supply the required input |
| Douyin returns login-required code `2483` | Session modes can return zero records, the run fails, and `OUTPUT.errors` lists the error | Review `OUTPUT.errors` and cookies, or use `hot_search` |
| No usable CN residential proxy is available | Requests may be rate-limited, challenged, blocked, or return an access error | Configure Apify `RESIDENTIAL` with country `CN` |
| The hot-search response has an empty `word_list` | Zero records, a no-topics message, a failed run, and the condition in `OUTPUT.errors` | Run again later or check for a changed response format |
| Some requests succeed and later requests fail | Delivered batches reach the dataset; the run succeeds with delivered records, `OUTPUT.errors` lists failures, and it reports a partial result | Review `OUTPUT.errors` and rerun the failed scope |
| A valid request returns no records without a fetch error | Succeeded with an empty dataset and a status message | Try different keywords or IDs, or use `hot_search` |
| A private account or video is requested | The private content cannot be retrieved because login is required and unsupported | Use publicly available content and supported session-based modes |
| An expired video CDN URL is used | `video_url` may no longer download because URLs expire within hours to days | Download required media promptly |

Request signing uses a pure-Python `a_bogus` implementation based on SM3, RC4, and custom Base64 processing, so a browser is not required for signing.

### FAQ

#### How much does it cost to scrape Douyin?

On Free, hot-search results cost $0.00049 each, video results cost $0.00099 each, and Actor Start costs $0.00005 per event. 1,000 hot-search results = $0.49005 on Free, assuming one Actor Start event.

#### Why did my run return an empty result?

The mode-specific input may be missing, or a non-paying `comments` run may have `maxComments` set to zero. Check the run status and `OUTPUT.errors`, then provide the required input or use `hot_search`.

#### What should I do if Douyin blocks the run?

Configure an Apify residential proxy for country `CN`. If the run reports login-required code `2483`, provide the required real session cookies or use `hot_search`.

#### Can I scrape public Douyin data legally?

The Actor retrieves Douyin data from its public hot-search source and other Douyin endpoints. Whether a use is legal or allowed depends on the buyer’s use case, applicable law, and the source’s terms; this Actor provides no legal guarantee.

### Related actors

- [Bilibili Video & Search Scraper](https://apify.com/bovi/bilibili-scraper) — related video and search collection for Bilibili.
- [Bluesky Scraper — Posts, Profiles & Followers](https://apify.com/bovi/bluesky-scraper) — related social-media collection for posts, profiles, and followers.
- [Facebook Comments Scraper](https://apify.com/bovi/facebook-comments-scraper) — related comment collection for Facebook content.

# Actor input Schema

## `mode` (type: `string`):

Scraping mode. 'hot_search' = Douyin trending topics (PUBLIC, no login). 'search'/'user_videos'/'comments'/'video_detail' require real login cookies (degraded as of 2026).

## `keywords` (type: `array`):

Keywords to search for. Used in mode=search. Example: \['美食', '探店', '旅游']. Each keyword runs a separate search up to maxItems results.

## `sec_user_ids` (type: `array`):

Douyin sec_user_id strings for user video mode. The sec_user_id is found in the Douyin user profile URL or API responses. Example: \['MS4wLjABAAAA...'].

## `aweme_ids` (type: `array`):

Douyin video IDs (aweme_id) for comments or video_detail mode. Example: \['7345492945006595379']. Find these in video URLs or previous search results.

## `maxItems` (type: `integer`):

Maximum number of videos to return per keyword or user. Default: 50. In comments mode, use maxComments instead.

## `maxComments` (type: `integer`):

Maximum number of comments to return per video (mode=comments only). Default: 50.

## `msToken` (type: `string`):

Optional: Douyin msToken cookie value from a real browser session. Improves success rate significantly. Get it from browser DevTools → Application → Cookies → www.douyin.com. Valid for days to weeks.

## `ttwid` (type: `string`):

Optional: Douyin ttwid cookie value from a real browser session (same source as msToken). Format: '1|hash|timestamp'.

## `svWebId` (type: `string`):

Optional: Douyin s_v_web_id cookie (device ID). Format: 'verify_XXXXXXXXXXXXXXXX'.

## `proxyConfiguration` (type: `object`):

REQUIRED for reliable access. Douyin blocks datacenter IPs. Use Apify RESIDENTIAL proxy with countryCode=CN. Without proxy, most requests will be blocked or captcha'd.

## Actor input object example

```json
{
  "mode": "hot_search",
  "keywords": [
    "美食"
  ],
  "maxItems": 50,
  "maxComments": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing Douyin Scraper records (rank, word, hot_value, view_count, video_count, discuss_video_count, event_time, sentence_id, scraped_at, parse_confidence).

# 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 = {
    "mode": "hot_search",
    "keywords": [
        "美食"
    ],
    "maxItems": 50,
    "maxComments": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "CN"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/douyin-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 = {
    "mode": "hot_search",
    "keywords": ["美食"],
    "maxItems": 50,
    "maxComments": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "CN",
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "mode": "hot_search",
  "keywords": [
    "美食"
  ],
  "maxItems": 50,
  "maxComments": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CN"
  }
}' |
apify call bovi/douyin-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/douyin-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vUaRrwcMxn3zfHUcK/builds/Pvdj6t9A3jJvaS6kY/openapi.json
