# TikTok Scraper | All-In-One (`toolzerhub/tiktok-scraper`) Actor

Extract TikTok videos, profiles, comments, hashtags, sounds, and follower lists in one Actor. Add a username, video URL, hashtag, or search term and get video IDs, captions, play, like, comment and share counts, plus author and music data. No login required.

- **URL**: https://apify.com/toolzerhub/tiktok-scraper.md
- **Developed by:** [ToolzerHub](https://apify.com/toolzerhub) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.62 / 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/platform/actors/running/actors-in-store#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

## TikTok Scraper

Pull TikTok profiles, videos, comments, hashtags, sounds, and follower or following lists from one Actor. Give it a username, a video URL, a hashtag, a sound ID, or a search term, and it returns structured rows — video IDs, captions, play/like/comment/share counts, author and music data. No login required: every request goes through this Actor's own backend, and no TikTok cookie, session token, or credential is ever sent.

### Modes

Set **`scraperType`** to pick what this run collects. Each mode takes its own identifier below the picker.

| Mode | Returns | Needs | Or use the focused Actor |
|---|---|---|---|
| User profile | Full profiles for one or more accounts | `username` (accepts a list of handles or URLs) | [TikTok Profile Scraper](https://apify.com/toolzerhub/tiktok-profile-scraper) |
| User posts | Videos posted by one account | `username` or `sec_user_id` | [TikTok Profile Videos Scraper](https://apify.com/toolzerhub/tiktok-profile-videos-scraper) |
| User followers | Full profiles of an account's followers | `username` or `sec_user_id` | [TikTok Followers Scraper](https://apify.com/toolzerhub/tiktok-followers-scraper) |
| User following | Full profiles of the accounts a user follows | `username` or `sec_user_id` | [TikTok Following Scraper](https://apify.com/toolzerhub/tiktok-following-scraper) |
| Video | One or more videos by ID, URL, or share link | `aweme_id` or `share_url` (both accept lists) | [TikTok Video Scraper](https://apify.com/toolzerhub/tiktok-video-scraper) |
| Video comments | A video's comments, with optional reply threads | `aweme_id` | [TikTok Comments Scraper](https://apify.com/toolzerhub/tiktok-comments-scraper) |
| Video search | Videos matching a keyword | `keyword` | [TikTok Video Search Scraper](https://apify.com/toolzerhub/tiktok-video-search-scraper) |
| Hashtag | A hashtag's stats, with optional current top videos | `tag_name` | [TikTok Hashtag Scraper](https://apify.com/toolzerhub/tiktok-hashtag-scraper) |
| Sound | A sound's metadata, with optional videos using it | `music_id` | [TikTok Sound Scraper](https://apify.com/toolzerhub/tiktok-sound-scraper) |
| User search | Accounts matching a keyword | `keyword` | [TikTok User Search Scraper](https://apify.com/toolzerhub/tiktok-user-search-scraper) |
| Live status | Whether one or more accounts are live right now | `username` (list) or `room_id` | [TikTok Live Status Scraper](https://apify.com/toolzerhub/tiktok-live-status-scraper) |

**`scraperType`** is the only field this Actor marks required. Every other field is mode-specific, so a blank identifier doesn't fail validation — it fails, or empties out, once the run actually starts. **User Profile** and **Video** stop with a clear error (`Provide at least one TikTok username or full profile URL`, `Provide at least one TikTok video ID, full video URL, or share URL`) if their identifier list is empty. Every other mode — Hashtag, Sound, User Search, Video Search, User Posts, Followers, Following, Video Comments, Live Status — runs to completion and logs why it found nothing (`No hashtag found for tag_name=undefined`, for example) instead of erroring. Either way, an empty dataset points you at the run log, not a bug.

### One Actor or eleven?

Each of the eleven modes above is also its own focused Actor, cheaper per result and scoped to a single lookup. Reach for a focused Actor once you know exactly what you're pulling at scale — a profile batch, one account's video history, comments on a known video. Reach for this Actor when a research question spans several of those in one project — a hashtag's top videos plus each poster's profile plus their follower counts, say — because that's one Actor integration and one dataset shape instead of switching between several.

### Input

```json
{
  "scraperType": "userProfile",
  "username": ["https://www.tiktok.com/@khaby.lame"]
}
```

`maxItems` (default `100`, prefill `20`, `0` for no limit) caps every paginated mode: user posts, followers, following, video comments, video search, user search. Profile, video, hashtag, sound, and live status aren't paginated — they return one row per identifier, or a fixed set for the record they describe.

### Output

Field names vary by mode. Across all eleven, the ones you'll see most are:

| Field | Contents |
|---|---|
| **`username`**, **`user_id`**, **`sec_user_id`** | Account identifiers |
| **`nickname`**, **`avatar_url`**, **`is_verified`**, **`is_private`**, **`region`**, **`stats`** | Profile data |
| **`aweme_id`**, **`description`**, **`create_time`** | Video identifiers and caption |
| **`music_info`** | Music metadata attached to a video |
| **`comment_id`**, **`comment_text`**, **`parent_comment_id`**, **`is_reply`** | Comment data |
| **`tag_name`**, **`ch_id`**, **`hashtag_video_count`**, **`hashtag_view_count`** | Hashtag data |
| **`music_id`**, **`music_title`**, **`music_author`**, **`music_usage_count`** | Sound data |
| **`is_live`**, **`room_id`**, **`live_title`**, **`live_started_at`** | Live status data |

```json
{
  "aweme_id": "7530466721379978522",
  "description": "example caption",
  "create_time": 1752480000,
  "stats": { "play_count": 1000000, "digg_count": 50000, "comment_count": 800, "share_count": 300 },
  "music_info": { "title": "original sound", "author": "khaby.lame" }
}
```

### Questions

**What happens if I leave the identifier blank for my mode?**
It depends on the mode. **User Profile** and **Video** throw a clear error naming what's missing. Every other mode finishes the run and saves nothing, with a log line explaining why — Hashtag logs `No hashtag found for tag_name=undefined`, User Followers logs that it couldn't resolve an account, and so on. Neither behavior is a bug; check the run log before assuming the mode is broken.

**Hashtag and Sound returned zero rows, but I know the hashtag exists. Why?**
With the video add-on (`addonHashtagVideos` / `addonMusicVideos`) turned on, the mode fetches the hashtag or sound's current videos *before* yielding anything. If that video fetch comes back empty, the run yields nothing at all — not even the hashtag or sound record itself. Turn the add-on off to get the base record on its own, no video lookup required.

**Can one share link return more than one video?**
Yes, for the Video mode's `share_url` input. A `vt.tiktok.com` or `vm.tiktok.com` link resolves through a different upstream endpoint than an `aweme_id`, and that endpoint returns an array — a single share link has come back with more than one video attached.

**Do the row-level add-ons (Add User Details, Add Video Detail, Add Profile, Add Similar Users) always cost extra?**
Only when they return something. Each is applied per saved row as a follow-up request; if that follow-up fails or comes back empty, you still get the base row and it isn't billed. `addonHashtagVideos` and `addonMusicVideos` work differently — they're charged once per run, not once per video returned.

**Why does User Search only offer "Add Profile Detail" and not "Add Similar Users"?**
That add-on isn't wired to this mode. Followers and Following expose both `addonProfile` and `addonSimilarUsers`; User Search exposes `addonProfile` only.

**How do I check if an account is live without knowing its room ID?**
Pass the username. No public TikTok page — including an account's own `/live` page — exposes a room ID directly, so Live Status resolves the current room and status from the username for you. Passing `room_id` directly skips that lookup if you already have one from elsewhere.

### Related Actors

| Actor | Purpose |
|---|---|
| [TikTok Profile Scraper](https://apify.com/toolzerhub/tiktok-profile-scraper) | Profile lookups by username or URL |
| [TikTok Video Scraper](https://apify.com/toolzerhub/tiktok-video-scraper) | Video lookups by ID, URL, or share link |
| [TikTok Comments Scraper](https://apify.com/toolzerhub/tiktok-comments-scraper) | One video's comments and reply threads |
| [TikTok Hashtag Scraper](https://apify.com/toolzerhub/tiktok-hashtag-scraper) | One hashtag's stats and top videos |
| [TikTok Followers Scraper](https://apify.com/toolzerhub/tiktok-followers-scraper) | One account's follower list |

# Actor input Schema

## `scraperType` (type: `string`):

Choose the dataset for this run, then fill in the section for that mode below.

## `username` (type: `string`):

TikTok username (without @), or a profile URL (https://www.tiktok.com/@<name>).

## `sec_user_id` (type: `string`):

Optional. Leave blank — the secUid is resolved from the Username automatically. Only set this to skip that lookup when you already hold a secUid.

## `addonUserDetails` (type: `boolean`):

Add country lookup and similar-account recommendations to the profile. One extra request.

## `addonProfile` (type: `boolean`):

Fetch the full public web profile for every result and merge it into the base row. One extra request per result.

## `addonSimilarUsers` (type: `boolean`):

Fetch and add TikTok's similar-account recommendations for every result. One extra request per result.

## `aweme_id` (type: `string`):

TikTok video (aweme) ID, or a full video URL (https://www.tiktok.com/@<user>/video/<id>).

## `share_url` (type: `array`):

TikTok share links to resolve, one per line. Full https://vt.tiktok.com/... and https://vm.tiktok.com/... URLs are accepted.

## `maxRepliesPerComment` (type: `integer`):

Maximum replies to save for each top-level comment. Replies also count toward Max Results. Set 0 for no per-comment limit.

## `addonCommentReplies` (type: `boolean`):

Paginate replies and save each as a separate comment row. Replies count toward Max Results.

## `keyword` (type: `string`):

Keyword or phrase to search TikTok for.

## `addonVideoDetails` (type: `boolean`):

Merge the full video detail response into every video row. One extra request per item.

## `tag_name` (type: `string`):

TikTok hashtag name without the # symbol.

## `addonHashtagVideos` (type: `boolean`):

Return each current top video as a separate row with hashtag context. One extra request.

## `music_id` (type: `string`):

A TikTok sound/music ID, or a full sound URL (https://www.tiktok.com/music/<slug>-<id>).

## `addonMusicVideos` (type: `boolean`):

Return each video using this sound as a separate row with music context. One extra request.

## `room_id` (type: `string`):

Optional. A TikTok LIVE room ID, if you already have one. Leave blank and give a Username instead — a room ID appears in no public TikTok URL, so there is normally no way to obtain one by hand.

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

Maximum number of items to save. Set 0 for no limit.

## `region` (type: `string`):

Two-letter region code affecting search/feed results, e.g. US, GB, JP.

## Actor input object example

```json
{
  "scraperType": "userProfile",
  "username": "khaby.lame",
  "addonUserDetails": false,
  "addonProfile": false,
  "addonSimilarUsers": false,
  "aweme_id": "7662422992172911903",
  "share_url": [
    "https://vt.tiktok.com/ZSxxxxxxxx/"
  ],
  "maxRepliesPerComment": 3,
  "addonCommentReplies": false,
  "keyword": "cats",
  "addonVideoDetails": false,
  "tag_name": "cats",
  "addonHashtagVideos": false,
  "addonMusicVideos": false,
  "maxItems": 20,
  "region": "US"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Every record collected during this run

# 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 = {
    "username": "khaby.lame",
    "sec_user_id": "",
    "aweme_id": "7662422992172911903",
    "share_url": [],
    "maxRepliesPerComment": 3,
    "keyword": "cats",
    "tag_name": "cats",
    "music_id": "",
    "room_id": "",
    "maxItems": 20,
    "region": "US"
};

// Run the Actor and wait for it to finish
const run = await client.actor("toolzerhub/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 = {
    "username": "khaby.lame",
    "sec_user_id": "",
    "aweme_id": "7662422992172911903",
    "share_url": [],
    "maxRepliesPerComment": 3,
    "keyword": "cats",
    "tag_name": "cats",
    "music_id": "",
    "room_id": "",
    "maxItems": 20,
    "region": "US",
}

# Run the Actor and wait for it to finish
run = client.actor("toolzerhub/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 '{
  "username": "khaby.lame",
  "sec_user_id": "",
  "aweme_id": "7662422992172911903",
  "share_url": [],
  "maxRepliesPerComment": 3,
  "keyword": "cats",
  "tag_name": "cats",
  "music_id": "",
  "room_id": "",
  "maxItems": 20,
  "region": "US"
}' |
apify call toolzerhub/tiktok-scraper --silent --output-dataset

```

## MCP server setup

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