# TikTok Scraper: Videos, Comments, Hashtags & Profiles (`apisamurai/tiktok-scraper`) Actor

TikTok scraper for videos by profile, keyword search, hashtag or link, plus comments, profile details, followers and following. Exact limits, real date and view filters, no mock data, and you pay only for real, unique rows.

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

## Pricing

from $1.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 Scraper: Videos, Comments, Hashtags & Profiles

This TikTok scraper gets videos by profile, keyword search, hashtag or video link, plus comments, profile details, followers and following of public accounts. Every video comes with its description, hashtags, mentions, post date, views, likes, comments, shares, saves, duration, music, author details, cover and video links. You pay only for real, unique rows, and IDs are always text, so long TikTok IDs never get rounded.

### What you can use it for

- **Scrape a TikTok profile** to collect a creator's videos, newest first, with optional profile details (bio, followers, total likes).
- **Search TikTok by keyword** for brand monitoring, trend research and content ideas.
- **Scrape TikTok hashtags** to see which videos run under a campaign or trend.
- **Scrape TikTok comments** to read audience reactions, one row per comment.
- **Fetch single videos** from links to refresh views and likes for videos you already track.
- **Scrape TikTok followers and following** of public accounts for influencer and audience research.

### Fair billing

- Only real videos, comments and users are charged. No demo, mock or placeholder rows, ever. If the data source sends one, it is dropped and counted in the run summary.
- No start fee, no per-run fee, no per-query fee, no minimum charge.
- Same price on every Apify plan, free plan included.
- Free Apify plan: up to 100 results per run (10 videos fetched by link, 10 profiles), so you can try it. Paid plans have no limit.
- Date, view and like filters and all limits are enforced by the Actor itself. Videos outside your filters are skipped and not charged.
- `Max rows per input item` and `Max comments per video` are exact: you never get, or pay for, more than you asked.
- Duplicates are never charged. A video found by a search and a hashtag is saved once.
- An empty run costs nothing for results.
- When you hit your spending limit, the run stops cleanly.

### How to use

1. Open the [TikTok Scraper](https://apify.com/apisamurai/tiktok-scraper) page and click **Try for free** (you sign in to your Apify account).
2. Fill in at least one source: profiles, search queries, hashtags, video links, or followers/following usernames.
3. Set **Max rows per input item**, and optionally comments, dates and filters.
4. Click **Start**. Rows appear in the **Output** tab while the run works.
5. Export the dataset as JSON, CSV or Excel, or check the `SUMMARY` record in the key-value store.

**API:** start a run and get the rows in one call with `POST https://api.apify.com/v2/acts/apisamurai~tiktok-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>` and the input as JSON in the body.

### Input

| Field | What it does |
|---|---|
| Profiles | Usernames or links: `khaby.lame`, `@khaby.lame`, `https://www.tiktok.com/@khaby.lame`. Gets their videos. |
| Include profile details | Off by default. Adds one user row per profile, billed as a profile. |
| Search queries | Keyword search for videos, one per line. |
| Hashtags | `fyp`, `#fyp` or a `tiktok.com/tag/fyp` link. |
| Video links | Full details of these videos or photo posts. Short `vm.tiktok.com` links work. |
| Include comments / Max comments per video | Comments of every saved video. Default 50 per video. |
| Followers of / Following of | Usernames whose followers or followed accounts you want. |
| Max rows per input item | Videos or users per profile, query, hashtag or list. Default 50. |
| Max rows for the whole run | Optional hard cap on all rows. |
| Posted after / Posted before | Inclusive, UTC. |
| Min views / Min likes | Skip videos below these numbers. |

```json
{
  "profiles": ["khaby.lame"],
  "hashtags": ["booktok"],
  "includeComments": true,
  "maxCommentsPerVideo": 20,
  "maxItemsPerSource": 100,
  "postedAfter": "2026-01-01",
  "minViews": 10000
}
```

### Output

One row per video, comment or user, with a `type` field. Field names never change between runs. Example video row (media links shortened):

```json
{
  "type": "video",
  "id": "7470969622276164906",
  "url": "https://www.tiktok.com/@stoolpresidente/video/7470969622276164906",
  "description": "Uncle Jerry and his family may be the nicest people in the world ",
  "hashtags": [],
  "mentions": [],
  "postedAt": "2025-02-13T18:18:03.000Z",
  "views": 141567, "likes": 18651, "comments": 152, "shares": 237, "saves": 274,
  "durationSeconds": 89,
  "isAd": false,
  "music": { "id": "7470969632736709422", "title": "original sound - stoolpresidente", "author": "Dave Portnoy", "isOriginal": true },
  "author": { "id": "6659752019493208069", "username": "stoolpresidente", "nickname": "Dave Portnoy", "followers": 4248754, "verified": true },
  "coverUrl": "https://p16-sign.tiktokcdn-us.com/...",
  "videoUrl": "https://v45.tiktokcdn-eu.com/...",
  "location": null,
  "source": "profile",
  "input": "stoolpresidente",
  "scrapedAt": "2026-02-01T10:00:00.000Z"
}
```

Comment rows have `type: "comment"`, `id`, `videoId`, `videoUrl`, `text`, `author` (`id`, `username`, `nickname`), `likes`, `repliesCount`, `postedAt`, `scrapedAt`. User rows have `type: "user"`, `id`, `username`, `nickname`, `bio`, `followers`, `following`, `likesTotal`, `videosCount`, `verified`, `avatarUrl`, `url`, `source`, `input`, `scrapedAt`. Missing values are `null`.

Each run also writes a `SUMMARY` record to the key-value store. For every input item it lists rows delivered, comments, whether the profile row was saved (`profileRow`, or `profileSkippedBecause` when it was not fetched), rows skipped by dates or filters, duplicates, placeholder rows dropped, and why it stopped (`limit reached`, `no more results`, `not found`, `temporary error`, `spending limit`, `free plan limit` or `data source unavailable`).

### Pricing

$1 per 1,000 videos; $6.50 per 1,000 videos fetched by link; $0.50 per 1,000 comments; $1 per 1,000 followers or following; $6.50 per 1,000 profiles

Videos from profiles, searches and hashtags are "videos"; videos from your own links are "videos fetched by link". User rows from **Followers of** and **Following of** are "followers or following"; the user row that **Include profile details** adds for each profile is a "profile", because each one needs its own lookup. Prices are preliminary and may change after measurement.

### Integrations

- **Apify API** to start runs and read datasets from any language.
- **Python and JavaScript clients** (`apify-client`) for scripts and backends.
- **Zapier, Make and n8n** to send new videos to Google Sheets, Slack, a CRM or a database.
- **MCP for AI agents:** connect the Apify MCP server to Claude, ChatGPT or another MCP client and the agent can run this Actor as a tool.
- **Schedules and webhooks** in Apify Console for daily or hourly runs.

### FAQ

**Do I need a TikTok account or login?**
No. You only need an Apify account. You never enter TikTok credentials or cookies.

**How many videos can I get?**
Up to 1,000,000 rows per input item on paid plans, and up to 100 results per run on the free Apify plan. TikTok decides how deep a profile, search or hashtag feed goes, so very old videos may not be reachable.

**Why did I get fewer results than I asked for?**
Open the `SUMMARY` record. It says for each input why it stopped: no more results, videos skipped by your dates or filters, duplicates, not found, the spending limit or the free plan limit. TikTok feeds can also leave out some posts, or return different videos for the same request. For videos you track, add their links to **Video links**.

**What about private accounts?**
Only public data is collected. Private accounts, and deleted or region-restricted videos, return nothing or show `not found` in the summary, and nothing is charged for them.

**Can I schedule it?**
Yes. Create a schedule in Apify Console, for example a daily hashtag run with `Posted after` set, and connect an integration to get the new rows.

**Do the video and cover links last?**
No. TikTok media links expire after some hours, so download files soon after the run.

**Is it legal to scrape TikTok?**
The Actor collects only public data. You are responsible for how you use it: follow TikTok's terms and the laws where you live, and take care with personal data (for example under GDPR). This is not legal advice.

### Tips

- Set `Posted after` on profiles: the profile feed is newest first, so the run stops as soon as it reaches older videos.
- Set `Max rows for the whole run` when you combine many sources with comments and want a firm total.

# Actor input Schema

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

Get the videos of these accounts, newest first. Usernames or profile links: khaby.lame, @khaby.lame or https://www.tiktok.com/@khaby.lame. One per line.

## `includeProfile` (type: `boolean`):

On: each profile also gets one user row with bio, followers, following, total likes and video count. Each of these rows is billed as a profile (see Pricing). Free plan: up to 10 per run.

## `searchQueries` (type: `array`):

Keyword search for videos, one query per line.

## `hashtags` (type: `array`):

Videos under these hashtags. With or without #, or a tiktok.com/tag link. One per line.

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

Fetch full details of these videos or photo posts, e.g. https://www.tiktok.com/@user/video/7463250363559218474. Short vm.tiktok.com links work too. One per line.

## `includeComments` (type: `boolean`):

On: collect the comments of every video saved by this run (one row per comment).

## `maxCommentsPerVideo` (type: `integer`):

Maximum comment rows for each video. Enforced exactly.

## `followersOf` (type: `array`):

Collect the followers of these accounts (one row per user). Usernames or profile links, one per line.

## `followingOf` (type: `array`):

Collect the accounts these accounts follow (one row per user). Usernames or profile links, one per line.

## `maxItemsPerSource` (type: `integer`):

Maximum videos (or users) for each profile, search query, hashtag or follower list. Enforced exactly: the last page is trimmed. Comments and profile rows are counted separately.

## `maxTotalItems` (type: `integer`):

Optional hard cap on all rows (videos, comments and users) across all input items. Leave empty for no total cap.

## `postedAfter` (type: `string`):

Only videos posted on or after this day (UTC). Videos outside the range are skipped and not charged.

## `postedBefore` (type: `string`):

Only videos posted on or before this day (UTC, the whole day is included).

## `minViews` (type: `integer`):

Skip videos with fewer views.

## `minLikes` (type: `integer`):

Skip videos with fewer likes.

## Actor input object example

```json
{
  "profiles": [
    "khaby.lame"
  ],
  "includeProfile": false,
  "includeComments": false,
  "maxCommentsPerVideo": 50,
  "maxItemsPerSource": 10
}
```

# 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": [
        "khaby.lame"
    ],
    "maxItemsPerSource": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("apisamurai/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": ["khaby.lame"],
    "maxItemsPerSource": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("apisamurai/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": [
    "khaby.lame"
  ],
  "maxItemsPerSource": 10
}' |
apify call apisamurai/tiktok-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,apisamurai/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/9Q5UvVfvgrrWbK2zW/builds/0boDITh9PchK3cEUm/openapi.json
