# Douyin Profile Scraper (`happy_b/douyin-profile-scraper`) Actor

Extract Douyin profile data with exact follower, following, video, and like counts, verification, stable IDs, and public profile links. Optionally collect public posts with engagement, media, music, and hashtags in a separate typed dataset.

- **URL**: https://apify.com/happy\_b/douyin-profile-scraper.md
- **Developed by:** [Happy B](https://apify.com/happy_b) (community)
- **Categories:** Social media, Videos
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.99 / 1,000 profiles

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

### What is Douyin Profile Scraper?

Douyin Profile Scraper extracts **public Douyin (抖音 / Chinese TikTok) profile data** from profile URLs, share links, or stable `sec_user_id` values. It can also collect each account's public post history with engagement, media, music, hashtag, and embedded creator fields.

Every successful account is written to a typed **Profiles** dataset. When **Include posts** is enabled, posts are written to a separate typed **Posts** dataset, so exports never mix unrelated row shapes.

No Douyin login, cookie, browser, or proxy configuration is required from you.

### Why use this Douyin profile scraper?

- **A profile is valuable on its own.** Get up to 32 typed public profile fields without paying for or waiting on post history.
- **Posts are strictly optional.** Enable them only when you need the 54-field content, engagement, media, music, hashtag, and creator context contract.
- **Get exact numbers.** Followers, likes, posts, plays, comments, shares, collections, and downloads are integers—not shortened values such as `1.2M`.
- **Keep large IDs intact.** Account and post IDs are strings, preventing precision loss in JavaScript and spreadsheet pipelines.
- **Use clean output tabs.** Profiles and Posts are separate typed datasets, while each post embeds flat profile context so it works independently downstream.
- **Paste what Douyin gives you.** Use a profile URL, a share URL, a bare `sec_user_id`, or mobile share text containing one Douyin link.

### How to scrape a Douyin profile

1. Add one or more Douyin profile URLs, share links, or `sec_user_id` values.
2. Leave **Include posts** off for profile-only research.
3. Turn it on to collect public posts and choose a maximum per profile.
4. Run the Actor and open the Profiles or Posts output.

#### Input example

```json
{
  "profileUrls": [
    "https://www.douyin.com/user/MS4wLjABAAAA..."
  ],
  "includePosts": true,
  "maxPostsPerProfile": 100
}
```

Duplicate inputs are removed before scraping.

### Accepted profile inputs

- Full profile URL: `https://www.douyin.com/user/MS4wLjAB...`
- Profile share URL: `https://v.douyin.com/...`
- Bare `sec_user_id`: `MS4wLjAB...`
- Douyin mobile share text containing exactly one supported HTTPS profile/share URL

Only HTTPS links on Douyin and iesdouyin domains are accepted. Unrelated links fail before any paid profile request.

### What profile data can I extract?

| Field | Description |
|---|---|
| `sourceProfileInput` | Normalized input that produced the row |
| `uid`, `secUid`, `shortId` | Numeric, stable encoded, and short account IDs |
| `uniqueId` | Public Douyin ID or handle |
| `nickname`, `signature` | Display name and public biography |
| `avatarThumbUrl`, `avatarMediumUrl`, `avatarLargerUrl` | Observed avatar variants |
| `avatarUrl`, `profileUrl` | Derived preferred avatar and canonical profile link |
| `followerCount`, `followingCount` | Counts reported by Douyin |
| `awemeCount`, `totalFavorited` | Published posts and total likes received |
| `verified`, `enterpriseVerifyReason`, `customVerify`, `verificationType` | Observed verification values |
| `privateAccount`, `commerceUser` | Normalized account flags |
| `gender`, `region`, `location`, `language` | Observed profile attributes when available |
| `insId`, `twitterId`, `youtubeChannelId` | Linked account identifiers when published |
| `liveStatus` | Public live-broadcast state when available |
| `scrapeTimestamp` | UTC time when the row was produced |

Fields Douyin does not publish for an account are omitted.

The output follows the published Profiles dataset schema. The example below is illustrative and does not represent a specific person or captured live row.

#### Profile output example

```json
{
  "sourceProfileInput": "MS4wLjABAAAA...",
  "uid": "68141954464",
  "secUid": "MS4wLjABAAAA...",
  "uniqueId": "example_creator",
  "nickname": "示例用户",
  "signature": "公开简介",
  "followerCount": 125430,
  "followingCount": 318,
  "awemeCount": 242,
  "totalFavorited": 3870000,
  "verified": false,
  "profileUrl": "https://www.douyin.com/user/MS4wLjABAAAA...",
  "scrapeTimestamp": "2026-08-26T12:00:00.000Z"
}
```

### Optional public post history

Each post row can include:

- Post ID, caption, canonical link, and publication time
- Play, like, comment, share, collection, and download counters as reported by Douyin
- Video, cover, or slideshow image URLs when available
- Media type, dimensions, and duration
- Music ID, title, author, URL, and hashtags when available
- The profile's IDs, name, bio, counters, verification, region, location, and language embedded as flat `profile...` fields
- `sourceProfileInput` and `scrapeTimestamp`

Embedding creator fields makes every post row usable on its own in a warehouse or spreadsheet.

#### Post output example

```json
{
  "awemeId": "7530000000000000000",
  "description": "示例作品",
  "createTimeIso": "2026-08-20T09:30:00.000Z",
  "playCount": 928430,
  "likeCount": 52800,
  "commentCount": 1640,
  "shareCount": 3900,
  "collectCount": 7200,
  "downloadCount": 120,
  "mediaTypeName": "video",
  "videoUrl": "https://example.com/video.mp4",
  "profileUniqueId": "example_creator",
  "profileFollowerCount": 125430,
  "sourceProfileInput": "MS4wLjABAAAA...",
  "scrapeTimestamp": "2026-08-26T12:00:00.000Z"
}
```

Media URLs can be signed or temporary. Download media you are entitled to retain soon after the run.

Douyin can report zero when a counter is unavailable. The Actor preserves the reported value and does not estimate a replacement.

### Input reference

| Parameter | Type | Default | Limits | Description |
|---|---|---:|---:|---|
| `profileUrls` | string\[] | required | 1–100 | Profile URLs, share links, or `sec_user_id` values |
| `includePosts` | boolean | `false` | — | Collect public posts in the Posts dataset |
| `maxPostsPerProfile` | integer | `50` | 1–5,000 | Maximum posts per profile |

### Reliable results and billing

Interrupted runs can continue without duplicating profiles or posts already delivered. Charges track rows visible in the Profiles and Posts datasets. If a result cannot be validated, the run reports a clear sanitized error instead of returning questionable data.

### How much does scraping Douyin profiles cost?

Profiles and posts are priced separately. You pay once for each returned profile and once for each returned post. Enabling posts does not change the profile price, and interrupted runs do not charge the same delivered row twice.

#### Profile result

| Apify tier | Per profile | Per 1,000 profiles |
|---|---:|---:|
| Free | $0.00799 | $7.99 |
| Bronze | $0.00599 | $5.99 |
| Silver | $0.00549 | $5.49 |
| Gold | $0.00499 | $4.99 |

#### Post result

| Apify tier | Per post | Per 1,000 posts |
|---|---:|---:|
| Free | $0.00799 | $7.99 |
| Bronze | $0.00599 | $5.99 |
| Silver | $0.00549 | $5.49 |
| Gold | $0.00499 | $4.99 |

An additional $0.001 run-start charge applies.

Platinum and Diamond users receive the listed Gold price.

| Example on the Free tier | Estimated cost |
|---|---:|
| 10 profiles only | $0.081 |
| 1 profile + 50 posts | $0.408 |
| 10 profiles + 50 posts each | $4.076 |

Examples include the run-start charge. You are charged only for returned rows, and the Actor respects the run's maximum charge.

### Common use cases

- Influencer and competitor profile audits
- Exact audience and publishing snapshots
- Public creator-content catalogs
- Engagement benchmarking
- Scheduled monitoring and archival workflows
- Enriching creator IDs returned by the Douyin Creator Scraper

### Integrations

Use Apify Schedules and Webhooks for monitoring, or send Profiles and Posts to Make, Zapier, Google Sheets, Slack, a warehouse, or your own API client. Export formats include JSON, CSV, Excel, XML, HTML, and JSONL.

### FAQ

#### Are private profiles supported?

Publicly visible profile fields may still be available. Private posts are not returned.

#### Why do I always get a profile row when posts are enabled?

The profile lookup is a useful, separately priced result and lives in the Profiles dataset. Posts are optional add-on results in the Posts dataset.

#### What happens when a profile has no public posts?

The profile row is still returned. The Posts dataset contains no row for that account, so there is no post charge.

#### Can I schedule profile monitoring?

Yes. Save an Actor task, attach a schedule, and compare the reported counters and `scrapeTimestamp` values across datasets.

### Related Douyin Actors

| Actor | Best for |
|---|---|
| [Douyin Creator Scraper](https://apify.com/happy_b/douyin-creator-scraper) | Find creators when you do not yet know their profile URL or ID |
| [Douyin Trend Scraper](https://apify.com/happy_b/douyin-trend-scraper) | Export current topics or compare keyword popularity over time |

### Legal and personal data

This Actor extracts publicly available data, some of which can be personal data. You are responsible for your lawful basis, notices, retention, security, outreach, profiling, copyright handling, and data-subject rights. Review Douyin's [User Service Agreement](https://www.douyin.com/agreements/?id=6773906068725565448), [Privacy Policy](https://www.douyin.com/privacy/), and all laws applicable to your use case.

### Support

For a bug or feature request, [open an Apify issue](https://apify.com/happy_b/douyin-profile-scraper/issues/open). Include the run ID, affected profile input, expected behavior, and input with sensitive values removed.

# Actor input Schema

## `profileUrls` (type: `array`):

Douyin profile URLs, v.douyin.com share links, stable sec\_user\_id values, or pasted mobile share text containing exactly one supported HTTPS Douyin link.

## `includePosts` (type: `boolean`):

Fetch public posts with engagement, media, music, hashtag, and embedded profile fields. Every stored post is separately charged at the documented post-item price.

## `maxPostsPerProfile` (type: `integer`):

Maximum number of posts returned for each profile when Include posts is enabled.

## Actor input object example

```json
{
  "profileUrls": [
    "https://www.douyin.com/user/MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y"
  ],
  "includePosts": false,
  "maxPostsPerProfile": 50
}
```

# Actor output Schema

## `profiles` (type: `string`):

One normalized public profile row for every successfully resolved input.

## `posts` (type: `string`):

Optional public post rows with embedded profile fields.

## `metadata` (type: `string`):

Completion state, profile and post counts, and sanitized errors.

# 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 = {
    "profileUrls": [
        "https://www.douyin.com/user/MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("happy_b/douyin-profile-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 = { "profileUrls": ["https://www.douyin.com/user/MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y"] }

# Run the Actor and wait for it to finish
run = client.actor("happy_b/douyin-profile-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 '{
  "profileUrls": [
    "https://www.douyin.com/user/MS4wLjABAAAAW9FWcqS7RdQAWPd2AA5fL_ilmqsIFUCQ_Iym6Yh9_cUa6ZRqVLjVQSUjlHrfXY1Y"
  ]
}' |
apify call happy_b/douyin-profile-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,happy_b/douyin-profile-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/AL07AUflfwvLZPWdk/builds/emyL64Y0ik2N5u2vU/openapi.json
