# Tiktok Scraper (`batscrape/tiktok-scraper`) Actor

Search TikTok by keyword and export unique videos with creator profiles, engagement stats, music, hashtags and media URLs. Sort by relevance or likes, filter by date and region. Cross-keyword dedup, flat pay-per-result pricing, no login or cookies needed.

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

## Pricing

from $1.96 / 1,000 search 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?

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 Search Scraper: Keyword Search with Creator & Engagement Data 🎵

Search TikTok by keyword and export unique videos as clean JSON: creator profiles, engagement stats, music metadata, and media URLs included, with transparent flat per-result pricing. No TikTok account, no login, no cookies required. Perfect for trend research, competitor and brand tracking, hashtag monitoring, influencer discovery, and building structured datasets of short-form video content.

💰 Price: $0.0005 flat per run + $0.00199/video (no separate query fee) 🌏 Coverage: TikTok global keyword search — English, emoji, brand names & keywords all work 📊 Data: Video description, creator profile, engagement stats, music metadata, and signed media URLs 🎯 Filters: Sort (relevance / most liked), publish-time window, region 🛡️ Flat Per-Result Pricing

### Quick Navigation

- [🧭 What Does This Actor Do?](#what-does-this-actor-do)
- [🎬 Features and Functionality](#features-and-functionality)
- [💰 Pricing: Transparent Event-Based Costs](#pricing-transparent-event-based-costs)
- [🌟 Who Needs This?](#who-needs-this)
- [🎵 Input Parameters](#input-parameters)
- [💡 Input Strategy Guide](#input-strategy-guide)
- [🔎 Example Requests](#example-requests)
- [📦 Output](#output)
- [🧩 Custom Map Function](#custom-map-function)
- [🔧 Troubleshooting](#troubleshooting)
- [❔ FAQ](#faq)
- [📞 Contact](#contact)

### 🧭 What Does This Actor Do?

This actor searches TikTok by keyword and pushes results to your dataset as structured JSON — no headless browser, no signing algorithm to maintain, no login wall to work around on your end. Give it one or more keywords and it queues exactly the searches needed, deduplicating across keywords and respecting your `maxItems` cap and pay-per-event budget as it goes.

**🔍 Keyword Search** — search as many keywords as you like in one run (English, brand names, product terms, emoji), each searched independently.

**🎯 Sort & Filter** — relevance or most-liked sort, a publish-time window, and a region setting, so you get exactly the slice of results you are after.

**👤 Creator Data Included** — every result carries the posting creator's profile (username, nickname, follower count, verification status) at no extra charge — no separate profile lookup needed.

### 🎬 Features and Functionality

| Feature                    | Description                                                                 | Benefit                                                      |
| -------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------ |
| 💰 Flat Per-Result Pricing | One price per unique video delivered, no separate query fee                 | Predictable cost — no surprise per-page or per-query charges |
| 🔍 Multi-Keyword Search    | Search as many keywords as you like in one run                              | Broad coverage from a single actor run                       |
| 🧹 Cross-Keyword Dedup     | A video surfaced by two different keywords is stored (and charged) once     | Never pay twice for the same result                          |
| 🎯 Sort & Filter           | Relevance or most-liked sort, publish-time window, region                   | Narrow results down without any extra cost                   |
| 👤 Creator Data Included   | Username, nickname, followers, verification on every result                 | No separate profile lookup needed                            |
| 🔧 Custom Map Function     | JavaScript function to reshape or enrich output on the fly                  | Shape results to match your exact requirements               |
| 💵 Budget-Aware            | Every result is checked against the run's charge budget before it is stored | A run stops cleanly instead of overspending                  |

### 💰 Pricing: Transparent Event-Based Costs

Pay-per-event pricing — no subscription, no hidden fees. A flat run fee, and one charge per unique video actually delivered.

#### Pricing Structure

| Event            | Price (USD) | Charged For                                 |
| ---------------- | ----------- | ------------------------------------------- |
| 🚀 Actor Start   | $0.0005     | Once per run, regardless of input           |
| 📊 Search Result | $0.00199    | Each unique TikTok video actually delivered |

#### How Pricing Works

Every run charges a flat $0.0005 Actor Start fee once, regardless of how many keywords or results you request, then $0.00199 per unique TikTok video actually stored in your dataset — nothing else. A search that returns nothing costs nothing beyond the flat run fee, and the first 2 pages of results (~40 videos) per keyword are free of charge for paying users.

#### 💵 Real-World Pricing Examples

| Use Case                         | Configuration                                    | Total Cost | Breakdown                    |
| -------------------------------- | ------------------------------------------------ | ---------- | ---------------------------- |
| Quick sample                     | 1 keyword, 10 results                            | $0.0204    | $0.0005 + (10 × $0.00199)    |
| Single keyword, default settings | 1 keyword, up to 100 results                     | $0.1995    | $0.0005 + (100 × $0.00199)   |
| Multi-keyword sweep              | 5 keywords, up to 100 results each (~500 unique) | $0.9955    | $0.0005 + (500 × $0.00199)   |
| Large single-keyword pull        | 1 keyword, up to 1,000 results                   | $1.9905    | $0.0005 + (1,000 × $0.00199) |

Result counts vary keyword to keyword — a narrow or low-volume keyword simply returns fewer unique results (and costs less) than a popular one; the rows above are illustrative at the volumes shown.

### 🌟 Who Needs This?

- **📈 Social media marketers** — track trending TikTok content under any keyword or campaign term.
- **🏷️ Brands & competitors** — monitor how competitor keywords or branded hashtags perform across creators.
- **🎓 Academic researchers** — build structured datasets of short-form video data for consumption pattern analysis.
- **🤝 Influencer agencies** — evaluate creator reach and engagement rates at scale before outreach.
- **📰 Journalists & analysts** — cover social media trends with verifiable, structured data.
- **🛒 E-commerce teams** — surface product-related user-generated content for campaigns and social proof.

### 🎵 Input Parameters

| Field               | Description                                                                                                                                                                          | Default     |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
| `keywords`          | Search keywords (one per line). Each keyword is searched independently; results are deduplicated across keywords so you never pay twice for the same video. Required (at least one). | —           |
| `maxItems`          | Maximum number of videos to collect across all keywords combined. Range: 1–10,000.                                                                                                   | `100`       |
| `sortType`          | `RELEVANCE` (relevance) / `MOST_LIKED` (most liked).                                                                                                                                 | `RELEVANCE` |
| `publishTime`       | `ALL` / `ONE_DAY` / `ONE_WEEK` / `ONE_MONTH` / `THREE_MONTHS` / `HALF_YEAR`.                                                                                                         | `ALL`       |
| `region`            | ISO 3166-1 alpha-2 country code to scope results (e.g. `US`, `GB`, `DE`).                                                                                                            | `US`        |
| `customMapFunction` | `(object) => object` applied to every item. Must not be used for filtering.                                                                                                          | (none)      |

### 💡 Input Strategy Guide

**Just want a quick sample?** Set `maxItems` to 10–20 and run a single keyword — a cheap, fast check that the actor and your keyword return what you expect. The first 2 pages (~40 results) per keyword are free for paying users, so a small test costs only the $0.0005 run fee.

**Tracking a trend or campaign term?** Use `sortType: MOST_LIKED` to surface the highest-engagement content, or `publishTime: ONE_WEEK` with `sortType: RELEVANCE` to focus on recently posted videos relevant to your keyword.

**Researching several brands or competitors in one run?** List every keyword up front. Cross-keyword dedup means an overlapping result is never charged twice, so batching keywords into one run costs the same as running them separately, minus the duplicates.

**Need region-specific content?** Set `region` to the relevant ISO country code (e.g. `GB` for the UK, `DE` for Germany). The default is `US`.

### 🔎 Example Requests

Search one keyword for travel content, sorted by most liked:

```json
{
    "keywords": ["travel"],
    "sortType": "MOST_LIKED",
    "maxItems": 100
}
```

Track a trend term's newest videos from the last week:

```json
{
    "keywords": ["summer fashion"],
    "sortType": "RELEVANCE",
    "publishTime": "ONE_WEEK",
    "maxItems": 50
}
```

Sweep several brand keywords in one run (cross-keyword dedup applies automatically):

```json
{
    "keywords": ["nike", "adidas", "puma"],
    "sortType": "MOST_LIKED",
    "publishTime": "ONE_MONTH",
    "region": "US",
    "maxItems": 500
}
```

### 📦 Output

One dataset item per unique TikTok video. A keyword that returns no matches simply contributes no items — it is not stored as a placeholder row.

Example item (field values illustrative — no real run output was captured; values are built from the output schema and field list):

```json
{
    "id": "7318492016453829893",
    "url": "https://www.tiktok.com/@adventureseeker/video/7318492016453829893",
    "description": "Best hidden beaches in Southeast Asia 🌊 #travel #beach #adventure",
    "descriptionLanguage": "en",
    "createTime": 1705420800,
    "createDate": "2024-01-16",
    "awemeType": 0,
    "isAiGenerated": false,
    "region": null,
    "authorMeta": {
        "id": "6841234567890123456",
        "secUid": "MS4wLjABAAAA…",
        "name": "adventureseeker",
        "nickname": "Adventure Seeker",
        "followerCount": 284500,
        "followingCount": 312,
        "heartCount": 0,
        "videoCount": 0,
        "verified": false,
        "avatar": "https://p16-sign.tiktokcdn-us.com/…"
    },
    "videoMeta": {
        "width": 1080,
        "height": 1920,
        "ratio": "540p",
        "duration": 42,
        "coverUrl": "https://p16-sign.tiktokcdn-us.com/…",
        "dynamicCoverUrl": "https://p16-sign.tiktokcdn-us.com/…",
        "playUrl": "https://v19-webapp.tiktok.com/…"
    },
    "statistics": {
        "likeCount": 48200,
        "commentCount": 1340,
        "shareCount": 2870,
        "playCount": 612000,
        "collectCount": 5100
    },
    "musicMeta": {
        "id": "6978234567890123456",
        "title": "Summer Vibes",
        "author": "ChillBeats",
        "playUrl": "https://sf16-ies-music.tiktokcdn.com/…"
    },
    "hashtags": ["travel", "beach", "adventure"],
    "searchKeyword": "travel",
    "inputKeyword": "travel"
}
```

Non-obvious fields:

- `videoMeta.playUrl` — a CDN-signed URL that expires within approximately 24 hours. Fetch or download the video promptly after collecting results; the URL will not be valid indefinitely.
- `region` — scoped by the `region` input parameter, not the creator's country. This field is not reliably returned by the search endpoint and may be `null`.
- `authorMeta.heartCount` / `authorMeta.videoCount` — these fields may return `0` for all items via the search endpoint; they are not reliably populated in search responses.
- `authorMeta.name` — the creator's `@username` handle (used in the URL). `authorMeta.nickname` is the display name shown in the TikTok UI.
- `hashtags` — a flat array of hashtag strings (without the `#` prefix) extracted from the video's challenge list.
- `searchKeyword` / `inputKeyword` — the keyword that retrieved this video, stamped by the extractor for traceability.

See [`tests/schemas/video.schema.js`](tests/schemas/video.schema.js) for the validated shape.

### 🧩 Custom Map Function

A synchronous `(object) => object` function applied to every dataset item. Use it only to **add or reshape** fields:

```js
(object) => {
    return {
        ...object,
        isViral: (object.statistics?.likeCount || 0) > 50000,
    };
};
```

Rules enforced by the actor (a violation is logged and the function is ignored — the run never crashes):

- **No filtering.** Returning `null`, `{}` or a non-object falls back to the original item.
- **No date-based logic.** Sources containing `new Date`, `Date.now` or `1970` are rejected.
- **Synchronous only.** `async` / generator functions and returned Promises are rejected.

### 🔧 Troubleshooting

#### ❓ Getting Few or No Results?

- ✅ Check `maxItems` — the run stops once this cap is reached
- ✅ Check the charge budget — a run that cannot afford another result stops cleanly rather than erroring
- ✅ Try a broader or more common keyword — a very narrow keyword may simply have little content on TikTok
- ✅ Confirm `keywords` is not empty — at least one keyword is required
- ✅ Check your `publishTime` setting — a very narrow window combined with a niche keyword can return zero results

#### 💰 Unexpected Costs?

Remember: every run charges a flat $0.0005 Actor Start fee once, no matter what you ask for. Beyond that, cost is purely $0.00199 × unique videos delivered — there is no separate per-keyword or per-page fee to budget for. The first 2 pages (~40 results) per keyword are free for paying users.

#### 💡 Want to Minimize Costs?

- ✅ Set `maxItems` to only what you actually need
- ✅ Use `publishTime` to narrow results to the relevant window — fewer pages to paginate means faster runs
- ✅ Batch related keywords into one run — cross-keyword dedup means overlaps are never charged twice

### ❔ FAQ

**Do I need a TikTok account or login to use this actor?**
No — searches run through a backend service using only public data; no TikTok account, login, or cookies are required on your end.

**Should I enter keywords with or without the `#` symbol?**
Enter keywords without `#` (e.g. `travel`, not `#travel`). The search endpoint treats them as plain text search terms.

**Is creator data included in the price?**
Yes, at no extra charge — every result includes the creator's profile (username, nickname, follower count, verification status).

**Does this actor download videos?**
No — it returns each video's metadata and a signed play URL, but does not download or store video files itself. The play URL expires within approximately 24 hours, so fetch the file promptly if you need it.

**What is included at no extra charge for paying users?**
The first 2 pages of results (~40 videos) per keyword per run are free. You only start paying the $0.00199/video rate from the third page onward.

**Can I extract data from a specific country's TikTok feed?**
Yes — set the `region` field to an ISO 3166-1 alpha-2 country code (e.g. `GB`, `DE`, `JP`) to scope search results to that region.

### 📞 Contact

Reach out to the maintainers directly for support.

- ✉️ Email: batscrape@gmail.com
- 💬 Discord: discord.com/invite/ZRANXwhWU
- 🐦 X (Twitter): x.com/batscrape
- 🛒 Apify: apify.com/batscrape

# Actor input Schema

## `keywords` (type: `array`):

Search keywords (one per line). Each keyword is searched independently; results are deduplicated across keywords so you never pay twice for the same video.

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

Maximum number of videos to collect across all keywords combined.

## `sortType` (type: `string`):

Result order.

## `publishTime` (type: `string`):

Restrict results to videos published within this time window.

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

ISO 3166-1 alpha-2 country code to scope results (e.g. US, GB, DE).

## `customMapFunction` (type: `string`):

A function that takes each output object and returns a transformed object. MUST NOT be used for filtering — accounts using it for filtering may be banned. Leave empty to store items unchanged.

## Actor input object example

```json
{
  "keywords": [
    "travel"
  ],
  "maxItems": 100,
  "sortType": "RELEVANCE",
  "publishTime": "ALL",
  "region": "US",
  "customMapFunction": "(object) => { return {...object} }"
}
```

# Actor output Schema

## `overview` (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 = {
    "keywords": [
        "travel"
    ],
    "maxItems": 100,
    "region": "US",
    "customMapFunction": (object) => { return {...object} }
};

// Run the Actor and wait for it to finish
const run = await client.actor("batscrape/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 = {
    "keywords": ["travel"],
    "maxItems": 100,
    "region": "US",
    "customMapFunction": "(object) => { return {...object} }",
}

# Run the Actor and wait for it to finish
run = client.actor("batscrape/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 '{
  "keywords": [
    "travel"
  ],
  "maxItems": 100,
  "region": "US",
  "customMapFunction": "(object) => { return {...object} }"
}' |
apify call batscrape/tiktok-scraper --silent --output-dataset

```

## MCP server setup

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