# TikTok Profile & Video Scraper: Followers, Views, Engagement (`precious_bathmat/tiktok-profile-video-scraper`) Actor

Scrape TikTok profiles and videos: followers, likes, bio, latest videos with views, likes, comments, shares, saves, hashtags and sound, plus engagement rate, median views and posting pace per profile. Any video by link. No login.

- **URL**: https://apify.com/precious_bathmat/tiktok-profile-video-scraper.md
- **Developed by:** [Mariam Ahmed](https://apify.com/precious_bathmat) (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 $2.00 / 1,000 videos

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: Followers, Views, Engagement

Scrape **TikTok profiles and videos** without logging in. For every profile you get **followers, following, total likes, video count, bio, bio link and verified flag**, plus its **latest videos** with **views, likes, comments, shares, saves, date, duration, caption, hashtags and sound**. From those videos the scraper works out each profile's **median views, engagement rate, engagement per follower and posting pace**. Paste any video link to get the same numbers for single videos.

- **Profiles**: exact follower, following, like and video counts, bio and link, account age, organisation and seller flags
- **Latest videos** of each profile (about 10–15, as TikTok's own embed lists them, pinned videos included)
- **Every video's numbers**: views, likes, comments, shares, saves (bookmarks), engagement rate, duration, hashtags, mentions, sound and whether it is original, TikTok's content categories and related search terms
- **Profile benchmarks**: median and average views, median engagement rate, engagement per follower, views per follower, posts per week (recent and all-time), top hashtags, best video
- **Single videos by link**, including short links (vm.tiktok.com)
- **No login, no cookies, no API key, no proxy**

### What does this TikTok scraper do?

```
@duolingo   18,232,862 followers · median 421,000 views · 16.7% engagement · 7.8 posts a week
@khaby.lame 163,016,611 followers · median 7,950,000 views · 9.0% engagement
@ryanair     2,926,582 followers · median 429,000 views · 6.46% engagement per follower
```

1. Add **profiles** (`@duolingo`, `duolingo` or the profile address) and/or **video addresses**.
2. The scraper reads each profile page, the profile's embed (its latest videos) and each video's page: the same public pages anyone can open in a browser.
3. You get **one row per video** in the dataset and **one row per profile** in `PROFILES`, with the benchmarks worked out.

```mermaid
flowchart LR
    A[Profiles ·<br/>video links] --> B[Profile page<br/>followers, likes, bio]
    A --> C[Latest videos<br/>from the embed]
    C --> D[Video pages<br/>views, likes, shares, saves]
    B --> E[Profile row<br/>+ median views, engagement, pace]
    D --> E
    D --> F[Video rows]
```

### Who is it for?

- **Influencer marketing teams and agencies** vetting creators: real median views and engagement instead of follower counts
- **Brands** benchmarking their TikTok against competitors, week by week
- **Social media managers** tracking which of their videos and hashtags work
- **Researchers and journalists** collecting public TikTok numbers for news accounts, brands or public figures
- **Lead generation**: bio links and organisation flags for business accounts

### What data do you get?

**Videos** (dataset, one row per video)

| Field | What it tells you |
|---|---|
| `url`, `videoId`, `cover` | The video |
| `author`, `authorNickname`, `authorFollowers`, `authorVerified` | Who posted it |
| `caption`, `createdAt`, `durationSeconds`, `isPhotoPost` | What and when |
| `plays`, `likes`, `comments`, `shares`, `saves` | How it performed |
| `engagementRate` | (likes + comments + shares) ÷ views, in % |
| `hashtags`, `mentions` | Hashtags and accounts tagged in the caption |
| `soundTitle`, `soundAuthor`, `soundId`, `soundIsOriginal` | The sound |
| `categories`, `searchTerms` | TikTok's content categories and the searches it suggests next to the video |
| `postedFrom`, `isAd` | Country it was posted from; whether it is marked as an ad |

**Profiles** (`PROFILES`, one row per profile; also `PROFILES_CSV`)

| Field | What it tells you |
|---|---|
| `username`, `nickname`, `verified`, `profileUrl`, `avatar` | The account |
| `followers`, `following`, `likes`, `videos`, `friends` | Exact counts |
| `bio`, `bioLink`, `language`, `accountCreatedAt` | Profile details |
| `isOrganization`, `isSeller`, `privateAccount` | Business account, TikTok Shop seller, private |
| `medianViews`, `averageViews`, `averageLikes`, `averageComments`, `averageShares` | From the latest videos |
| `medianEngagementRate`, `engagementPerFollower`, `viewsPerFollower` | Engagement benchmarks |
| `postsPerWeek`, `postsPerWeekAllTime`, `lastPostedAt` | Posting pace and activity |
| `topHashtags`, `bestVideo` | What they post about and their top video |

### Example: 11 October 2026

**15 profiles and 171 videos in 62 seconds**, every page read on the first pass.

| Profile | Followers | Median views (latest videos) | Median engagement | Posts a week |
|---|---|---|---|---|
| @khaby.lame | 163,016,611 | 7,950,000 | 9.03% | 1.2 |
| @espn | 61,339,347 | 53,400 | 7.0% | 63 (10 videos in 2.5 hours on a game night) |
| @duolingo | 18,232,862 | 421,000 | 16.7% | 7.8 |
| @redbull | 23,184,836 | 569,000 | 5.98% | 7.7 |
| @gymshark | 6,682,483 | 210,100 | 14.77% | 6.3 |
| @chipotle | 2,932,848 | 1,900,000 | 1.71% | 4.8 |
| @nasa | 2,045,952 | 229,200 | 6.82% | 2.9 |

- **Big follower counts are not big views**: ESPN has 61 million followers and a median of 53,400 views per recent video; Chipotle has 2.9 million and a median of 1.9 million.
- Duolingo's latest videos earned **16.7% engagement**, nearly double NBA's 9.1%.

### Pricing

**$0.002 per video** and **$0.004 per profile**.

- 100 profiles with their latest videos (about 1,200 videos): **about $2.80**
- 100 profiles without videos: **$0.40**
- The run above: 15 profiles and 171 videos, **$0.40**

Profiles or videos that cannot be read (deleted, private, wrong name) are not charged.

### Good to know

- **Latest videos**: TikTok's public embed shows about 10–15 of a profile's newest videos, pinned videos included. That is enough for current benchmarks; it is not a profile's full history.
- **Posts per week** is read from the latest videos, ignoring old pinned ones, and a burst counts as at least one day. `postsPerWeekAllTime` divides all videos by the account's age.
- **Engagement rate** is (likes + comments + shares) ÷ views. **Engagement per follower** is the average of the same sum ÷ followers.
- **Private accounts** give profile numbers only. Accounts that switched off embedding give profile numbers only, with a note.
- **Personal data**: public account numbers and posts only. Commenters, followers and viewers are never collected. Use it for public accounts (brands, creators, media, public figures) and follow the data protection rules that apply to you.
- No login, no cookies, no proxies needed.

### Input

| Field | Meaning |
|---|---|
| **Profiles** | Usernames or profile addresses, one per line |
| **Latest videos of each profile** | On by default |
| **Full numbers for each video** | On by default; off = views and captions only |
| **Maximum latest videos per profile** | 1 to 15 (default 15) |
| **Video addresses** | Single videos, including short links |
| **Minimum views** | Skip videos with fewer views |

### Integrations

Export to JSON, CSV, Excel or Google Sheets, or connect through the Apify API, webhooks, Make, Zapier and n8n. Schedule it weekly on your competitors' profiles to build a follower and engagement history.

# Actor input Schema

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

One per line: "@duolingo", "duolingo" or the profile address (tiktok.com/@duolingo).

## `latestVideos` (type: `boolean`):

Also get each profile's latest videos (up to about 15, as TikTok's embed shows them, pinned ones included), and work out median views, engagement and posting pace.

## `videoDetails` (type: `boolean`):

Read each video's page for likes, comments, shares, saves, date, duration, hashtags and sound. Off = views and caption only, faster.

## `maxVideosPerProfile` (type: `integer`):

1 to 15.

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

Optional. Single videos, one per line: tiktok.com/@user/video/123..., or short links (vm.tiktok.com/...).

## `minPlays` (type: `integer`):

Only save videos with at least this many views. 0 = all.

## Actor input object example

```json
{
  "profiles": [
    "@duolingo",
    "@nba"
  ],
  "latestVideos": true,
  "videoDetails": true,
  "maxVideosPerProfile": 15,
  "minPlays": 0
}
```

# Actor output Schema

## `videos` (type: `string`):

One row per video: views, likes, comments, shares, saves, engagement, hashtags and sound.

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

One row per profile: followers, likes, videos, bio, median views, engagement rate and posts per week.

## `profilesCsv` (type: `string`):

Profiles as a spreadsheet.

## `videosCsv` (type: `string`):

Videos as a spreadsheet.

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

Counts and notes.

# 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": [
        "@duolingo",
        "@nba"
    ]
};

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

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

```

## MCP server setup

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