# TikTok Scraper: Videos, Profiles, Hashtags, Search (`deepmine/tiktok-scraper`) Actor

TikTok scraper for every input in one run: paste video, profile, hashtag or search links, or type hashtags, profiles and keywords. One row per video with caption, creator, followers, plays, likes, comments, shares, saves, music, hashtags, post date and a video file link. No login.

- **URL**: https://apify.com/deepmine/tiktok-scraper.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Social media, Videos, Marketing
- **Features:** Limited permissions
- **Stats:** 17 total users, 12 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.19 / 1,000 videos

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 Scraper: Videos, Profiles, Hashtags, Search

TikTok scraper for every kind of input in one run: paste any TikTok link, or type hashtags, profiles and search keywords, and get one row per video with caption, creator, followers, plays, likes, comments, shares, saves, music, hashtags, post date and a video file link.

| Creator | Caption | Plays | Likes | Comments | Saves | Followers | Music | Source |
|---|---|---|---|---|---|---|---|---|
| [@jenna_bushhager](https://www.tiktok.com/@jenna_bushhager/video/7223827494913215786) | #WorldBookDay is 4/23, and I've joined the #BookTo… | 39,200 | 998 | 34 | 134 | 224,000 | original sound | #booktok |
| [@zachking](https://www.tiktok.com/@zachking/video/7702834585830231310) | Can I do extreme yoga? 🧘 | 1,700,000 | 177,400 | 1,826 | 6,829 | 86,760,607 | original sound | @zachking |
| [@biteswithlily](https://www.tiktok.com/@biteswithlily/video/7598108209903127829) | Everything I ate at the Train Night Market in Bang… | 11,600,000 | 1,200,000 | 1,526 | 68,411 | 3,400,000 | Mario like action game 2 | street food |

<sub>Collected 2026-11-02 by the prefilled run. Numbers are as TikTok showed them to a logged-out visitor.</sub>

**$0.29 per 1,000 videos on the Starter plan ($0.35 Free, $0.25 Scale, $0.19 Business).** The prefilled run (75 videos) costs about $0.02.

### What you can enter

Mix these in one run. Every input gets up to 💯 Videos per input, and a video that two inputs find is delivered and charged once.

| Field | What it takes | Example |
|---|---|---|
| 🔗 TikTok links | Any TikTok link: each is read for what it is | `tiktok.com/@zachking/video/...`, `vm.tiktok.com/...`, `tiktok.com/t/...`, `tiktok.com/@zachking`, `tiktok.com/tag/booktok`, `tiktok.com/search?q=street%20food`, `tiktok.com/music/...` |
| #️⃣ Hashtags | With or without # | `booktok` |
| 👤 Profiles | With or without @ | `zachking` |
| 🔍 Search keywords | One search per line | `street food` |

The links field alone can hold a whole mixed list, so a spreadsheet of URLs works as it is. A link to one video gives that one video.

### Filters

All filters are free: a video they leave out isn't charged.

| Filter | Works on |
|---|---|
| 📅 Only videos posted after | Profiles and searches. Hashtag feeds aren't ordered by date, so they aren't filtered. |
| 📅 Only videos posted before | Profiles |
| 🔍 Search order: relevance, newest, most views, most likes | Searches |
| 🔍 Search posted within: 24 hours to 6 months | Searches |
| 👤 Profile video order: latest, popular, oldest | Profiles |
| 👤 Profile sections: own videos, reposts, stories | Profiles |
| 👤 Skip pinned videos | Profiles |
| ❤️ Min and max likes | Profiles |

TikTok refuses Popular and Oldest on many datacenter IPs: if a profile fails with them, use a residential proxy.

Calls written for `clockworks/tiktok-scraper` work too. `postURLs`, `resultsPerPage`, `profileScrapeSections`, `profileSorting`, `excludePinnedPosts`, `oldestPostDateUnified`, `newestPostDate`, `leastDiggs`, `mostDiggs`, `videoSearchSorting` and `videoSearchDateFilter` are read as the fields above.

### What you get

One row per video, in the order of your inputs. `sourceInput` says what found each video, so you can filter one export by input.

- **📊 Overview:** cover, creator, caption, link, plays, likes, comments, shares, saves, followers, music, post date, source.
- **📈 Stats:** every count side by side, ready to sort.
- **🔎 Details:** the video file, TikTok's AI label, captions, quality, file size and the creator's totals.

Video file links and picture links are signed by TikTok and stop working about 2 days after the run, so download them the same day. Filters and repeats aren't charged. Inputs that fail are named in the status message and the run summary; their rows are never charged, and the other inputs' rows are kept.

### Speed

Measured on 6 Apify runs at the default 256 MB, 2026-11-02: first row 2.2-6.6 s after the run starts, and 700 videos in 48 s. The run lasts as long as your inputs do, and rows reach the dataset in batches as they are read.

### Output fields

- `cover`: The video's cover image. Signed by TikTok: the link stops working about 2 days after the run.
- `creatorName`: The creator's display name.
- `caption`: The full caption, hashtags included.
- `captionSnippet`: The caption's first 50 characters on one line, for tables.
- `creator`: The creator's TikTok username, without @.
- `url`: The video's page on TikTok.
- `creatorVerified`: The creator has TikTok's verified badge.
- `isPinned`: Pinned to the top of the profile. Null for videos not found on a profile: only a profile's feed says.
- `isAd`: TikTok labels the post as an ad or a paid partnership.
- `plays`: Views. TikTok rounds large counts on its web pages (411.7K is 411700). Null when TikTok hides the counter.
- `likes`: Likes. Null when TikTok hides the counter.
- `comments`: Comments.
- `shares`: Shares. Null when TikTok hides the counter.
- `saves`: Saves (TikTok's Favorites). Null when TikTok hides the counter.
- `reposts`: Reposts (TikTok's Repost button). Null when TikTok hides the counter.
- `followers`: The creator's followers when the video was collected.
- `durationSeconds`: Length in seconds. Null for photo posts.
- `postedAt`: When it was posted (UTC, ISO 8601).
- `rank`: Position in the feed or search as collected, 1 = first. Null for a video you entered.
- `hashtags`: Hashtags in the caption, without #.
- `mentions`: Usernames mentioned in the caption.
- `mentionedUsers`: Each person mentioned in the caption: the name as written (TikTok writes a mention as the person's display name), their username, user id, secUid and profile link.
- `music`: The sound's title ("original sound" is the creator's own audio).
- `soundUrl`: The sound's page on TikTok, with every video that uses it.
- `videoUrl`: The video file (MP4) in the best quality TikTok serves, a direct link anyone can open or download (no login, no cookies). Often H.265 (HEVC), which some browsers don't play; download it to watch. Download it before videoExpiresAt. Null for photo posts.
- `videoExpiresAt`: When TikTok's links to the video file expire (UTC), about 2 days after the run.
- `isPhotoPost`: A photo post (slideshow): its pictures are in photos.
- `isAiGenerated`: TikTok labels the post as AI-generated.
- `hasCaptions`: TikTok has captions (subtitles) for the video. The caption text itself is what TikTok Transcripts delivers.
- `captionLanguages`: The languages TikTok has captions in for the video (eng-US, ...).
- `captionLanguage`: The language of the caption text as TikTok detects it (en, es, ...).
- `onScreenText`: Text the creator put on the video with TikTok's text stickers; several are joined with ' | '.
- `relatedSearches`: Searches TikTok suggests next to the video ("Others searched for").
- `topics`: TikTok's own topic labels for the video.
- `country`: Where TikTok says the video was posted from (country code).
- `placeName`: The place the post is tagged with, when it has one.
- `placeAddress`: The tagged place's address.
- `placeCity`: The tagged place's city, when TikTok gives one.
- `width`: Video width in pixels. Null for photo posts.
- `height`: Video height in pixels. Null for photo posts.
- `definition`: TikTok's quality label for the video (540p, 720p, 1080p).
- `format`: The video file format (mp4).
- `fileSizeBytes`: Size of TikTok's standard video file in bytes.
- `creatorAvatar`: The creator's profile picture. Signed by TikTok: the link stops working about 2 days after the run.
- `creatorBio`: The creator's bio.
- `creatorFollowing`: Accounts the creator follows.
- `creatorLikes`: Total likes on all the creator's videos.
- `creatorVideos`: The creator's public videos.
- `creatorPrivate`: The creator's account is private. Null when TikTok doesn't say.
- `soundAuthor`: The sound's artist or creator name.
- `soundAlbum`: The album of a released track, when TikTok names it.
- `soundIsOriginal`: The sound is the creator's own audio, not a released track. Null without a sound.
- `soundCover`: The sound's cover art. Signed by TikTok: the link stops working about 2 days after the run.
- `creatorSizeTier`: The creator's size by followers: nano (under 10K), micro (10K-100K), mid (100K-500K), macro (500K-1M) or mega (1M and more).
- `creatorEmail`: The first email address written in the creator's bio, when there is one.
- `soundDurationSeconds`: The sound's length in seconds.
- `soundAudioUrl`: The sound's audio file. Signed by TikTok; it can expire.
- `soundIsCopyrighted`: TikTok marks the sound as a copyrighted track.
- `soundIsCommercial`: The sound is in TikTok's commercial music library (cleared for business use).
- `commentsAllowed`: Anyone may comment on the video. False when the creator turned comments off or limited them to friends.
- `duetAllowed`: Others may Duet the video. Null when TikTok doesn't say (photo posts).
- `stitchAllowed`: Others may Stitch the video. Null when TikTok doesn't say (photo posts).
- `videoCodec`: The video's codec (h264, h265). Null for photo posts.
- `videoBitrate`: The standard video file's bitrate in bits per second. Null for photo posts.
- `dynamicCover`: The video's animated cover image. Signed by TikTok: the link stops working about 2 days after the run.
- `embedUrl`: TikTok's embed player page for the video: opens with no login or cookies, and the link isn't signed, so it doesn't expire.
- `photos`: The images of a photo post (slideshow); null for videos. Signed by TikTok: the link stops working about 2 days after the run.
- `videoId`: TikTok's video id.
- `creatorId`: TikTok's user id of the creator.
- `creatorSecUid`: The creator's secUid, the id TikTok's own web API uses.
- `soundId`: TikTok's sound (music) id.
- `poiId`: TikTok's id of the tagged place.
- `playlistId`: TikTok's id of the creator's playlist the video is in, when it is in one.
- `sourceType`: Which kind of input found it: video, profile, hashtag, search or sound.
- `sourceInput`: What found the video: the @profile, #hashtag, search keyword or URL you entered.
- `scrapedAt`: When it was collected (UTC).

The run summary (🧾 Run summary) lists each input's status, rows and stop reason.

### Pricing

Pay per video in your dataset, no start fee. Plan prices per 1,000 videos:

| Plan | Price |
|---|---|
| Free | $0.35 |
| Starter | $0.29 |
| Scale | $0.25 |
| Business | $0.19 |

### Questions

**Do I need a TikTok account?** No. Everything comes from what TikTok shows logged-out visitors.

**How many videos can I get?** Profiles and hashtags go deep; TikTok ends a search after about 200 videos.

**Can I get comments, transcripts or followers?** Those have their own Actors below.

### Related Actors

- [TikTok Video Search](https://apify.com/deepmine/tiktok-video-search): keyword search with sort orders and date windows.
- [TikTok Hashtag Videos](https://apify.com/deepmine/tiktok-hashtag-videos): one hashtag in depth, with its totals.
- [TikTok Profile & Videos](https://apify.com/deepmine/tiktok-profile-videos): profile rows, tabs, likes filters.
- [TikTok Video Details](https://apify.com/deepmine/tiktok-video-details): video URLs in, full details out.
- [TikTok Comments Scraper](https://apify.com/deepmine/tiktok-comments-scraper): comments and replies.
- [TikTok Transcripts](https://apify.com/deepmine/tiktok-transcripts): the spoken text of videos.

### Feedback

Tell us what's missing on the Issues tab. If the data helps you, a short review on the Store page helps others find it.

# Actor input Schema

## `startUrls` (type: `array`):

Any TikTok link, one per line: a video, a short vm.tiktok.com or tiktok.com/t/ share link, a profile, a /tag/ hashtag page, a /search page or a /music/ sound. Each is read for what it is.

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

Hashtags, one per line, with or without #, e.g. booktok. Each gets up to the videos per input.

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

TikTok usernames, with or without @, e.g. zachking. Each gives its newest videos, up to the videos per input.

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

Words to search TikTok videos for, one search per line, e.g. street food. TikTok ends a search after about 200 videos.

## `resultsPerInput` (type: `integer`):

The most videos from each profile, hashtag, search or link. You pay per video. A link to one video always gives that one video.

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

Skip older videos from profiles and searches: a date (YYYY-MM-DD) or a period such as 7 days. Hashtag feeds aren't ordered by date, so they aren't filtered. Empty = all.

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

Skip profile videos posted after this date (YYYY-MM-DD; the whole day counts) or a period such as 30 days ago. Empty = all.

## `sortOrder` (type: `string`):

Relevance keeps TikTok's order. The others sort everything TikTok's search shows for a keyword (roughly 150-250 videos), then keep your videos per input: the run reads the whole search, but you pay only for the videos you get.

## `datePosted` (type: `string`):

Keep only search results posted in this window (a month is 30 days). TikTok's results aren't sorted by date, so a short window can give fewer videos than you asked for.

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

As the profile's tabs on TikTok. Popular is TikTok's own ranking: pinned videos, then mostly the most played. TikTok refuses Popular and Oldest on many datacenter IPs: if a profile fails with them, use a residential proxy.

## `profileSections` (type: `array`):

Reposts are other creators' videos the profile reposted (their rows name their own creator). Stories are the ones up right now. Videos per input counts all of them together.

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

Leave out the videos a creator pinned to the top of the profile.

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

Keep only profile videos with at least this many likes. Others are free and don't count toward Videos per input. To find them the run reads up to 1,000 videos per profile (or 10 per video you ask for, if more). Empty = no minimum.

## `maxLikes` (type: `integer`):

Keep only profile videos with at most this many likes. Empty = no maximum.

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

Leave as is: Apify's datacenter proxy works for every input. Only Popular or Oldest profile order can need a residential proxy.

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

The same as startUrls (postURLs).

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

The same as resultsPerInput (resultsPerPage).

## `profileScrapeSections` (type: `array`):

The same as profileSections (profileScrapeSections).

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

The same as postedAfter, or a number of days: 1 is today, 2 yesterday and today (oldestPostDateUnified).

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

The same as postedBefore (newestPostDate).

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

The same as minLikes (leastDiggs).

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

Keep videos with fewer likes than this (mostDiggs).

## `videoSearchSorting` (type: `string`):

MOST_RELEVANT, MOST_LIKED or LATEST: the same as sortOrder (videoSearchSorting).

## `videoSearchDateFilter` (type: `string`):

ALL_TIME, PAST_24_HOURS, PAST_WEEK, PAST_MONTH, LAST_3_MONTHS or LAST_6_MONTHS: the same as datePosted (videoSearchDateFilter).

## Actor input object example

```json
{
  "startUrls": [
    "https://www.tiktok.com/tag/booktok",
    "https://www.tiktok.com/@zachking",
    "https://www.tiktok.com/search?q=street%20food"
  ],
  "resultsPerInput": 25,
  "sortOrder": "relevance",
  "datePosted": "allTime",
  "profileSorting": "latest",
  "profileSections": [
    "videos"
  ],
  "excludePinnedPosts": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        "https://www.tiktok.com/tag/booktok",
        "https://www.tiktok.com/@zachking",
        "https://www.tiktok.com/search?q=street%20food"
    ],
    "resultsPerInput": 25,
    "sortOrder": "relevance",
    "datePosted": "allTime",
    "profileSections": [
        "videos"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/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 = {
    "startUrls": [
        "https://www.tiktok.com/tag/booktok",
        "https://www.tiktok.com/@zachking",
        "https://www.tiktok.com/search?q=street%20food",
    ],
    "resultsPerInput": 25,
    "sortOrder": "relevance",
    "datePosted": "allTime",
    "profileSections": ["videos"],
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/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 '{
  "startUrls": [
    "https://www.tiktok.com/tag/booktok",
    "https://www.tiktok.com/@zachking",
    "https://www.tiktok.com/search?q=street%20food"
  ],
  "resultsPerInput": 25,
  "sortOrder": "relevance",
  "datePosted": "allTime",
  "profileSections": [
    "videos"
  ]
}' |
apify call deepmine/tiktok-scraper --silent --output-dataset

```

## MCP server setup

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