# TikTok Scraper - Videos, Profiles, Hashtags & Trends (`aiscraperdev/scrape-tiktok-videos-profiles-hashtags`) Actor

Extract TikTok videos, profiles, hashtags, and search results without login. Filter by date range, likes, and engagement. Get captions, stats, music info, and optional AI transcription. Export structured JSON/CSV. Fast, reliable, no authentication required.

- **URL**: https://apify.com/aiscraperdev/scrape-tiktok-videos-profiles-hashtags.md
- **Developed by:** [Randeep Dhillon](https://apify.com/aiscraperdev) (community)
- **Categories:** Social media, Videos, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 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/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

Scrape publicly available TikTok data (videos, user profiles, hashtags, and search results) at scale **without requiring TikTok login credentials or API keys**.

Designed using **Crawlee + Playwright** to intercept XHR/Fetch network responses directly from TikTok's internal APIs, bypassing DOM obfuscation and bot mitigation.

***

### Features

- 🎥 **Video & Post Scraping**: Extract captions, upload timestamps, author metadata, audio track metadata, video engagement stats (likes, shares, comments, plays), hashtags, video/cover URLs, and optional AI subtitles.
- 👤 **Profile Scraping**: Extract user bio, follower count, following count, total video count, total heart/like count, verification status, and avatar image URLs.
- \#️⃣ **Hashtag Scraping**: Extract hashtag name, total video count, and total view count.
- 🔍 **Search Query Scraping**: Search TikTok by keywords targeting Videos (`/video`) or Users (`/user`).
- ⚡ **Priority Processing Logic**: Automatically prioritizes direct `postURLs` first when provided, before processing `profiles`, `hashtags`, or `searchQueries`.
- 🎯 **Date & Engagement Filtering**: Filter posts early by relative age (e.g. `'7 days'`, `'2 weeks'`, `'1 month'`), ISO dates, minimum likes (`leastDiggs`), or maximum likes (`mostDiggs`) to save compute & storage.
- 💾 **Binary Media Downloads**: Download full-resolution video binaries, covers, avatars, and audio covers directly into Apify Key-Value Store.
- 🤖 **Optional AI Transcription**: Decoupled AI subtitle transcription mode (`downloadSubtitlesOptions: "TRANSCRIBE_ALL_VIDEOS"`).
- 🚨 **Machine-Readable Error Emission**: Never fails silently — emits explicit error records (`PROFILE_PRIVATE`, `NOT_FOUND`, `POST_SENSITIVE`, `RATE_LIMITED`) with full context.

***

### How to Use

#### Step 1 — Define your target inputs

Specify any combination of:

- **`postURLs`**: Array of direct video links (highest priority execution).
- **`profiles`**: Array of TikTok usernames (e.g. `["khaby.lame", "tiktok"]`).
- **`hashtags`**: Array of hashtag names (without `#`).
- **`searchQueries`**: Array of raw search terms (with mandatory `searchSection` set to `"/video"` or `"/user"`).

#### Step 2 — Configure filters & media options

- Filter by date (`oldestPostDateUnified`, `newestPostDate`).
- Filter by engagement (`leastDiggs`, `mostDiggs`).
- Enable binary downloads (`shouldDownloadVideos`, `shouldDownloadCovers`, `shouldDownloadAvatars`).
- Enable AI transcription (`downloadSubtitlesOptions`).

#### Step 3 — Run & Export

Click **Start** and export your structured dataset in **JSON, CSV, Excel, or JSONL**.

***

### Input Reference

```json
{
  "postURLs": [
    "https://www.tiktok.com/@tiktok/video/7123456789012345678"
  ],
  "profiles": [
    "khaby.lame"
  ],
  "hashtags": [
    "fitness"
  ],
  "searchQueries": [
    "gym workout"
  ],
  "searchSection": "/video",
  "resultsPerPage": 30,
  "oldestPostDateUnified": "7 days",
  "newestPostDate": "2026-12-31",
  "mostDiggs": 500000,
  "leastDiggs": 1000,
  "shouldDownloadVideos": false,
  "shouldDownloadCovers": false,
  "shouldDownloadAvatars": false,
  "shouldDownloadMusicCovers": false,
  "downloadSubtitlesOptions": "NONE",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

***

### Sample Outputs

#### 1. Video / Post Output

```json
{
  "id": "7123456789012345678",
  "url": "https://www.tiktok.com/@tiktok/video/7123456789012345678",
  "text": "Try out this new trend! #fitness #fyp",
  "createTime": "2025-01-15T12:00:00.000Z",
  "authorMeta": {
    "username": "tiktok",
    "nickname": "TikTok",
    "verified": true,
    "followerCount": 80000000,
    "followingCount": 500,
    "videoCount": 1200
  },
  "musicMeta": {
    "musicName": "Original Sound - TikTok",
    "musicAuthor": "TikTok",
    "playUrl": "https://v16-webapp-prime.tiktok.com/music.mp3"
  },
  "stats": {
    "diggCount": 150000,
    "shareCount": 2000,
    "commentCount": 3500,
    "playCount": 2500000
  },
  "hashtags": [
    "fitness",
    "fyp"
  ],
  "videoUrl": "https://v16-webapp-prime.tiktok.com/video.mp4",
  "coverUrl": "https://p16-sign-va.tiktokcdn.com/cover.jpeg",
  "subtitles": null,
  "isAd": false
}
```

#### 2. Profile Output

```json
{
  "username": "khaby.lame",
  "nickname": "Khabane Lame",
  "bio": "If u wanna laugh u are in the right place bro",
  "verified": true,
  "followerCount": 162000000,
  "followingCount": 78,
  "videoCount": 1150,
  "heartCount": 2500000000,
  "avatarUrl": "https://p16-sign-va.tiktokcdn.com/avatar.jpeg"
}
```

#### 3. Hashtag Output

```json
{
  "name": "fitness",
  "videoCount": 4500000,
  "viewCount": 98000000000
}
```

#### 4. Error Object Example

```json
{
  "targetUrl": "https://www.tiktok.com/@privateaccount",
  "errorCode": "PROFILE_PRIVATE",
  "message": "Profile @privateaccount is private or restricts access"
}
```

***

### Data Field Specification

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | String | null | Unique TikTok Video ID |
| `url` | String | null | Canonical TikTok Video URL |
| `text` | String | null | Caption / description text |
| `createTime` | String | null | ISO 8601 creation date |
| `authorMeta` | Object | Author profile metadata (username, nickname, verified, counts) |
| `musicMeta` | Object | Audio track metadata (musicName, musicAuthor, playUrl) |
| `stats` | Object | Engagement counts (diggCount, shareCount, commentCount, playCount) |
| `hashtags` | Array | List of extracted hashtag strings |
| `videoUrl` | String | null | Direct video URL or Key-Value Store asset URL |
| `coverUrl` | String | null | Direct cover URL or Key-Value Store asset URL |
| `subtitles` | String | null | AI transcribed text or WebVTT transcript |
| `isAd` | Boolean | Whether the video is a sponsored advertisement |

***

### FAQ & Support

- **Does this scraper require a TikTok account?**\
  No, it operates entirely on public endpoints without credentials or session cookies.

- **How do relative date filters work?**\
  You can set `oldestPostDateUnified` to `'7 days'`, `'2 weeks'`, `'1 month'`, or an ISO date `'YYYY-MM-DD'`. The scraper automatically filters out older content before pushing records to the dataset.

- **For custom features or issues:**\
  Open an issue in the **Issues** tab on Apify Console.

# Actor input Schema

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

List of TikTok usernames to scrape (without the @ symbol).

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

List of direct TikTok video URLs (processed with highest priority if provided).

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

List of hashtag names to scrape (without the # symbol).

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

List of search terms to query on TikTok search.

## `searchSection` (type: `string`):

Search tab section to target. Required if searchQueries is used.

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

Maximum number of video posts/items to extract per profile or target.

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

Exclude pinned posts from the scraped video feed.

## `oldestPostDateUnified` (type: `string`):

Filter out posts older than this date (ISO string 'YYYY-MM-DD' or relative age like '7 days', '2 weeks', '1 month').

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

Filter out posts newer than this date (ISO string 'YYYY-MM-DD').

## `mostDiggs` (type: `integer`):

Maximum number of diggs/likes for posts to include (null or empty for unlimited).

## `leastDiggs` (type: `integer`):

Minimum number of diggs/likes required for posts to include.

## `shouldDownloadVideos` (type: `boolean`):

Download full-resolution video binaries and store in Key-Value Store.

## `shouldDownloadCovers` (type: `boolean`):

Download video thumbnail covers and store in Key-Value Store.

## `shouldDownloadAvatars` (type: `boolean`):

Download profile avatar images and store in Key-Value Store.

## `shouldDownloadMusicCovers` (type: `boolean`):

Download audio track cover images and store in Key-Value Store.

## `downloadSubtitlesOptions` (type: `string`):

Optional AI transcription mode for generating or extracting audio subtitles.

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

Apify Proxy configuration for anti-bot bypass and IP rotation.

## Actor input object example

```json
{
  "profiles": [
    "khaby.lame"
  ],
  "postURLs": [],
  "hashtags": [],
  "searchQueries": [],
  "searchSection": "/video",
  "resultsPerPage": 100,
  "excludePinnedPosts": false,
  "oldestPostDateUnified": "",
  "newestPostDate": "",
  "shouldDownloadVideos": false,
  "shouldDownloadCovers": false,
  "shouldDownloadAvatars": false,
  "shouldDownloadMusicCovers": false,
  "downloadSubtitlesOptions": "NONE",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (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"
    ],
    "postURLs": [],
    "hashtags": [],
    "searchQueries": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("aiscraperdev/scrape-tiktok-videos-profiles-hashtags").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"],
    "postURLs": [],
    "hashtags": [],
    "searchQueries": [],
}

# Run the Actor and wait for it to finish
run = client.actor("aiscraperdev/scrape-tiktok-videos-profiles-hashtags").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ],
  "postURLs": [],
  "hashtags": [],
  "searchQueries": []
}' |
apify call aiscraperdev/scrape-tiktok-videos-profiles-hashtags --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=aiscraperdev/scrape-tiktok-videos-profiles-hashtags",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/IOSSVGeU7Lfa0iMEQ/builds/DsehidQoBEfn8ExsS/openapi.json
