# TikTok Profile Scraper (`tokfluence/tiktok-profile-scraper`) Actor

Scrape recent posts from TikTok profiles by username or profile URL. One row per post with caption, views, likes, comments, shares, sound and author details, in Clockworks TikTok Profile Scraper field names.

- **URL**: https://apify.com/tokfluence/tiktok-profile-scraper.md
- **Developed by:** [Tokfluence Tiktok API](https://apify.com/tokfluence) (community)
- **Categories:** Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.24 / 1,000 results

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

## TikTok Profile Scraper

Give it TikTok usernames or profile URLs and it returns each profile's recent posts, one row per post with the creator's details embedded. Rows use the same field names as the Clockworks TikTok Profile Scraper (`authorMeta`, `musicMeta`, `videoMeta`, `playCount`, `diggCount`, ...), so a pipeline built on that actor can read the fields we fill. The fields we cannot fill are null, and the list is below.

### What it returns

One Clockworks video row per post, with the author embedded in each row, as Clockworks Profile Scraper does. There is no separate profile row. Filled when we hold them:

- the post: `id`, `text`, `textLanguage`, `createTime`, `createTimeISO`, `webVideoUrl`, `isAd`, `hashtags`, `mentions`, `detailedMentions`, `effectStickers`, `input`, `fromProfileSection` (always `videos`) and `isStory` (always `false`)
- the counters: `playCount`, `diggCount`, `commentCount`, `shareCount`, `collectCount`, `repostCount`
- `videoMeta`: `height`, `width`, `duration`, `definition`, `format`, `coverUrl` (our stored copy of the cover when we have one, TikTok's signed cover otherwise), `subtitleLinks`
- `musicMeta`: `musicId`, `musicName`, `musicAuthor`, `musicOriginal`
- `authorMeta`: `id`, `name`, `nickName`, `profileUrl`, `avatar`, `signature`, `bioLink`, `fans`, `following`, `heart`, `video`, `friends`, `commerceUserInfo`
- `locationMeta` when the post has a location tag; `hasTikTokShopProduct` when we have checked the post for a Shop product tag

Fields Tokfluence adds that Clockworks does not have sit under a `tokfluence` object:

- `tokfluence.engagement_rate`: the creator's engagement rate as Tokfluence stores it, worked out from the median likes, comments, shares and views of their recent posts, passed through unchanged
- `tokfluence.has_email`: whether Tokfluence holds a contact email for the creator; the address itself is not in the output
- `tokfluence.last_analyzed_at`: when Tokfluence last scraped this profile, so you can judge how fresh the author details are
- `tokfluence.post_scraped_at`: when Tokfluence last scraped this post, so you can judge how fresh its counters are
- `tokfluence.posts_per_week`, `tokfluence.average_views_per_video`, `tokfluence.is_brand`
- `tokfluence.is_branded_content` and `tokfluence.ad_disclosure`: whether the post reads as paid or branded content, and how it discloses it
- `tokfluence.region`: the creator's region as Tokfluence stores it

### How many posts per profile

This is where we differ most from Clockworks, which pages back through a whole profile. We do not.

- **Stored posts: at most 15 per creator.** Tokfluence keeps the 15 newest posts of each creator it tracks. Anything served from storage, in `database` mode or in `auto` mode when our copy is fresh, stops at 15 however high you set **Max posts per profile**.
- **Live scrape: one page.** A live scrape reads the posts TikTok loads on the profile's first page. TikTok decides how many that is; we do not page further back. The live answer is the newest posts we hold for the creator right after that scrape.
- **Creators under 1,000 followers: no posts.** Tokfluence does not collect posts for them, live or stored. When such a creator is scraped live, the run's status message says so by name; when served from storage, they are reported as not found, because we hold no posts for them.
- **Sorting.** Latest is the default. Popular ranks the posts we fetched (the stored 15 or the live first page) by views; it is not the profile's all-time most popular posts as on Clockworks. Oldest is not offered, because we cannot page back to a profile's first posts.
- **Date filters** (`oldestPostDateUnified`, `newestPostDate`) are applied to the posts we fetched, so they cannot reach further back than the 15 or the first page.

### Inputs

- `profiles` (required): usernames, `@handles` or profile URLs. A TikTok numeric user id is read as a username, so it will not find the account.
- `resultsPerPage`: posts per profile, default 30.
- `profileSorting`: `latest` (default when empty) or `popular`, as above.
- `oldestPostDateUnified`: a date (`2026-09-01`), a span (`7 days`), or a number of days where `1` is today only.
- `newestPostDate`: a date, inclusive of that whole day in UTC.
- `maxResults`: a ceiling on rows across all profiles, default 1000.
- `mode`, under Advanced: see below.

Not supported: reposts and stories, excluding pinned posts, comments, followers and following, video and cover downloads, and transcription. Use the other Tokfluence actors for comments and transcripts.

### Fresh or fast: the Mode setting

Under **Advanced**, `mode` trades freshness for speed:

- `auto` (default): serves the posts Tokfluence already stores when they were scraped in the last 7 days, and scrapes TikTok live for the rest. A profile served from storage returns at most 15 posts.
- `database`: fastest. Never scrapes, so profiles we do not already hold are missing from the results, at most 15 posts come back per profile, and they are as old as our last visit (check `tokfluence.post_scraped_at`).
- `live`: always scrapes TikTok now and reads the profile's first page. Freshest, and slower.

Live requests run on Tokfluence's shared scraping workers, one profile after another, and wait behind other live requests, so a large live run can take minutes. The actor sends up to 50 profiles per request, one request after another, and writes rows only once every request has answered.

If a live scrape outlasts the run's timeout, the run fails with the request id and delivers no rows, including for profiles that had already finished. The scrape keeps going and is stored when it finishes, so a `database` run shortly afterwards returns those posts without scraping again, at most 15 per creator.

### Fields that can be null

This actor never fills a gap itself: when we do not have a field it is `null`, not `0`, `false` or an empty string. Always null today:

- `authorMeta.region`: our stored region is in `tokfluence.region` instead.
- `authorMeta.verified`, `authorMeta.privateAccount`, `authorMeta.digg`, `authorMeta.isUnderAge18`, `authorMeta.roomId`, `authorMeta.createTime`, `authorMeta.originalAvatarUrl`, `authorMeta.followDatasetUrl`, `authorMeta.hasActiveStory`
- `isPinned`, `isSponsored`, `isSlideshow`, `isMuted`, `locationCreated`: we do not store these per post
- `mediaUrls`, `slideshowImageLinks`, `videoMeta.transcriptionLink`, `videoMeta.originalDownloadAddr`, and `downloadLink` inside `videoMeta.subtitleLinks`: we do not copy files into a key-value store. The TikTok subtitle URL is in `tiktokLink` and is signed, so it stops working some time after the scrape.
- `hashtags[].title` and `hashtags[].cover`, `detailedMentions[].nickName` and `detailedMentions[].postUrl`, `effectStickers[].stickerStats.useCount`
- `musicMeta.coverMediumUrl`, `musicMeta.originalCoverMediumUrl`, `musicMeta.playUrl`, `musicMeta.musicAlbum`
- `commentsDatasetUrl`, `note`, `url`, `error`, `errorCode`, `invalidUrls`, `submittedVideoUrl`, `searchQuery`, `searchHashtag`, `searchMusic`: Clockworks fills these for add-ons, error rows and other inputs this actor does not have

Often null:

- `authorMeta.commerceUserInfo.category` and `authorMeta.ttSeller`: null when we do not hold them
- `hasTikTokShopProduct`: null means we have not checked the post, not "no product"
- `videoMeta.downloadAddr`, `videoMeta.originalCoverUrl`
- `musicMeta` as a whole is null for a post with no sound, and `locationMeta` for a post with no location tag
- If a creator's profile cannot be loaded, their posts still come back with `authorMeta.id`, `name`, `profileUrl` and the follower counts the post carries; the other author fields and the `tokfluence` creator fields are null

Clockworks writes an error row for a profile that is private, empty or not found. We do not, because every row is a paid result. The run's status message names those profiles instead.

### Zero or short results

When a run returns nothing, or fewer posts than the profiles times **Max posts per profile**, it still succeeds, but it logs a warning and sets the run's status message to the likely cause: profiles we could not find, private accounts, creators under 1,000 followers, the 15 stored posts per creator, the live first page, or the date filter. Fix the one it names and run again.

The actor uses one Tokfluence account for every run. If that account is out of API credits, or Tokfluence's scrape service is down, the run fails with a message saying so. You are charged only for rows already in the dataset.

### What Tokfluence keeps from a run

Tokfluence logs every request the actor makes: the usernames, the mode, where each row was served from, and a reference made of a one-way hash of your Apify user id plus the run id. Every TikTok handle and hashtag in your inputs and in the returned rows is recorded as a candidate for Tokfluence's creator discovery. Every profile scraped live is stored in Tokfluence like any other scrape, and later runs, anyone's, can be served that stored copy.

### Memory

The actor defaults to 256 MB and allows up to 512 MB. It makes one API call per 50 profiles for the posts and one per 100 for the creators' details, holds the posts in memory until those calls finish, then writes rows to the dataset in batches of 100.

### Pricing

PLACEHOLDER (Daniel): pay per result, one `result` event per dataset row. Price to be set in Console at publish.

If your plan's remaining budget covers fewer rows than you asked for, the actor collects up to that ceiling, says so in the log, and stops cleanly rather than returning a silently short list.

### Notes

Data comes from public TikTok pages, scraped and stored by Tokfluence. You are the data controller for anything you export; follow GDPR and any local rules that apply to you. More at [Tokfluence](https://tokfluence.com).

# Actor input Schema

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

TikTok usernames, @handles or profile URLs (https://www.tiktok.com/@name). User ids are not accepted. Use Bulk edit to paste a list.

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

How many posts to return per profile, newest first. Tokfluence stores at most 15 recent posts per creator, and a live scrape reads the one page of posts TikTok loads on the profile. Asking for more returns what there is.

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

Empty means Latest. Popular ranks the posts we fetched (the stored 15, or the first page when scraped live) by views; it is not the profile's all-time top posts. Oldest is not offered: Tokfluence does not page back that far.

## `oldestPostDateUnified` (type: `string`):

Optional. A date (2026-09-01), a span (7 days), or a number of days where 1 is today only. Applied to the posts we fetch, so it cannot reach past the stored 15 or the live first page.

## `newestPostDate` (type: `string`):

Optional. Only posts published on or before this date (2026-09-30), inclusive of the whole day in UTC.

## `maxResults` (type: `integer`):

Stops once this many rows are in the dataset, across all profiles. Each row is one post and one result.

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

Trades freshness for speed. Auto serves what Tokfluence already stores when it is fresh enough (up to 15 recent posts per creator) and scrapes live for the rest. Database only is fastest and never scrapes, so anything we do not already hold is missing from the results. Live always scrapes TikTok now and reads the profile's first page of posts: freshest, and slower.

## Actor input object example

```json
{
  "profiles": [
    "tiktok"
  ],
  "resultsPerPage": 30,
  "maxResults": 1000,
  "mode": "auto"
}
```

# Actor output Schema

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

One row per post, in Clockworks Profile Scraper field names, author embedded.

# 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": [
        "tiktok"
    ]
};

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tokfluence/tiktok-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/YKnlPAvExmeTAruVL/builds/EV3ecuuk8r9iIjUUy/openapi.json
