# TikTok Scraper — Videos, Profiles & Engagement Analytics (`punkrecordsdata/tiktok-scraper`) Actor

Scrape TikTok profiles and videos: captions, stats, hashtags, engagement rate, virality score, sponsorship detection and watermark-free download links. Export to CSV, Excel, JSON.

- **URL**: https://apify.com/punkrecordsdata/tiktok-scraper.md
- **Developed by:** [PunkRecordsData](https://apify.com/punkrecordsdata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.55 / 1,000 video/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.
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?

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

<p align="center">
  <img src="https://api.apify.com/v2/key-value-stores/AAm3a1h3Z9nYfrvh9/records/banner" alt="PunkRecordsData" width="100%" />
</p>

## 🎵 TikTok Scraper: Videos, Profiles & Analytics

![Category](https://img.shields.io/badge/Category-Social%20Media-ff2d55) ![Proxy](https://img.shields.io/badge/Proxy-Residential-blueviolet) ![Node](https://img.shields.io/badge/Node.js-20-339933?logo=node.js\&logoColor=white) ![Status](https://img.shields.io/badge/Cloud%20verified-✅-brightgreen)

> 🚀 **TikTok Scraper** is an Apify Actor that exports TikTok videos and
> profiles in seconds, with engagement rate, a virality score, sponsorship
> detection, and watermark-free download links already computed for you,
> not just raw numbers.

> 🕒 **Last updated:** 2026-08-28 · **📊 30+ fields** per record · verified on
> a real cloud run against `@tiktok` · by **PunkRecordsData**

TikTok's own app gives you a scroll feed. This Actor gives you a dataset:
every video's caption, stats, hashtags, and music. Plus the analysis layer
most scrapers leave for you to build yourself. Point it at a list of
profiles or specific video URLs and get back a table ready for a
spreadsheet, a BI dashboard, or an LLM prompt.

### 📚 Table of Contents

- [🎯 Who this is for](#-who-this-is-for)
- [📋 What it does](#-what-the-tiktok-scraper-does)
- [📈 How it compares](#-how-it-compares-to-alternatives)
- [⚙️ Input](#️-input)
- [📊 Output](#-output)
- [🧾 Sample record](#-sample-record-real-data)
- [🚀 How to use](#-how-to-use)
- [💼 Business use cases](#-business-use-cases)
- [🔌 Integrate with any app](#-integrate-with-any-app)
- [💰 Cost](#-cost)
- [❓ FAQ](#-frequently-asked-questions)
- [🗺️ Roadmap](#️-roadmap)

### 🎯 Who this is for

| 🎯 Target Audience | 💡 Primary Use Cases |
|---|---|
| 📊 Social media analysts | Competitor & trend tracking |
| 📣 Marketing / brand teams | Influencer vetting, sponsorship audits |
| 📈 Growth & content teams | Posting-time and engagement benchmarking |
| 🎓 Researchers & journalists | Public discourse and trend analysis |

### 📋 What the TikTok Scraper does

- 👤 Scrapes recent videos from a list of **TikTok profiles**
- 🔗 Scrapes **direct video URLs** individually
- 📈 Computes **engagement rate** and a **0–100 virality score** per video
- 💰 Flags likely **sponsored/ad content** from caption signals
- \#️⃣ Cleans **hashtags and mentions** into real arrays, not raw text
- 🕒 Adds **posting-time analytics** (day of week, hour UTC)
- ⬇️ Returns a **watermark-free download URL** for every video
- 👥 Optionally enriches each video with the **author's full stats**
  (followers, following, total hearts, video count)

### 📈 How it compares to alternatives

| | 🎵 TikTok Scraper (this) | Narrow single-purpose scrapers | Manual export |
|---|---|---|---|
| Engagement rate | ✅ built in | ❌ compute yourself | ❌ |
| Virality score | ✅ built in | ❌ | ❌ |
| Sponsored-content detection | ✅ built in | ❌ | ❌ |
| Posting-time analytics | ✅ built in | ❌ | ❌ |
| Clean hashtag/mention arrays | ✅ built in | Often raw text only | ❌ |
| Watermark-free download URL | ✅ | Varies | ❌ |
| Profiles **and** direct video URLs | ✅ | Usually one or the other | None |
| Scheduling, API, integrations | ✅ (Apify platform) | Varies | ❌ |
| Comments / hashtag search / AI summaries | 🗺️ roadmap | Some offer today | ❌ |

### ⚙️ Input

| Field | Type | Default | Description |
|---|---|---|---|
| `profiles` | array | None | TikTok usernames or profile URLs to scrape |
| `postURLs` | array | None | Direct TikTok video URLs to scrape individually |
| `resultsPerPage` | integer | `20` | Max videos to pull per profile |
| `maxItems` | integer | `10` (free) | Cap across everything combined, paid plans up to 1,000,000 |
| `excludePinnedPosts` | boolean | `false` | Skip videos pinned to the top of a profile |
| `oldestPostDate` | string | None | Only videos posted on/after this date (`YYYY-MM-DD`) |
| `newestPostDate` | string | None | Only videos posted on/before this date (`YYYY-MM-DD`) |
| `scrapeAdditionalAuthorMeta` | boolean | `true` | Fetch full author stats (followers, hearts, video count) |
| `detectSponsoredContent` | boolean | `true` | Flag likely ads from caption/hashtag signals |
| `proxyConfiguration` | object | `RESIDENTIAL` | Required for reliable results, TikTok blocks datacenter IPs at scale |

**Minimal, scrape 2 profiles:**

```json
{
  "profiles": ["tiktok", "nike"],
  "resultsPerPage": 25,
  "maxItems": 50
}
```

**Scrape one specific video:**

```json
{
  "postURLs": ["https://www.tiktok.com/@tiktok/video/7679101730352565535"]
}
```

> ⚠️ **Good to know:** `postURLs` is matched against the author's most recent
> uploads. Very old videos may not be found. Use `profiles` with a higher
> `resultsPerPage` instead for deep history. TikTok's anti-bot defenses are
> inconsistent by design; the Actor automatically retries a profile once if
> the first attempt returns nothing.

### 📊 Output

| Field | Description |
|---|---|
| 🖼 `imageUrl` | Video cover image |
| 🆔 `id` | Video ID |
| 📝 `text` | Caption |
| 🔗 `url` | Video/profile URL |
| 📌 `isPinned` | Whether the video is pinned to the profile |
| 📢 `isAd` | TikTok's own platform-declared ad flag |
| 👤 `authorMeta` | Id, name, profile URL, avatar, verified, private account, bio + bio link + (optional) full stats: followers, following, friends, hearts, videos, total diggs given |
| 🎵 `musicMeta` | Sound name, author, album, original vs. cover |
| 🎬 `videoMeta` | Duration, resolution, format, cover, **watermark-free download URL** |
| ❤️ `diggCount` | Likes |
| 💬 `commentCount` | Comments |
| ▶️ `playCount` | Plays |
| 🔁 `shareCount` | Shares |
| ⭐ `collectCount` | Saves |
| 🔂 `repostCount` | Reposts |
| #️⃣ `hashtags` | Cleaned hashtag array |
| @️⃣ `mentions` / `detailedMentions` | Cleaned `@handle` array + resolved `{id, name, profileUrl}` objects |
| 💰 `isSponsoredContent` / `sponsorSignals` | Our own ad-detection heuristic + matched signals (independent from the platform's `isAd` flag) |
| 📈 `engagementRate` | `(likes+comments+shares+saves) / plays`, as % |
| 🔥 `viralityScore` | 0–100 composite score |
| 📅 `postedDayOfWeek` / `postedHourUTC` | Posting-time analytics |
| 🌐 `captionLanguage` | Detected caption language (heuristic) |
| 🕓 `createTimeISO` | When the video was posted |
| 🕒 `scrapedAt` | When this record was scraped |
| ❌ `error` | Present only on failed items |

Download the dataset as **JSON, CSV, Excel, or XML** straight from the Apify Console, or pull it via the API.

### 🧾 Sample record (real data)

<details>
<summary><b>▶️ Click to expand. Real item scraped from @tiktok on 2026-08-28</b></summary>

```json
{
  "imageUrl": "https://p19-common-sign.tiktokcdn-us.com/.../oMkA0CE...image",
  "id": "7679101730352565535",
  "text": "what started on TikTok grew into a special IRL connection on tour between @Bella Kay \"Behind the Breakthrough.\"",
  "url": "https://www.tiktok.com/@tiktok",
  "isPinned": false,
  "authorMeta": {
    "id": "107955",
    "name": "tiktok",
    "nickName": "TikTok",
    "verified": true,
    "signature": "One TikTok can make a big impact",
    "followers": 95391312,
    "following": 2,
    "heartCount": 462970935,
    "videoCount": 1497,
    "followerToEngagementRatio": 0.604
  },
  "musicMeta": {
    "musicName": "original sound",
    "musicAuthor": "TikTok",
    "musicOriginal": true
  },
  "videoMeta": {
    "duration": 62,
    "width": 720,
    "height": 1280,
    "definition": "720p"
  },
  "diggCount": 635,
  "shareCount": 32,
  "playCount": 17500,
  "commentCount": 122,
  "collectCount": 55,
  "hashtags": [],
  "mentions": ["@itsbellakaymusic"],
  "isSponsoredContent": false,
  "sponsorSignals": [],
  "engagementRate": 4.82,
  "viralityScore": 64,
  "postedDayOfWeek": "Friday",
  "postedHourUTC": 15,
  "captionLanguage": null,
  "createTimeISO": "2026-08-28T15:16:51.000Z",
  "scrapedAt": "2026-08-28T18:29:12.746Z",
  "error": null
}
```

</details>

### 🚀 How to use

1. Sign up or log in at [console.apify.com](https://console.apify.com)
2. Open **TikTok Scraper** and go to the **Input** tab
3. Add usernames to `profiles` or full URLs to `postURLs`
4. Set `resultsPerPage` / `maxItems` and click **▶️ Start**
5. Download results as JSON, CSV, Excel, or XML. Or pull them via the API

### 💼 Business use cases

| 🏆 Competitor & trend tracking | 🤝 Influencer vetting |
|---|---|
| Track a list of competitor accounts, spot which videos are outperforming via `viralityScore`, and export weekly to your BI tool. | Pull a creator's recent videos with `scrapeAdditionalAuthorMeta` on to check real engagement rate against follower count before a sponsorship deal. |

| 🗓️ Content strategy | ⚖️ Compliance / ad-disclosure audits |
|---|---|
| Use `postedDayOfWeek` / `postedHourUTC` across your top-performing videos to find the best posting windows for your niche. | Use `isSponsoredContent` and `sponsorSignals` to flag videos that look sponsored but may be missing proper disclosure. |

### 🔌 Integrate with any app

Pull results via the [Apify API](https://docs.apify.com/api/v2), or connect
to Make, Zapier, Google Sheets, Airbyte, n8n, or any webhook-based tool from
the Apify Console **Integrations** tab. Schedule recurring runs with Apify's
built-in **Scheduler**.

```bash
curl "https://api.apify.com/v2/acts/PunkRecordsData~tiktok-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{ "profiles": ["tiktok"], "maxItems": 10 }'
```

### 💰 Cost

| Plan | What you get |
|---|---|
| 🆓 Free | Up to 10 items per run (preview) |
| 💳 Paid | Up to 1,000,000 items per run, billed on Apify usage (compute + residential proxy) |

Cost scales mainly with **how many profiles/videos you visit**, not raw item
count. Set `resultsPerPage` higher to pull more videos per profile visit
and get a better cost-per-item.

### ❓ Frequently Asked Questions

**Does this work without a proxy?**
No. TikTok blocks datacenter IPs at scale. `RESIDENTIAL` proxy is the
default and required for reliable results.

**Why did a profile return 0 items?**
TikTok's anti-bot defenses are inconsistent; the Actor retries once
automatically. If it still returns nothing, the profile may be private,
empty, or temporarily rate-limiting your proxy session. Try again.

**Can I scrape any video by URL?**
Videos are matched against the author's most recent uploads. Very old
videos may not be found. Use `profiles` with a higher `resultsPerPage`
for deep history instead.

**Does it download the video file itself?**
It returns a direct, watermark-free `downloadUrl`. The Actor doesn't
download/store the binary video for you.

**Is this affiliated with TikTok?**
No. See disclaimer below.

**What counts as a "result" for pricing?**
Each video record in your output dataset.

**Can I filter by date?**
Yes, `oldestPostDate` / `newestPostDate`.

**Does it scrape comments?**
Not in this version. See roadmap below.

**Can I run this on a schedule?**
Yes, use Apify's built-in Scheduler.

**What happens on the free plan?**
Results are capped at 10 items per run.

### 🗺️ Roadmap

- 💬 Comments
- 🔎 Hashtag / keyword search
- 👥 Follower / following lists
- 🤖 AI video summaries

***

> **⚠️ Disclaimer:** This is an independent tool, not affiliated with,
> endorsed by, or sponsored by TikTok. It only collects data that is
> publicly visible on TikTok's website.

**🆘 Need help or want a custom scraper?** Contact PunkRecordsData at
<contact.punkrecordsdata@gmail.com>.

# Actor input Schema

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

Usernames (with or without @) or full profile URLs. The Actor pulls each profile's most recent videos. Example: `tiktok`, `@nike`, or `https://www.tiktok.com/@nike`.

## `postURLs` (type: `array`):

Full TikTok video links to scrape individually, e.g. `https://www.tiktok.com/@user/video/1234567890123456789`. Matched against the author's most recent uploads — a very old video may not be found; for deep history use **TikTok profiles** with a higher **Videos per profile** instead.

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

How many recent videos to pull from each profile listed above.

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

Hard cap across every profile and video combined, so a run never runs longer or costs more than you expect. **Free plan:** capped at 10 regardless of this value. **Paid:** up to 1,000,000.

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

Skip videos pinned to the top of a profile, so they don't push out fresher content when you only want the latest.

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

Only keep videos posted on or after this date. Format: `YYYY-MM-DD`.

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

Only keep videos posted on or before this date. Format: `YYYY-MM-DD`.

## `scrapeAdditionalAuthorMeta` (type: `boolean`):

Add each video's author's follower count, following count, total hearts and video count. Costs one extra request per unique author, worth it for influencer vetting or engagement-ratio analysis.

## `detectSponsoredContent` (type: `boolean`):

Flag videos as likely sponsored/ads based on caption signals (`#ad`, `#sponsored`, "paid partnership", etc.) — handy for compliance and disclosure audits.

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

TikTok blocks datacenter IPs at scale — **Residential** is required for reliable results and is already selected below.

## Actor input object example

```json
{
  "profiles": [
    "tiktok"
  ],
  "resultsPerPage": 20,
  "maxItems": 10,
  "excludePinnedPosts": false,
  "scrapeAdditionalAuthorMeta": true,
  "detectSponsoredContent": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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": [
        "tiktok"
    ],
    "resultsPerPage": 20,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("punkrecordsdata/tiktok-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"],
    "resultsPerPage": 20,
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("punkrecordsdata/tiktok-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"
  ],
  "resultsPerPage": 20,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call punkrecordsdata/tiktok-scraper --silent --output-dataset

```

## MCP server setup

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