# TikTok Scraper - Videos, Hashtags, Profiles & Transcripts (`topapi/tiktok-scraper`) Actor

Scrape TikTok videos by profile, hashtag, search keyword or video URL: caption, plays, likes, comments, shares, saves, engagement rate, publish date, author stats, sound, resolution, download and subtitle links, optional transcript. Date, like, ad and pinned filters, monitor mode.

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

## Pricing

from $0.28 / 1,000 post scrapeds

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

### What does TikTok Scraper do?

**TikTok Scraper** extracts TikTok videos from [tiktok.com](https://www.tiktok.com) and turns a profile, a hashtag or a video URL into structured rows: one post per row with its caption, plays, likes, comments, shares, saves, publish date, author stats, sound, video files and, as an add-on, the transcript of what is said in the video. Built for social-media analysts, influencer-marketing teams, brand monitors and researchers who need every TikTok post of an account or a topic, or only the new ones since yesterday, without scrolling the app.

TikTok Scraper - TikTok Video Scraper - TikTok Transcript Scraper - TikTok Hashtag Scraper - TikTok Profile Scraper

<a href="https://console.apify.com/actors/FvveLWu32hLkxgAf4"><img src="https://api.apify.com/v2/key-value-stores/qNQ9zP0xaj2yxGeMY/records/tiktok-scraper-source.png" alt="TikTok profile page with its video grid that TikTok Scraper turns into rows" style="width:70%"></a>

- **Transcripts next to the stats:** the spoken text of the video from TikTok's own caption files (creator captions or TikTok's speech recognition) in a `transcript` field, no AI cost and no separate tool - 68% of posts on a 25-post platform run had one.
- **Profiles, hashtags and video URLs, one row shape:** profiles (videos or reposts), hashtags and direct video or photo-post URLs, all in one run, all delivering the same fields. Words in **Search queries** are read as the public hashtag feed for the same words, because TikTok shows keyword search only after login; the run says so (see Limits).
- **Every number the post shows:** plays, likes, comments, shares, saves and reposts, plus a computed `engagementRate`, exact `createTimeISO`, duration, resolution and the cover image.
- **The author on every row:** username, nickname, verified badge, bio, followers, total likes and video count; on profile runs also the bio link and seller flag.
- **Filters:** date window, minimum likes, exclude ads and paid partnerships, exclude pinned posts, videos-only or photo-posts-only, keyword filter.
- **No login, cookies or TikTok API key:** paste names, tags, keywords or URLs and nothing else.
- **Monitor mode for schedules:** each run delivers only posts it has not delivered before; a profile checked daily costs one page.
- **Export anywhere:** JSON, CSV, Excel, XML, RSS; schedules, webhooks, Make, Zapier, n8n, Google Sheets, Slack; Apify API and MCP server, with a `compact` mode for AI agents.

### What data can you get from TikTok?

<table>
<tr>
<td>🆔 Post id and URL (`id`, `webVideoUrl`)</td>
<td>📝 Caption and its language (`text`, `textLanguage`)</td>
<td>📅 Publish time (`createTime`, `createTimeISO`)</td>
</tr>
<tr>
<td>▶️ Plays (`playCount`)</td>
<td>❤️ Likes (`diggCount`)</td>
<td>💬 Comments (`commentCount`)</td>
</tr>
<tr>
<td>🔁 Shares and reposts (`shareCount`, `repostCount`)</td>
<td>🔖 Saves (`collectCount`)</td>
<td>📈 Engagement rate (`engagementRate`, percent of plays)</td>
</tr>
<tr>
<td>👤 Author: username, nickname, verified, bio, bio link, avatar (`authorMeta`)</td>
<td>👥 Author stats: followers, following, total likes, videos (`authorMeta.fans`, `.heart`, `.video`)</td>
<td>🎵 Sound: name, artist, original flag, sound id, play URL (`musicMeta`)</td>
</tr>
<tr>
<td>🎬 Video: duration, width, height, definition, format, cover, play and download URLs (`videoMeta`)</td>
<td>🔤 Subtitle files per language (`videoMeta.subtitleLinks`) and transcript text (`transcript`, add-on)</td>
<td>#️⃣ Hashtags with ids (`hashtags`) and mentions (`mentions`, `detailedMentions`)</td>
</tr>
<tr>
<td>🖼️ Photo posts: `isSlideshow`, image links (`slideshowImageLinks`)</td>
<td>📢 Ad and paid-partnership flags (`isAd`, `isSponsored`), pinned flag (`isPinned`)</td>
<td>📍 Tagged place (`poi`), attached links (`anchors`), TikTok Shop flag (`hasTikTokShopProduct`)</td>
</tr>
<tr>
<td>🏷️ Content category labels (`diversificationLabels`, `categoryType`)</td>
<td>🤖 AI-generated label (`isAIGC`, `aigcLabel`)</td>
<td>⚙️ Duet, stitch, share and comment settings</td>
</tr>
</table>

On a 25-post run on the Apify platform (profile @tiktok, #cooking, the query "cooking recipes" and one video URL) every row had the id, caption, publish time, all six engagement counts, the author's name and stats, the sound, the cover image and the video file links; 72% carried subtitle files, 68% hashtags, 44% mentions and 24% on-screen text stickers. Photo slideshows (`isSlideshow`, no video file) were about 1 in 100 posts across 208 captured hashtag and profile posts.

### How to scrape TikTok with TikTok Scraper

1. [Create a free Apify account](https://console.apify.com/sign-up) - $5 of monthly credit, no card needed.
2. Open [TikTok Scraper](https://apify.com/topapi/tiktok-scraper) and click **Try for free**.
3. Paste usernames into **Profiles**, tags into **Hashtags** or video links into **Video URLs** (words in **Search queries** are read as the matching hashtag feed), switch on **Include transcript** for the spoken text, and set **Max posts per profile, hashtag or search**.
4. Click **Start**. Posts stream into the dataset as TikTok serves them, about 30 per feed page.
5. Open the **Storage** tab and **Export** as JSON, CSV or Excel - or let a schedule run it for you with **Only new posts since the last run** switched on.

### ⬇️ Input

| Parameter | Type | Description |
|---|---|---|
| **🔍 What to scrape** (fill any of the four; URLs are routed by what they are) | | |
| `profiles` | List | Usernames or profile URLs: `tiktok`, `@zachking`, `https://www.tiktok.com/@khaby.lame`. Newest videos first, about 35 per feed page |
| `hashtags` | List | Hashtags or tag URLs: `cooking`, `#fyp`, `https://www.tiktok.com/tag/dance` |
| `searchQueries` | List | Keywords or search URLs: `cooking recipes`, `ai tools 2026`. TikTok login-walls keyword search, so a query is read as the hashtag feed for the same words (`#cookingrecipes`); rows carry `searchQuery` and `searchHashtag` |
| `postURLs` | List | Video or photo-post URLs, short links or bare ids: `https://www.tiktok.com/@zachking/video/7095025543627705643`, `https://vm.tiktok.com/ZMabc123/`, `7095025543627705643` |
| **🎯 Filters** (applied by TikTok) | | |
| `profileSection` | Select | `videos` (the creator's own posts) or `reposts` (videos the creator reposted; `authorMeta` is the original creator). Default: `videos` |
| `profileSorting` | Select | `latest` (complete, newest-first), `popular` (TikTok's Popular order), `oldest` (oldest video first). Default: `latest` |
| **✂️ Refine results** | | |
| `oldestPostDate` | String | Only posts published after: `2026-09-01`, `7 days`, `3 weeks`, or a day count (`1` = today). On a latest-first profile the run stops at the first page older than this |
| `newestPostDate` | String | Only posts published before: `2026-06-30`, `30 days` |
| `leastDiggs` | Integer | Minimum likes, e.g. `10000`. Default `0` |
| `excludePinnedPosts` | Boolean | Skip posts pinned to the top of a profile. Default `false` |
| `excludeAds` | Boolean | Skip ads and paid partnerships (`isAd`, `isSponsored`). Default `false` |
| `postType` | Select | `all`, `video` (skip photo slideshows) or `photo` (slideshows only). Default `all` |
| `keywordFilter` | String | Keep posts whose caption, hashtags, on-screen text or author name contain the word(s), comma = any: `giveaway`, `recipe, meal prep` |
| **➕ Extra data** | | |
| `includeTranscript` | Boolean | Adds `transcript`, `transcriptLanguage`, `transcriptSource` from TikTok's caption file - charged as the **transcript** event only for posts that receive one. Default `false` |
| **🔁 Monitoring** | | |
| `monitorMode` | Boolean | Deliver only posts not delivered by previous runs with the same `monitorStoreName`. Pair with a daily schedule. Default `false` |
| `monitorStoreName` | String | Key-value store that keeps the per-target memory. Default `tiktok-posts-monitor` |
| **📦 Output** | | |
| `resultsPerPage` | Integer | Max posts per profile, hashtag or search after filters. `0` = everything TikTok serves. Default `30` (prefill `10`) |
| `maxItems` | Integer | Hard cap for the whole run. `0` = no total cap. Default `0` |
| `compact` | Boolean | Core fields only (id, text, date, URL, author, counts, engagement rate, duration, hashtags, transcript), sized for AI agents and MCP. Default `false` |
| **⚙️ Advanced** | | |
| `proxyConfiguration` | Proxy | Default: Apify Proxy, RESIDENTIAL group. With this default, feeds are read through Apify datacenter proxies first and through the residential group only when TikTok refuses those; video pages and subtitles go through datacenter proxies automatically. Custom proxies are used as given |

#### Input JSON

```json
{
  "profiles": ["tiktok", "https://www.tiktok.com/@zachking"],
  "hashtags": ["cooking"],
  "searchQueries": ["cooking recipes"],
  "postURLs": ["https://www.tiktok.com/@zachking/video/7095025543627705643"],
  "resultsPerPage": 30,
  "oldestPostDate": "30 days",
  "excludeAds": true,
  "includeTranscript": true
}
```

#### Give it the name, not the search for the name

A profile is `zachking` or `@zachking` or the profile URL; a hashtag is `cooking` or `#cooking`; only free text goes into **Search queries**, where it is read as the hashtag feed for the same words. **Do:** `profiles: ["zachking"]` · **Don't:** `searchQueries: ["zachking"]` (that reads the `#zachking` hashtag feed: other people's videos tagged with the name, not his own posts).

#### Use latest-first for anything complete, scheduled or date-bounded

TikTok's profile feed is newest-first, so `oldestPostDate` and `monitorMode` can stop reading as soon as a page is older than the floor or the last run's newest post. Hashtag feeds (and search queries, which are served as hashtag feeds) are TikTok's ranking: the date window still applies, but the whole page is read first, so set `resultsPerPage` to what you actually need.

#### A video URL is the cheapest way to refresh known posts

Each URL in `postURLs` is one HTML page fetched through a datacenter proxy, no browser session, and returns the same row shape, plus `locationCreated` (the country the post was made in), which TikTok only publishes on the video page. Short links (`vm.tiktok.com/...`, `tiktok.com/t/...`) are resolved first.

### ⬆️ Output

Every TikTok post becomes one dataset item. Here is the table view of a platform run (profile @tiktok, #cooking and one video URL, transcript add-on on):

<a href="https://console.apify.com/actors/FvveLWu32hLkxgAf4"><img src="https://api.apify.com/v2/key-value-stores/qNQ9zP0xaj2yxGeMY/records/tiktok-scraper-output.png" alt="TikTok Scraper output table with plays, likes, comments, shares, saves and transcript per video" style="width:70%"></a>

And one row as JSON (long URL fields shortened):

```json
{
  "id": "7095025543627705643",
  "text": "#answer to @spidermark790",
  "textLanguage": "en",
  "createTimeISO": "2022-05-07T15:22:45.000Z",
  "locationCreated": "US",
  "authorMeta": { "name": "zachking", "nickName": "Zach King", "verified": true, "fans": 86900000, "heart": 1300000000, "video": 618, "profileUrl": "https://www.tiktok.com/@zachking" },
  "musicMeta": { "musicName": "original sound", "musicAuthor": "Zach King", "musicOriginal": true, "musicId": "7095025525487962926", "duration": 18 },
  "webVideoUrl": "https://www.tiktok.com/@zachking/video/7095025543627705643",
  "videoMeta": { "height": 1024, "width": 576, "duration": 18, "definition": "540p", "format": "mp4", "coverUrl": "https://p16-sign.tiktokcdn-us.com/...", "downloadAddr": "https://v16-webapp-prime.tiktok.com/...", "subtitleLinks": [{ "language": "eng-US", "source": "ASR", "downloadLink": "https://v16-webapp.tiktok.com/..." }] },
  "playCount": 27100000, "diggCount": 1400000, "commentCount": 13200, "shareCount": 16600, "collectCount": 47672, "repostCount": 0,
  "engagementRate": 5.45,
  "hashtags": [{ "id": "92758", "name": "answer", "title": "", "cover": "" }],
  "mentions": ["@spidermark790"],
  "isAd": false, "isSponsored": false, "isSlideshow": false, "isPinned": false,
  "diversificationLabels": ["Professional Special Effects"],
  "transcript": "you like my costume? so cool how are you doing that...",
  "transcriptLanguage": "eng-US",
  "submittedVideoUrl": "https://www.tiktok.com/@zachking/video/7095025543627705643",
  "scrapedAt": "2026-10-03T07:25:11.450Z"
}
```

#### Fields

| Field | Type | What it is | Fill on a 25-post platform run |
|---|---|---|---|
| `id`, `webVideoUrl` | string | Post id and canonical URL (`/photo/` for slideshows) | 100% |
| `text`, `textLanguage` | string | Caption and TikTok's language code | 100% |
| `createTime`, `createTimeISO` | integer, string | Publish time, Unix seconds and ISO 8601 | 100% |
| `playCount`, `diggCount`, `commentCount`, `shareCount`, `collectCount`, `repostCount` | integer | Plays, likes, comments, shares, saves, reposts | 100% |
| `engagementRate` | number | (likes + comments + shares + saves) / plays, in percent | 100% |
| `authorMeta` | object | `id`, `name`, `nickName`, `profileUrl`, `verified`, `signature`, `avatar`, `secUid`, `privateAccount`, `following`, `friends`, `fans`, `heart`, `video`, `digg`; on profile runs also `bioLink`, `commerceUserInfo`, `ttSeller`, `region`, `roomId` | 100% (bioLink 32%: the profile rows) |
| `musicMeta` | object | `musicName`, `musicAuthor`, `musicOriginal`, `musicAlbum`, `musicId`, `duration`, `playUrl`, `coverMediumUrl`, `isCopyrighted`, `isCommerceMusic` | 100% |
| `videoMeta` | object | `height`, `width`, `duration`, `definition`, `format`, `bitrate`, `codecType`, `size`, `coverUrl`, `originalCoverUrl`, `dynamicCoverUrl`, `playAddr`, `downloadAddr`, `subtitleLinks[]` | 100% (file links on every video; photo posts have none) |
| `mediaUrls` | array | Direct media URLs (expire after a few hours) | 100% |
| `hashtags`, `mentions`, `detailedMentions` | array | Hashtags with ids; mentioned accounts with id, secUid and profile URL | 68% / 44% |
| `isSlideshow`, `slideshowImageLinks` | boolean, array | Photo posts and their image links | 0% in this run; about 1% of 208 captured posts |
| `isAd`, `isSponsored`, `isPinned` | boolean | TikTok's ad flag, paid-partnership flag, pinned-to-profile flag | flags; 1 of 25 here, 15% of brand-account posts on a 210-post sample |
| `subtitleLanguages`, `transcript`, `transcriptLanguage`, `transcriptSource` | array, string | Caption languages; the transcript text (add-on) | subtitle files 72%, transcript 68% |
| `poi`, `anchors`, `hasTikTokShopProduct` | object, array, boolean | Tagged place; attached links (CapCut templates, shop products); shop flag | 0% / 24% / 0% here (poi 3% of 208 captured posts) |
| `diversificationLabels`, `categoryType`, `isAIGC`, `aigcLabel` | array, integer, boolean, string | TikTok's content category labels and AI-generated label | labels 4% (video URL rows only), category 100% |
| `duetEnabled`, `stitchEnabled`, `shareEnabled`, `commentsDisabled` | boolean | Interaction settings | 100% |
| `input`, `fromProfileSection`, `searchQuery`, `searchHashtag`, `submittedVideoUrl` | string | Which input produced the row | 100% |

### How can I use TikTok data?

- 🎯 **Influencer-marketing teams** - pull the last 30 videos of 50 creators, rank by `engagementRate` and `fans`, and shortlist who actually moves an audience.
- 📊 **Social-media managers and agencies** - track a brand account and its competitors daily with `monitorMode`; every new video lands in a Google Sheet with its first-day plays.
- 🔎 **Trend and hashtag research** - read `#cooking` or `#fyp` each morning, keep posts with `leastDiggs: 10000`, and see which sounds (`musicMeta.musicName`) and formats are rising.
- 🛍️ **Brands and e-commerce** - read the hashtag of your product or brand, filter paid partnerships out with `excludeAds`, and read what creators say about it in `transcript`.
- 🤖 **AI and research teams** - feed `text`, `transcript` and `hashtags` to an LLM for sentiment or topic analysis; `compact` keeps a thousand posts inside a context window.
- 📈 **Content strategists** - compare `postType` video vs photo, duration vs `engagementRate`, posting cadence from `createTimeISO`, week over week on a schedule.

### How much does it cost to scrape TikTok?

TikTok Scraper is pay-per-event (the Pricing tab always shows the live rates):

| Event | Price | When it is charged |
|---|---:|---|
| `feed-scraped` | **$0.005 per profile, hashtag or search query** | Once per target per run, when TikTok serves its feed (opening it in a browser session). Never for video URLs |
| `post-scraped` | **$0.00028 per post** ($0.28 per 1,000) | Each post written to the dataset after your filters |
| `transcript` | **$0.001 per transcript** ($1.00 per 1,000) | Optional add-on; only posts that receive a transcript |

There is no start fee. Once TikTok serves a feed, its fee applies even if your filters remove every post or, in monitor mode, nothing is new: opening and checking the feed is the service.

What one profile or hashtag costs:

| Posts | Feed fee | Posts | Total | With a transcript on every post |
|---:|---:|---:|---:|---:|
| 10 | $0.005 | $0.0028 | $0.0078 | $0.0178 |
| 100 | $0.005 | $0.028 | $0.033 | $0.133 |
| 1,000 | $0.005 | $0.28 | $0.285 | $1.285 |

Worked examples:

- **1 profile × 30 posts** = $0.005 + 30 × $0.00028 = $0.005 + $0.0084 = **$0.0134**
- **1 profile × 30 posts with transcripts** (about 7 in 10 videos have a caption file, so about 21 transcripts) = $0.0134 + 21 × $0.001 = **$0.0344**
- **20 video URLs** = 20 × $0.00028 = **$0.0056** (no feed fee)
- **Daily monitor of 10 creators with 2 new posts each** = 10 × $0.005 + 20 × $0.00028 = $0.05 + $0.0056 = **$0.0556**; a day with nothing new costs **$0.05**

There is nothing else to pay: Apify platform usage (compute, residential proxy) is included in these prices. Measured on the platform on 2026-10-07 (default 2 GB of memory): a 25-post profile run took 23 seconds end to end, and 125 posts across two profiles, two hashtags and a search query took 35 seconds; a profile page delivers about 35 posts and a hashtag page about 30.

### Integrations, API, scheduling & MCP

- **Schedules:** run TikTok Scraper hourly, daily or weekly from the **Schedules** tab; combine with `monitorMode` to get only new posts, and with `oldestPostDate: "2"` to re-read yesterday's and today's posts with fresh counts.
- **Webhooks:** fire a URL when a run finishes - push rows to your CRM, Slack or a sheet.
- **No-code:** Make, Zapier, n8n, Google Sheets, Airtable, Slack via [Apify integrations](https://docs.apify.com/integrations).
- **API:** call it from Node.js or Python with `apify-client` - code on the [API tab](https://apify.com/topapi/tiktok-scraper/api/python) and the [Apify API reference](https://docs.apify.com/api/v2).
- **MCP / AI agents:** connect Claude, Cursor or any MCP client through the [MCP tab](https://apify.com/topapi/tiktok-scraper/api/mcp) and ask for TikTok videos in plain language; switch on `compact` to keep the answer small.

### More TopApi scrapers

<table>
<tr>
<td>⭐ <a href="https://apify.com/topapi/google-maps-reviews-scraper">Google Maps Reviews Scraper</a> - every review of a place, newest first, with owner replies and exact dates</td>
<td>🎵 <a href="https://apify.com/topapi/tiktok-scraper">TikTok Scraper</a> - this actor: posts by profile, hashtag, search or URL</td>
<td>🧭 <a href="https://apify.com/topapi">All TopApi social-media and lead-gen actors</a> - Instagram, YouTube Shorts, Facebook and X scrapers are next on this account</td>
</tr>
</table>

### Limits & empty runs

- **Keyword search is a login feature on TikTok's web app.** To the signed-out sessions this actor uses, the search page shows "Log in to search for popular content" and never loads results (measured on every platform session on 2026-10-03). The actor never logs in, so a search query is served as the **public hashtag feed for the same words** (`cooking recipes` -> `#cookingrecipes`), every row carries `searchQuery` and `searchHashtag`, and the status message says how many queries were served that way. A query with no hashtag equivalent delivers nothing.
- **Feeds are read in a real browser session.** The run opens TikTok's web app once, then requests each feed page from TikTok the way the app does, through Apify datacenter proxies (residential when TikTok refuses those). If TikTok still serves no feed, that target is read from TikTok's own page in the browser, through fresh residential sessions (up to three per target), and otherwise reported as "got no data from TikTok".
- **Posts per feed page:** TikTok serves about 35 posts per profile page and about 30 per hashtag page; a profile with 1,500 videos is about 45 pages. `resultsPerPage` and `oldestPostDate` are the cost controls.
- **Cut-down hashtag feeds:** TikTok serves some visitors a short hashtag feed with no further pages. Measured on 2026-10-07: `#fitness` answered 10-11 posts to 6 of 9 fresh sessions (and 30 per page, 100+ in all, to the others); `#fyp` and `#foryou` answered 1-5 posts every time. A hashtag that comes back short is read once more on a fresh session; what TikTok serves then is what the run delivers.
- **Speed:** the first feed page arrives about 5-20 seconds after the run starts (browser start and TikTok's web app booting, once per run); each further page takes 1-3 seconds. A target that needs the fallback takes from 30 seconds to two minutes more.
- **Sorted profile feeds:** `popular` follows TikTok's Popular order and `oldest` starts at the account's first video. If a profile has to be read from TikTok's own page and that page serves no sorted feed, the run reads it latest-first and logs it.
- **Reposts:** only profiles that show a Reposts tab; a profile without one returns no rows for `profileSection: "reposts"`.
- **Empty dataset:** means no matches after your filters, a private, removed or non-existent target, or TikTok served no data to the session (the status message names which). A feed TikTok did serve still pays its feed fee.
- **Not available:** comment text and follower lists (separate products), email or phone of the author (TikTok publishes none), view history over time (each run is a snapshot). Media URLs expire after a few hours; re-run the video URL to refresh them.

### FAQ

#### Can TikTok Scraper give me the transcript of a TikTok video?

Yes, with `includeTranscript: true`: it fetches TikTok's own caption file (the creator's captions or TikTok's automatic speech recognition) and delivers the plain text in `transcript`, with the language and source, on the same row as the post's stats. Videos without a caption file return `null`.

#### How many TikTok posts can TikTok Scraper collect in one run?

Everything TikTok serves: `resultsPerPage: 0` walks a profile to its oldest video (a 1,500-video account is about 45 feed pages, roughly a minute). Hashtag feeds (and search queries, served as hashtag feeds) are TikTok's ranking and go as deep as TikTok pages them; on tests `#cooking` kept serving 28-30 new posts per page, while some hashtags are cut short for some visitors (see Limits).

#### Can I run TikTok Scraper on a schedule to get new TikTok videos automatically?

Yes. Save your input as a task, open **Schedules**, pick the cadence, and switch on `monitorMode`. Each run delivers only posts not delivered before and stops at the last run's newest post on profile feeds, so a daily check of a big account costs one page. A run that finds nothing new delivers nothing and bills only the $0.005 feed fee per profile, hashtag or query checked.

#### Can I integrate TikTok Scraper with other apps?

Yes - Make, Zapier, n8n, Google Sheets, Slack and more via [Apify integrations](https://docs.apify.com/integrations), or use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger an action when a run finishes.

#### Can I use TikTok Scraper with the Apify API?

Yes. The API lets you start runs, fetch datasets and manage schedules. Use `apify-client` for [Node.js](https://apify.com/topapi/tiktok-scraper/api/javascript) or [Python](https://apify.com/topapi/tiktok-scraper/api/python); the API tab has ready-to-paste code.

#### Can I use TikTok Scraper through an MCP server?

Yes. Open the [MCP tab](https://apify.com/topapi/tiktok-scraper/api/mcp), connect your MCP client (Claude Desktop, Cursor, LibreChat...), and ask for TikTok videos of a creator or hashtag in plain language. Set `compact: true` so a hundred posts fit the model's context.

#### Do I need a TikTok account, cookies or an API key?

No. TikTok Scraper reads only what TikTok shows a signed-out visitor; you pass names, hashtags, keywords or URLs and nothing else. That is also why keyword search is served as a hashtag feed: TikTok's search results page asks visitors to log in, and this actor never does.

#### Why did my run return no TikTok videos?

In order of frequency on test runs: (1) the target is private, removed or misspelled - the status message says "not found" or "private"; (2) your filters removed everything - the run summary lists how many posts were read and why they were dropped; (3) `monitorMode` found nothing new since the last run; (4) a search query had no hashtag equivalent (TikTok login-walls keyword search, so queries are served as hashtag feeds); (5) TikTok served no feed data to the run's sessions, the browser fallback included - retry in a few minutes or use `postURLs` for posts you already know. In (2) and (3) TikTok did serve the feed, so its feed fee applies.

#### Does TikTok Scraper download the video files?

It delivers the direct media URLs (`videoMeta.downloadAddr`, `mediaUrls`) and the cover images; the files themselves are not stored. The URLs expire after a few hours, so download them right after the run or re-run the video URL.

#### How is TikTok Scraper different from other TikTok scrapers?

It puts the transcript text on the same row as the post, from TikTok's own caption files, and delivers the same post fields as the lane's leading TikTok Scraper plus `engagementRate`, content labels, AI-generated flags, tagged places and attached links; it filters by date, likes, ads, pinned posts, type and keyword, and ships monitor mode for scheduled runs. On the 32-post test run every row carried all six engagement counts and the author's stats.

#### Is it legal to scrape TikTok data?

TikTok Scraper extracts only publicly available TikTok posts; it does not log in or collect private data. Results may still contain personal data (creator names, captions), which is regulated by laws such as GDPR. Make sure you have a legitimate purpose before you use it.

#### Your feedback

We keep improving TikTok Scraper. Found a bug or missing a field? Open an issue on the [Issues tab](https://apify.com/topapi/tiktok-scraper/issues/open) - we answer within two working days.

# Actor input Schema

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

TikTok usernames or profile URLs whose videos you want, e.g. "tiktok", "@zachking", "https://www.tiktok.com/@khaby.lame". Newest videos first, 24-30 per feed page.

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

Hashtags or tag URLs, e.g. "cooking", "#fyp", "https://www.tiktok.com/tag/dance". Returns the videos TikTok shows on the hashtag page, 28-30 per page.

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

Keywords to search videos for, e.g. "cooking recipes", "ai tools 2026", or a search URL. TikTok shows keyword search results only after login ("Log in to search for popular content", measured 2026-10-03), so each query is served as the public hashtag feed for the same words (#cookingrecipes); every row carries searchQuery and searchHashtag and the run summary says so.

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

Direct video or photo-post URLs, short links or bare ids, e.g. "https://www.tiktok.com/@zachking/video/7095025543627705643", "https://vm.tiktok.com/ZMabc123/", "7095025543627705643". One row per URL, no browser needed; this mode works from every IP class tested.

## `profileSection` (type: `string`):

Which tab of the profile to read. Reposts returns other creators' videos that this profile reposted; the row's authorMeta is the original creator.

## `profileSorting` (type: `string`):

Latest walks the profile newest-first so the date window and monitor mode can stop early. Popular and Oldest use TikTok's own sort controls; when TikTok serves no sorted feed to a signed-out session (it happens), the run falls back to latest-first and says so in the log. Hashtag and search feeds are always TikTok's ranking.

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

Absolute date (2026-09-01, 2026-09-01T12:00:00Z), relative to now (7 days, 3 weeks, 2 months, 1 year) or a day count (1 = today's posts, 2 = yesterday and today). Leave empty for no lower bound.

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

Absolute date or relative (e.g. 30 days). Combine with the field above for a window such as oldestPostDate "2026-01-01" + newestPostDate "2026-06-30".

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

Keep only posts with at least this many likes (diggCount), e.g. 10000 to keep hits only. 0 = no minimum.

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

Skip the posts a creator pinned to the top of the profile (usually old). They are reported in the run summary.

## `excludeAds` (type: `boolean`):

Skip posts TikTok marks as ads (isAd) or as paid partnership / branded content (isSponsored). On a 210-post test sample 15% of posts from brand accounts carried one of the two flags.

## `postType` (type: `string`):

Photo posts (slideshows) come back with isSlideshow true and their image links in slideshowImageLinks; videoMeta.duration is 0 for them.

## `keywordFilter` (type: `string`):

Keep only posts whose caption, hashtags, on-screen text stickers or author name contain this word or phrase, case-insensitive, e.g. "giveaway" or "recipe, meal prep" (comma = any of them).

## `includeTranscript` (type: `boolean`):

Adds the spoken text of the video as plain text (transcript, transcriptLanguage, transcriptSource) from TikTok's own caption files - the creator's captions or TikTok's automatic speech recognition, no AI cost. On a 210-post test sample 72% of videos had a caption file. Charged as the transcript event only for posts that receive one.

## `monitorMode` (type: `boolean`):

Remembers, per profile / hashtag / query, which posts were already delivered (in the named key-value store below) and returns only new ones. On a profile read latest-first the run stops at the last run's newest post, so a daily check of a 2,000-video account costs one page. A target checked with nothing new delivers nothing and is billed only its feed fee (feed-scraped), the check itself.

## `monitorStoreName` (type: `string`):

Name of the key-value store that keeps the per-target memory for monitor mode. Give each separate feed (a client, a Slack channel) its own name so they do not hide posts from each other. Letters, digits and hyphens.

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

Cap per target after filters (your main cost control; you pay per delivered post plus one feed fee per profile, hashtag or search). 0 = everything TikTok serves (a profile with 1,500 videos takes about 60 feed pages). TikTok serves 24-30 posts per profile or hashtag page and 12 per search page.

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

Hard cap for the whole run across all targets. 0 = no total cap (each target is still capped above).

## `compact` (type: `boolean`):

Core fields only (id, text, createTimeISO, webVideoUrl, author, authorFans, plays, likes, comments, shares, saves, engagementRate, duration, hashtags, transcript if requested): about a tenth of the bytes, sized for AI agents and MCP clients.

## `debugScreenshots` (type: `boolean`):

When a profile, hashtag or search page serves no posts, save a screenshot of what the browser saw to the run's key-value store (NOFEED-<kind>-<n>). Useful when you report an empty run to us.

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

Residential proxies are required for profile, hashtag and search feeds: TikTok answers datacenter IPs with empty feed pages (measured). Video URLs and subtitle files are fetched through datacenter proxies automatically because TikTok serves those to any IP. Pick a proxy country to see a market's feed.

## Actor input object example

```json
{
  "profiles": [],
  "hashtags": [],
  "searchQueries": [],
  "postURLs": [
    "https://www.tiktok.com/@zachking/video/7095025543627705643",
    "https://www.tiktok.com/@guinnessworldrecords/video/7172183875538488582"
  ],
  "profileSection": "videos",
  "profileSorting": "latest",
  "leastDiggs": 0,
  "excludePinnedPosts": false,
  "excludeAds": false,
  "postType": "all",
  "keywordFilter": "",
  "includeTranscript": false,
  "monitorMode": false,
  "monitorStoreName": "tiktok-posts-monitor",
  "resultsPerPage": 10,
  "maxItems": 0,
  "compact": false,
  "debugScreenshots": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `posts` (type: `string`):

The dataset of TikTok posts (one item per video or photo post).

## `summary` (type: `string`):

Per-target counts (read, filtered, already delivered, delivered), sessions used and bytes transferred.

# 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 = {
    "postURLs": [
        "https://www.tiktok.com/@zachking/video/7095025543627705643",
        "https://www.tiktok.com/@guinnessworldrecords/video/7172183875538488582"
    ],
    "profileSorting": "latest",
    "resultsPerPage": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("topapi/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 = {
    "postURLs": [
        "https://www.tiktok.com/@zachking/video/7095025543627705643",
        "https://www.tiktok.com/@guinnessworldrecords/video/7172183875538488582",
    ],
    "profileSorting": "latest",
    "resultsPerPage": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("topapi/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 '{
  "postURLs": [
    "https://www.tiktok.com/@zachking/video/7095025543627705643",
    "https://www.tiktok.com/@guinnessworldrecords/video/7172183875538488582"
  ],
  "profileSorting": "latest",
  "resultsPerPage": 10
}' |
apify call topapi/tiktok-scraper --silent --output-dataset

```

## MCP server setup

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