# TikTok Profile & Video Scraper: Followers, Bio & Video Stats (`automatic/tiktok-profile-video-scraper`) Actor

Get public TikTok profiles with exact follower, following, like and video counts, bio, seller flags and creation date, plus up to 10 latest videos each with plays, likes, comments, shares and saves, or any video links you paste. Empty input runs a sample. $1.50 per 1,000 rows.

- **URL**: https://apify.com/automatic/tiktok-profile-video-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/automatic) (community)
- **Categories:** Social media, Videos
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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.

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 & Video Scraper

Get public TikTok profile and video data as clean rows. Give it usernames or profile links and each account comes back with its exact follower count, following, total likes, video count, bio, bio link, verified badge and creation date, plus up to 10 of its latest videos. Give it video links and each video comes back with plays, likes, comments, shares, saves, caption, hashtags, mentions, music, duration and author.

No TikTok account or login is needed. Only public data is returned: private accounts still return their profile row, but not their videos.

### Quick Start

```json
{
  "profiles": ["nike", "@khaby.lame", "https://www.tiktok.com/@nasa"],
  "latestVideos": 5,
  "videoUrls": [
    "https://www.tiktok.com/@nike/video/7698062113742310670"
  ],
  "maxItems": 100
}
```

This returns 3 profile rows, up to 15 latest-video rows and 1 video row. A video that appears both as a latest video and as a link is returned once.

### Use cases

- **Influencer research** — compare follower counts, total likes and posting volume across a list of creators, then read the plays, likes, comments, shares and saves of their latest videos in the same run.
- **Campaign tracking** — put the campaign's video links in `videoUrls` and re-run daily or weekly to follow plays, likes, comments, shares and saves on the same rows.
- **Brand and competitor monitoring** — watch the latest videos of brand and competitor accounts: what they posted, when, and how each one is doing.
- **Creator shortlists and lead lists** — bio links, business categories, seller flags, verified status and account creation dates for outreach, one row per account.
- **Trend research** — collect the latest videos from a set of accounts in a niche and rank them by plays per follower.

### Your first run

You do not have to fill the form to see the output. With no input the Actor reads the same profile and video the Console prefills (`nike` plus one of its videos) with three of its latest videos, so a complete sample arrives in seconds. The run summary carries `usedExample: true` and the run status says it was the example run, so it cannot be mistaken for your own data. Replace the prefilled values to collect your own accounts.

### Bulk input

`profiles` and `videoUrls` accept lists. In the Console, click **Bulk edit** in either field and paste one username, profile link, video link or video ID per line. Usernames with and without `@`, `tiktok.com` and `m.tiktok.com` profile links, full video links, `vm.tiktok.com` share links and bare numeric video IDs all work; duplicates are returned once. Long lists are fine: allowance is `maxItems` rows in total (up to 10,000) with up to 10 latest videos per profile.

### Worked costs

| What you collect | Rows | What you pay |
| --- | ---: | ---: |
| The first-run sample (1 profile, 3 latest videos, 1 video) | 5 | $0.0125 |
| 100 profiles, profile rows only (`latestVideos: 0`) | 100 | $0.155 |
| 100 profiles with 3 latest videos each | 400 | $0.605 |
| 1,000 videos | 1,000 | $1.505 |

One $0.005 run start plus $0.0015 per delivered row. Failed profiles and videos are not charged. The first-run sample takes about six seconds; each extra video is one more page.

### Input

| Input | Type | Default | Meaning |
| --- | --- | --- | --- |
| `profiles` | array | the sample profile | Usernames (`nike` or `@nike`) or profile links (`https://www.tiktok.com/@nike`). One row per profile. If both `profiles` and `videoUrls` are empty, the Actor collects the same profile and video the Console prefills (`nike`) and marks the run summary `usedExample: true`, so a first run still returns a sample. |
| `latestVideos` | integer | `0` | How many of each profile's latest videos to return, from 0 to 10. Each video is one extra row. |
| `videoUrls` | array | `[]` | Video links (`https://www.tiktok.com/@user/video/…`), short share links (`https://vm.tiktok.com/…`) or numeric video IDs. One row per video. |
| `maxItems` | integer | `100` | Total cap on rows (profiles plus videos) for the whole run. |
| `proxyConfiguration` | object | direct connection | Optional. Pick Apify datacenter proxy here if you need a different network. Apify Proxy connections use a US exit unless you choose another country. |
| `apifyProxyCountry` | string | `US` | Two-letter country for Apify Proxy exits when Apify Proxy is selected and no country is chosen in `proxyConfiguration`. |

### What it returns

Every dataset row has `kind` set to `profile` or `video`.

**Profile rows**

| Field | Meaning |
| --- | --- |
| `id`, `username`, `url`, `nickname` | Account identity, profile link and display name. |
| `followers`, `following`, `totalLikes`, `videoCount`, `friends` | Exact public counts. `totalLikes` is the total likes received across all videos. |
| `bio`, `bioLink` | Bio text and the link shown in the bio. |
| `verified`, `privateAccount`, `isSeller`, `commerceCategory` | Verified badge, private flag, TikTok Shop seller flag and business category. |
| `language`, `avatarUrl`, `secUid`, `accountCreatedAt` | Profile language, profile picture link, TikTok's secondary account ID and account creation time. |
| `embedAllowed` | Whether TikTok lists this account's latest videos. |

**Video rows**

| Field | Meaning |
| --- | --- |
| `id`, `url`, `description` | Video identity, link and caption. |
| `createdAt`, `createTimeUnix` | Publish time (UTC, ISO 8601) and the same time as a Unix timestamp. |
| `plays`, `likes`, `comments`, `shares`, `saves`, `reposts` | Exact engagement counts. `saves` is how often the video was saved to favourites. |
| `hashtags`, `mentions` | Hashtags (without `#`) and usernames mentioned in the caption. |
| `postType`, `durationSeconds`, `width`, `height`, `coverUrl` | `video` or `photo` carousel, length, size and cover image link. |
| `language`, `locationCreated`, `isAd` | Detected caption language, the country the video was posted from and the ad flag. |
| `music` | Sound `id`, `title`, `authorName`, `album`, `original` (the creator's own audio) and `durationSeconds`. |
| `author` | Creator `id`, `username`, `nickname`, `verified`, `followers` and profile `url`. |

**Every row**

| Field | Meaning |
| --- | --- |
| `input` | The input value the row came from. |
| `source` | `profile` or `video` for your own inputs; `profileLatest` for a profile's latest videos. |
| `scrapedAt` | Collection time (UTC, ISO 8601). |

Picture and cover links are signed by TikTok and expire after a few days; download them promptly if you need the images.

The run summary (`OUTPUT`) reports `sourcesRequested`, `usedExample` (true only for the bare-start sample), `items`, `profiles`, `videos`, `errors` and the list at `itemErrors`.

### Example queries

- One creator and their 10 latest videos: `{"profiles": ["zachking"], "latestVideos": 10}`
- Stats for a list of videos: `{"videoUrls": ["https://www.tiktok.com/@nike/video/7698062113742310670", "7698475408160722190"]}`
- Follower counts for many accounts: `{"profiles": ["nike", "adidas", "puma", "newbalance"], "maxItems": 500}`

### Output example

A profile row:

```json
{
  "kind": "profile",
  "id": "208464585232822272",
  "username": "nike",
  "url": "https://www.tiktok.com/@nike",
  "nickname": "Nike",
  "bio": "Just Do It.",
  "bioLink": "http://empli.fi/niketiktok",
  "verified": true,
  "privateAccount": false,
  "isSeller": false,
  "commerceCategory": "Sports, Fitness & Outdoors",
  "language": "en",
  "avatarUrl": "https://p16-common-sign.tiktokcdn-eu.com/tos-maliva-avt-0068/e0b0ac7b6ad6447a8e923fd1eb162f2c~tplv-tiktokx-cropcenter:1080:1080.jpeg?x-expires=...",
  "secUid": "MS4wLjABAAAA_3ndMt8d_tECTdpKgCxcx238tOnQZX-20wqN01aMui5zQ7hsqSdff-jC5qYC-Cl_",
  "accountCreatedAt": "2017-03-20T21:16:05+00:00",
  "followers": 9316580,
  "following": 91,
  "totalLikes": 49994334,
  "videoCount": 1098,
  "friends": 46,
  "embedAllowed": true,
  "input": "nike",
  "source": "profile",
  "scrapedAt": "2026-10-19T23:00:00+00:00"
}
```

A video row:

```json
{
  "kind": "video",
  "id": "7698062113742310670",
  "url": "https://www.tiktok.com/@nike/video/7698062113742310670",
  "description": "London is the place to be… #afterdarktour #nikerunning #fyp",
  "createdAt": "2026-10-18T17:32:58+00:00",
  "createTimeUnix": 1792344778,
  "postType": "video",
  "plays": 70800,
  "likes": 5932,
  "comments": 82,
  "shares": 373,
  "saves": 178,
  "reposts": 0,
  "hashtags": ["afterdarktour", "nikerunning", "fyp"],
  "mentions": [],
  "durationSeconds": 18,
  "width": 720,
  "height": 1280,
  "coverUrl": "https://p19-common-sign.tiktokcdn-eu.com/tos-useast5-p-0068-tx/owFVRQWiqQSAE8D8AB1FOfKEQvDHyyAA1gfisH~tplv-tiktokx-origin.image?x-expires=...",
  "language": "en",
  "locationCreated": "US",
  "isAd": false,
  "music": {
    "id": "7698062197494254350",
    "title": "original sound",
    "authorName": "Nike",
    "album": null,
    "original": true,
    "durationSeconds": 18
  },
  "author": {
    "id": "208464585232822272",
    "username": "nike",
    "nickname": "Nike",
    "verified": true,
    "followers": 9300000,
    "url": "https://www.tiktok.com/@nike"
  },
  "input": "nike",
  "source": "profileLatest",
  "scrapedAt": "2026-10-19T23:00:00+00:00"
}
```

### Failed items

A profile or video that cannot be retrieved (deleted, private, misspelled, or unavailable) is listed in the run summary at `OUTPUT.itemErrors` with its `input`, `url`, a `code` such as `NOT_FOUND`, `PRIVATE_VIDEO` or `PRIVATE_ACCOUNT`, and a `message`. Failed items are never dataset rows and are not charged. If a profile loads but its latest videos cannot be listed, the profile row is still delivered and the video list problem is reported with `sourceKind` `latestVideos`. A run in which nothing at all could be collected exits with an error instead of finishing green with an empty dataset.

### Limits and caveats

- Latest videos are the most recent ones TikTok lists on the profile, up to about 10; pinned videos can come first. A profile's full video history, hashtag pages, search results and comments are not included.
- Private accounts return their profile row only. Accounts that hide their video list return the profile row and an `itemErrors` entry.
- Counts are live at collection time. TikTok rounds some counts on the author block of a video; the profile row carries the exact numbers.
- Automated access is subject to TikTok's terms; use this actor only where you have the necessary permissions and a lawful basis.

### FAQ

**Do I need a TikTok account?** No. Only public profile and video pages are read.

**What happens if I just press Start?** The Actor collects the sample profile `nike`, three of its latest videos and the sample video link, and marks the run summary `usedExample: true`. It is a real run and is charged normally (about $0.0125), so check the rows before adding your own list.

**Can I mix profiles and video links?** Yes. Put them in the matching inputs; duplicates are returned once.

**Why did I get fewer latest videos than I asked for?** Some profiles list fewer than 10 recent videos, private videos are skipped, and `maxItems` stops the run once it is reached.

### Price

**$0.0015 per result** (each profile or video row delivered), plus **$0.005 per run start**. The run-start event is charged per GB of memory; the default 512 MB run is one start event. The start is charged even if the run saves no results. Failed items are not charged. Platform usage is included in these prices.

That is $1.50 per 1,000 rows at list price, and profile rows and video rows cost the same. For comparison, the largest TikTok profile scraper lists from $1.00 per 1,000 results and charges $3.00 per 1,000 results on the Free plan, and returns its video rows from a paginated history; this one returns up to 10 latest videos per profile, exact counts and full video metadata for a flat $0.0015 per row.

# Actor input Schema

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

TikTok usernames (nike or @nike) or profile links (https://www.tiktok.com/@nike). Each profile becomes one row with its follower, following, like and video counts, bio, link and verified status.

## `latestVideos` (type: `integer`):

How many of each profile's latest videos to return as video rows, from 0 to 10. TikTok shows up to about 10 recent videos per public profile; pinned videos may come first. Each video is one extra row.

## `videoUrls` (type: `array`):

TikTok video links (https://www.tiktok.com/@user/video/123...), short share links (https://vm.tiktok.com/...) or numeric video IDs. Each video becomes one row with plays, likes, comments, shares, saves, caption, hashtags, music and author.

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

Total cap on dataset rows (profiles plus videos) for the whole run. The run stops collecting once the cap is reached.

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

Optional. By default the actor connects directly. Choose Apify datacenter proxy here if you need a different network; Apify Proxy connections use a US exit unless you pick another country. Explicit settings are respected.

## `apifyProxyCountry` (type: `string`):

Two-letter country code for Apify Proxy exits when Apify Proxy is selected and the proxy setting names no country. Defaults to US.

## Actor input object example

```json
{
  "profiles": [
    "nike"
  ],
  "latestVideos": 3,
  "videoUrls": [
    "https://www.tiktok.com/@nike/video/7698062113742310670"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "apifyProxyCountry": "US"
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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": [
        "nike"
    ],
    "latestVideos": 3,
    "videoUrls": [
        "https://www.tiktok.com/@nike/video/7698062113742310670"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automatic/tiktok-profile-video-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": ["nike"],
    "latestVideos": 3,
    "videoUrls": ["https://www.tiktok.com/@nike/video/7698062113742310670"],
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("automatic/tiktok-profile-video-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": [
    "nike"
  ],
  "latestVideos": 3,
  "videoUrls": [
    "https://www.tiktok.com/@nike/video/7698062113742310670"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call automatic/tiktok-profile-video-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automatic/tiktok-profile-video-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/9EPUPRef3XbzezrCI/builds/LCv9gIEtaImR3CAhm/openapi.json
