# TikTok Profile Scraper (Pay Per Result) (`xmolodtsov/tiktok-profile-scraper`) Actor

Scrape TikTok profiles by username: followers, bio, bio link, verified badge, TikTok Shop seller flag and category, avatar, plus latest posts with full metadata. No proxies needed, explicit not-found entries, batch up to 1000 handles. Compatible output with popular profile scrapers.

- **URL**: https://apify.com/xmolodtsov/tiktok-profile-scraper.md
- **Developed by:** [Yevhenii Molodtsov](https://apify.com/xmolodtsov) (community)
- **Categories:** Social media, Lead generation, Videos
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.75 / 1,000 tiktok profile results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## TikTok Profile Scraper (Pay Per Result)

Scrape TikTok profiles by username and get the complete author block — followers, bio,
bio link, verified badge, **TikTok Shop seller flag and seller category**, avatar, account
region — plus the latest posts with full metadata (stats, music, hashtags, mentions,
subtitles, CDN URLs). No proxy setup needed. You pay only per result.

### Why this scraper

- 💰 **Pay per result** — a fraction of the price of comparable profile scrapers.
- 🔁 **Drop-in compatible input & output** with the popular TikTok profile scrapers:
  `profiles`, `resultsPerPage`, download flags — and the same `authorMeta` item shape.
- 🛍️ **Commerce fields included**: `authorMeta.ttSeller` and
  `authorMeta.commerceUserInfo.category` distinguish an actual TikTok Shop store from a
  creator who merely sells something.
- 📇 **One item per requested handle — guaranteed.** Unresolvable handles produce an
  explicit `{"input": "...", "error": "not_found"}` item instead of a silently missing row.
- 📦 **Batching**: up to 1000 handles per run.
- 🪶 **Profile-only mode**: set `resultsPerPage: 0` to skip posts entirely and get one
  compact item per handle with just the author block — the cheapest and fastest way to
  bulk-resolve profile metadata.

### Input

```json
{
    "profiles": ["apifyoffice", "another_handle"],
    "resultsPerPage": 1
}
```

- `profiles` — usernames without `@` (bare handles, `@handle`, and full profile URLs are
  all accepted). Up to 1000 per run.
- `resultsPerPage` — latest posts per profile (each post is one paid result). `0` =
  profile-only mode.
- `excludePinnedPosts`, `oldestPostDate` — optional post filters.
- `shouldDownload*` flags are accepted for compatibility but are a **no-op**: media is
  never downloaded; TikTok CDN URLs are always returned instead. That is what keeps the
  per-result price low.

### Output

One dataset item per post, with the author block nested under `authorMeta`:

```json
{
    "id": "7623273873403809054",
    "text": "Post caption ...",
    "createTimeISO": "2026-03-31T04:36:16.000Z",
    "authorMeta": {
        "id": "6809214858661659653",
        "name": "lilianalazarin",
        "profileUrl": "https://www.tiktok.com/@lilianalazarin",
        "nickName": "Liliana Valeria",
        "verified": false,
        "signature": "dental • fitness • travel ...",
        "bioLink": "https://beacons.ai/lilianalazarin",
        "avatar": "https://p16-common-sign.tiktokcdn-us.com/...",
        "commerceUserInfo": { "commerceUser": false },
        "privateAccount": false,
        "region": null,
        "ttSeller": false,
        "following": 630,
        "friends": 48,
        "fans": 43700,
        "heart": 1600000,
        "video": 2558
    },
    "musicMeta": { "musicName": "original sound", "musicId": "..." },
    "videoMeta": { "height": 1280, "width": 720, "duration": 117, "coverUrl": "..." },
    "diggCount": 3156,
    "playCount": 37600,
    "hashtags": [{ "name": "higienistadental" }],
    "isPinned": true,
    "input": "lilianalazarin",
    "fromProfileSection": "videos"
}
```

Unresolvable handles produce an explicit error item:

```json
{
    "input": "deleted_user_123",
    "error": "not_found",
    "errorDescription": "Profile @deleted_user_123 not found — deleted or never existed."
}
```

Private accounts and profiles with zero posts still return one item with the full
`authorMeta` block (posts simply aren't included).

### Run status semantics

- The run finishes **SUCCEEDED** when the batch was processed, including handles that
  turned out not to exist (those get explicit error items).
- The run **FAILS** when a significant share of handles could not be fetched for
  technical reasons — so an automated caller can safely retry on non-SUCCEEDED statuses
  without ever consuming a half-empty dataset.

### Notes

- `authorMeta.region` is returned on a best-effort basis (TikTok does not always expose
  it); all other author fields are populated whenever the profile resolves.
- Posts are returned newest-first. `profileScrapeSections` other than `videos` are not
  supported.

# Actor input Schema

## `profiles` (type: `array`):

TikTok usernames to scrape, without the <code>@</code> (bare handles, <code>@handle</code> and full profile URLs are all accepted). Batch many handles into one run for the best cost efficiency — up to 1000 per run.

## `resultsPerPage` (type: `integer`):

How many latest posts to return per profile. Each post is one paid result and carries the full author block (<code>authorMeta</code>).<br><br><strong>Set to 0 for profile-only mode:</strong> one compact item per handle with just the author block — the cheapest way to get profile metadata.

## `profileScrapeSections` (type: `array`):

Which profile sections to scrape. Only <code>videos</code> is supported.

## `profileSorting` (type: `string`):

Order of returned posts. Posts are returned newest-first (<code>latest</code>).

## `excludePinnedPosts` (type: `boolean`):

If enabled, pinned posts are filtered out of the results.

## `oldestPostDate` (type: `string`):

Only return posts created on/after this date (ISO format, e.g. <code>2024-01-01</code>).

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

Accepted for input compatibility, but this actor never downloads media — it returns TikTok CDN URLs instead, which is what keeps the per-result price low.

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

Accepted for compatibility — media is never downloaded, CDN URLs are returned.

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

Accepted for compatibility — media is never downloaded, CDN URLs are returned.

## `shouldDownloadAvatars` (type: `boolean`):

Accepted for compatibility — media is never downloaded, CDN URLs are returned.

## `shouldDownloadMusicCovers` (type: `boolean`):

Accepted for compatibility — media is never downloaded, CDN URLs are returned.

## `downloadSubtitlesOptions` (type: `string`):

Accepted for compatibility — subtitle CDN links are always included in <code>videoMeta.subtitleLinks</code> when TikTok provides them.

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

Optional override. By default the actor uses its own built-in proxy pool — you don't need to configure anything.

## Actor input object example

```json
{
  "profiles": [
    "apifyoffice"
  ],
  "resultsPerPage": 1,
  "profileScrapeSections": [
    "videos"
  ],
  "profileSorting": "latest",
  "excludePinnedPosts": false,
  "shouldDownloadVideos": false,
  "shouldDownloadCovers": false,
  "shouldDownloadSlideshowImages": false,
  "shouldDownloadAvatars": false,
  "shouldDownloadMusicCovers": false,
  "downloadSubtitlesOptions": "NEVER_DOWNLOAD_SUBTITLES"
}
```

# 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 = {
    "profiles": [
        "apifyoffice"
    ],
    "resultsPerPage": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("xmolodtsov/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 = {
    "profiles": ["apifyoffice"],
    "resultsPerPage": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("xmolodtsov/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 '{
  "profiles": [
    "apifyoffice"
  ],
  "resultsPerPage": 1
}' |
apify call xmolodtsov/tiktok-profile-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/pcDgbS5iggjkvxZoN/builds/zCBlYhi51LGuSG8eJ/openapi.json
