# Tiktok Profile Scraper (Include Posts Account) (`xtracto/tiktok-profile-scraper`) Actor

Get a TikTok user's full profile (followers, likes, bio, avatar, verification, secUid) plus their last N posts in a single call. HTTP-only, no login, no cookies. Multi-strategy fallback chain (SSR → signed API → embed) means even WAF-blocked profiles return up to 10 recent posts

- **URL**: https://apify.com/xtracto/tiktok-profile-scraper.md
- **Developed by:** [Xtractoo](https://apify.com/xtracto) (community)
- **Categories:** Social media
- **Stats:** 5 total users, 3 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.20 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## 🎵 TikTok Profile + Recent Posts Scraper

Scrape any public TikTok user's **profile information** and their **most recent posts** in a single call. One input (a username), one combined output.

> Previously two separate actors — `tiktok-profile-scraper` and `tiktok-posts-scraper` — now merged into this one. Same input, one output dict containing both `profile` and `posts`.

### ✨ Why Use This Actor?

- ⚡ **Fast** — typically returns in **5–30 seconds** for profile + 10 posts
- 💰 **Cheap** — HTTP-only, low memory, no browser overhead
- 🪶 **Lightweight** — no Playwright, no Chromium download, ~256 MB RAM
- ✅ **No login required** — fully anonymous, no cookies, no session tokens
- 🛡️ **Multi-strategy resilience** — 4-step fallback chain; even when TikTok's WAF blocks the profile page entirely, the actor still returns up to 10 posts via the public embed endpoint
- 🧩 **One call, two datasets worth of data** — profile metadata + recent video list

### 🎯 Use Cases

- **Influencer research** — verify follower counts, engagement, and recent content style in one request
- **Competitor monitoring** — snapshot a competitor's profile + last 10 uploads on a schedule
- **Lead generation** — enrich creator lists with profile stats and post examples
- **Content auditing** — pull a creator's recent video metadata for review/categorisation
- **Brand monitoring** — track owned/sponsored accounts' latest posts
- **Academic research** — collect public creator data + post samples for analysis
- **CRM enrichment** — attach TikTok handle, follower count, and recent activity to contact records

### 📥 Input

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `username` | string | Yes | — | TikTok username without `@`. Example: `charlidamelio` |
| `maxPosts` | integer | No | `10` | Number of most recent posts to attach. Set `0` to skip post fetching (profile only). |

#### Example input

```json
{
    "username": "tiktok",
    "maxPosts": 10
}
````

### 📤 Output

A **single dataset record** containing both the profile info and the recent post list:

```json
{
  "profile": { /* raw TikTok userInfo */ },
  "posts":   [ /* raw itemStruct objects, newest first */ ],
  "_input":  "tiktok"
}
```

#### `profile` object

The raw TikTok user info extracted from the SSR HTML (`__UNIVERSAL_DATA_FOR_REHYDRATION__` → `webapp.user-detail.userInfo`) — or a partial reconstruction from the user-search API when the profile page is WAF-blocked.

Key nested fields:

- **`user`** — `id`, `uniqueId`, `nickname`, `avatarLarger/Medium/Thumb`, `signature`, `verified`, `secUid`, `privateAccount`, `region`, `bioLink`, `commerceUserInfo`, `roomId`
- **`stats`** / **`statsV2`** — `followerCount`, `followingCount`, `heartCount`, `videoCount`, `diggCount`, `friendCount`

#### `posts` array

Each post is a raw TikTok video item (the same shape returned by TikTok's web `/api/post/item_list/` endpoint, the SSR `webapp.user-post.itemList`, or the public `/embed/@username` page — depending on which strategy succeeded).

Two metadata fields are added by the scraper:

| Field | Type | Description |
|-------|------|-------------|
| `_input` | string | The username used for the request |
| `_source` | string | Which fetch path returned this item: `"ssr"`, `"api"`, or `"embed"` |

Note: `_source: "embed"` items have a **reduced field set** (no `authorStats`, no `downloadAddr`, video dimensions may be 0) because the embed endpoint is intentionally minimal. Use this as a signal of how much fidelity you have for downstream processing.

#### Example output (abridged)

```json
{
  "_input": "tiktok",
  "profile": {
    "user": {
      "id": "107955",
      "uniqueId": "tiktok",
      "nickname": "TikTok",
      "signature": "One TikTok can make a big impact",
      "verified": true,
      "secUid": "MS4wLjABAAAAv7iSuuXDJGDvJkmH_vz1qkDZYo1apxgzaxdBSeIuPiM",
      "bioLink": { "link": "linktr.ee/tiktok", "risk": 0 },
      "privateAccount": false
    },
    "stats": {
      "followerCount": 93600000,
      "followingCount": 3,
      "heartCount": 457000000,
      "videoCount": 1421
    }
  },
  "posts": [
    {
      "id": "7637896329779350814",
      "desc": "…",
      "createTime": 1762000000,
      "video": { "duration": 21, "cover": "https://…", "playAddr": "https://…" },
      "stats": { "playCount": 1234567, "diggCount": 89000, "commentCount": 1200, "shareCount": 450 },
      "_input": "tiktok",
      "_source": "embed"
    }
  ]
}
```

### 🛠️ How It Works (Strategy Chain)

The actor walks four progressively-more-fallback strategies. Each one that returns data contributes to the output; results are deduplicated by video ID across strategies. The chain stops early once `maxPosts` is hit.

| Step | Path | Yields | Bypasses |
|------|------|--------|----------|
| **S1** | SSR profile HTML at `/@username` | Profile info + secUid + first ~30 posts | TLS fingerprinting via Chrome impersonation |
| **S1b** | `/api/search/user/full/` (X-Bogus signed) | Profile (partial) + secUid | Triggered when S1 is WAF-blocked |
| **S2** | `/api/post/item_list/` (X-Bogus + X-Gnarly signed) | Paginated posts beyond the initial 30 | Multi-session rotation to push past X-Gnarly enforcement |
| **S3** | `/embed/@username` (FRONTITY state) | Up to ~10 posts (limited fields) | Always reachable — no signing, no WAF gate |

If every other path is blocked, **S3 still guarantees up to 10 recent posts** with the basic metadata needed for most use cases. That's why this actor reliably returns *something* for almost any public account, even from datacenter IPs that TikTok normally restricts.

### ⚙️ Technical Details

- **Engine**: HTTP-only — no Playwright, no Selenium, no headless browser
- **Anti-detection**: TLS fingerprint emulation via `curl_cffi` (Chrome 131 impersonation), X-Bogus + X-Gnarly request signing, msToken rotation
- **Auth**: Fully unauthenticated — no login, no user cookies
- **Docker image**: `apify/actor-python:3.12`
- **Memory**: ~256 MB RAM
- **Proxy**: Optional. Datacenter proxies usually work. If you hit the embed-only fallback often, try **Apify Datacenter** proxy group.

### ⚠️ Known Limits

- **Private accounts** return `privateAccount: true` in profile; their posts cannot be retrieved.
- **Posts past ~10** require either the SSR or signed API path to succeed. When only S3 (embed) delivers, the cap is ~10 regardless of `maxPosts`.
- **Region/language**: defaults to `en_US`. TikTok serves different content per region — use a proxy in the target country for region-accurate post lists.
- **Field consistency**: posts from different sources (`_source: ssr / api / embed`) have slightly different field sets. Normalise downstream if you need a uniform schema.

# Actor input Schema

## `username` (type: `string`):

Public TikTok username, without the leading @. Example: 'charlidamelio'. The actor will resolve full profile info plus this user's most recent posts.

## `maxPosts` (type: `integer`):

How many of the user's most recent posts to fetch alongside the profile. Default 10. Set 0 to skip posts entirely and return profile info only. When TikTok's WAF restricts the signed API on the run's IP, the actor falls back to the public /embed/@username page, which is capped at ~10 posts regardless of this setting.

## Actor input object example

```json
{
  "username": "tiktok",
  "maxPosts": 10
}
```

# 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 = {
    "username": "tiktok"
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/tiktok-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 = { "username": "tiktok" }

# Run the Actor and wait for it to finish
run = client.actor("xtracto/tiktok-profile-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 '{
  "username": "tiktok"
}' |
apify call xtracto/tiktok-profile-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Tiktok Profile Scraper (Include Posts Account)",
        "description": "Get a TikTok user's full profile (followers, likes, bio, avatar, verification, secUid) plus their last N posts in a single call. HTTP-only, no login, no cookies. Multi-strategy fallback chain (SSR → signed API → embed) means even WAF-blocked profiles return up to 10 recent posts",
        "version": "2.0",
        "x-build-id": "16DPdgr5qLUyzYmh9"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/xtracto~tiktok-profile-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-xtracto-tiktok-profile-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/xtracto~tiktok-profile-scraper/runs": {
            "post": {
                "operationId": "runs-sync-xtracto-tiktok-profile-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/xtracto~tiktok-profile-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-xtracto-tiktok-profile-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",
                "required": [
                    "username"
                ],
                "properties": {
                    "username": {
                        "title": "TikTok Username",
                        "type": "string",
                        "description": "Public TikTok username, without the leading @. Example: 'charlidamelio'. The actor will resolve full profile info plus this user's most recent posts."
                    },
                    "maxPosts": {
                        "title": "Max Recent Posts",
                        "minimum": 0,
                        "maximum": 200,
                        "type": "integer",
                        "description": "How many of the user's most recent posts to fetch alongside the profile. Default 10. Set 0 to skip posts entirely and return profile info only. When TikTok's WAF restricts the signed API on the run's IP, the actor falls back to the public /embed/@username page, which is capped at ~10 posts regardless of this setting.",
                        "default": 10
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
