# TikTok Scraper (`donjuan_mime/tiktok-parser`) Actor

Scrape TikTok videos by hashtag or profile: captions, views, likes, comments, shares, music, and author stats. No login needed. Export to JSON, CSV, or Excel.

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

## Pricing

from $1.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/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, stats, authors, and music from hashtags and profiles

TikTok Scraper collects public TikTok posts for any hashtag or profile you give it. For every post you get the caption, publish date, view, like, comment, share, save, and repost counts, the author's profile and follower stats, the sound used, video details, subtitles, location tags, mentions, and hashtags. For hashtags you also get the total view count of the hashtag itself.

You don't need a TikTok account, an API key, or any code. Type in hashtags, profiles, or both, press **Start**, and download the results as JSON, CSV, Excel, XML, or HTML. Or pull them straight into your app through the Apify API.

### What can you do with TikTok data?

- **Track trends.** See which videos lead a hashtag right now, how many views they have, and which sounds and effects they use.
- **Monitor creators and brands.** Pull the latest, most viewed, or oldest videos of any public profile, plus the posts it reposted, and track how each one performs.
- **Find creators and influencers.** Every post comes with the author's follower count, total likes, video count, bio, and verified badge, so you can shortlist creators for a campaign without opening hundreds of profiles.
- **Measure a campaign.** Run your branded hashtag on a schedule and watch views, likes, and shares grow over time. The hashtag's total view count comes with every result.
- **Research competitors.** See who posts under your competitors' hashtags, what they say, and how their audience reacts.
- **Study content and language.** Captions, detected caption language, subtitles, and hashtags give you clean text for topic analysis, sentiment analysis, or training data.
- **Pick music.** Each post names its sound, the artist, the album, and whether the sound is original, so you can spot tracks that are taking off.
- **Build datasets for research.** Export thousands of rows to a spreadsheet or a database for academic or market research.

### What data does TikTok Scraper extract?

| Group | Fields |
|---|---|
| Post | ID, URL, caption text, caption language, publish time (Unix and ISO 8601), ad flag, pinned flag, slideshow flag |
| Engagement | views, likes, comments, shares, saves (bookmarks), reposts |
| Author | user ID, username, display name, profile URL, avatar, bio, verified badge, private account flag, followers, following, friends, total likes received, likes given, number of videos |
| Music | sound name, artist, album, sound ID, original sound flag, audio URL, cover image |
| Video | width, height, duration, quality (for example 720p), format, cover image, video file URL |
| Subtitles | language, source (machine translation or speech recognition), version, link to the subtitle file |
| Location | place name, address, city, location ID, TikTok's city and country IDs (geotagged posts only) |
| Text entities | hashtags with their TikTok IDs, mentioned users with ID, username, profile URL, and secUid |
| Effects | effect and sticker names and IDs used in the video |
| Slideshows | links to every image in photo posts |
| Hashtag | the hashtag name and its total views across TikTok (hashtag inputs) |
| Profile section | whether a post is one of the profile's own videos or a repost (profile inputs) |

### How to scrape TikTok hashtags and profiles

1. Open the actor and go to the **Input** tab.
2. Add hashtags, profiles, or both. For a hashtag, write `cats`, `#cats`, or paste `https://www.tiktok.com/tag/cats`. For a profile, write `nasa`, `@nasa`, or paste `https://www.tiktok.com/@nasa`.
3. For profiles, pick the sections (videos, reposts, or both) and the video order.
4. Set **Posts per hashtag or profile** and turn on any downloads you want.
5. Press **Start**. When the run finishes, open the **Output** tab to preview the table, or press **Export** to download the data.

### Input

| Field | Type | Description |
|---|---|---|
| `hashtags` | array of strings | Hashtags to scrape. Accepts `cats`, `#cats`, or a full `https://www.tiktok.com/tag/cats` URL. |
| `profiles` | array of strings | Profiles to scrape. Accepts `nasa`, `@nasa`, or a full `https://www.tiktok.com/@nasa` URL. Add hashtags, profiles, or both. |
| `profileScrapeSections` | array of strings | `videos`, `reposts`, or both. Defaults to `["videos"]`. |
| `profileSorting` | string | `latest`, `popular`, or `oldest`: the order of a profile's videos. Defaults to `latest`. Reposts always come newest first. |
| `resultsPerPage` | integer | The maximum number of posts per hashtag and per profile. A profile's sections share the limit: videos first, then reposts. |
| `excludePinnedPosts` | boolean | Skip posts the author pinned. Skipped posts don't count toward the limit. |
| `shouldDownloadCovers` | boolean | Save video cover images to the run's key-value store. |
| `shouldDownloadSlideshowImages` | boolean | Save every image of photo (slideshow) posts. |
| `shouldDownloadAvatars` | boolean | Save author profile pictures. |
| `shouldDownloadMusicCovers` | boolean | Save the cover images of sounds. |
| `downloadSubtitlesOptions` | string | `NEVER_DOWNLOAD_SUBTITLES` or `DOWNLOAD_SUBTITLES`. |
| `proxyCountryCode` | string | A two-letter country code such as `US` or `DE` to browse TikTok through Apify residential proxy in that country. `None` uses Apify datacenter proxy. |

#### Input example

```json
{
  "hashtags": ["cats", "#dogsoftiktok", "https://www.tiktok.com/tag/petsoftiktok"],
  "profiles": ["nasa", "https://www.tiktok.com/@natgeo"],
  "profileScrapeSections": ["videos", "reposts"],
  "profileSorting": "popular",
  "resultsPerPage": 50,
  "excludePinnedPosts": true,
  "shouldDownloadCovers": true,
  "shouldDownloadSlideshowImages": false,
  "shouldDownloadAvatars": false,
  "shouldDownloadMusicCovers": false,
  "downloadSubtitlesOptions": "DOWNLOAD_SUBTITLES",
  "proxyCountryCode": "None"
}
```

### Output

Every post becomes one item in the dataset. The field layout matches the popular TikTok scrapers on Apify (`authorMeta`, `musicMeta`, `videoMeta`, and so on), so you can swap this actor into an existing pipeline without rewriting it.

#### Output example

Below is a real post from the `#cats` hashtag with cover, avatar, music cover, and subtitle downloads turned on. Long links are shortened.

```json
{
  "id": "7583279464440777998",
  "text": "#cutecat #funnyvideos #funny #cat #catsoftiktok ",
  "textLanguage": "un",
  "createTime": 1765619988,
  "createTimeISO": "2025-12-13T09:59:48.000Z",
  "webVideoUrl": "https://www.tiktok.com/@yycats8/video/7583279464440777998",
  "isAd": false,
  "authorMeta": {
    "id": "7496296259767665706",
    "name": "yycats8",
    "profileUrl": "https://www.tiktok.com/@yycats8",
    "nickName": "Didpet",
    "verified": false,
    "privateAccount": false,
    "signature": "🐱My name is Yuanyuan\nI love parkour and get jealous easily\nThank your follow❤️",
    "avatar": "https://api.apify.com/v2/key-value-stores/aBcD1234eFgH5678i/records/avatar-7496296259767665706",
    "originalAvatarUrl": "https://p16-common-sign.tiktokcdn-eu.com/tos-maliva-avt-0068/...",
    "following": 95,
    "fans": 297000,
    "video": 285,
    "heart": 14300000,
    "digg": 886,
    "friends": 0
  },
  "musicMeta": {
    "musicName": "The Winner Is... - DeVotchKa Version",
    "musicAuthor": "DeVotchKa",
    "musicOriginal": false,
    "musicAlbum": "The Winner Is... - DeVotchKa Version",
    "musicId": "7268735501090539521",
    "playUrl": "https://sf16-music.tiktokcdn-eu.com/obj/tos-alisg-ve-2774/...",
    "coverMediumUrl": "https://api.apify.com/v2/key-value-stores/aBcD1234eFgH5678i/records/music-cover-7268735501090539521",
    "originalCoverMediumUrl": "https://p77-sg.tiktokcdn.com/aweme/200x200/tos-alisg-v-2774/..."
  },
  "videoMeta": {
    "height": 1280,
    "width": 720,
    "duration": 13,
    "coverUrl": "https://api.apify.com/v2/key-value-stores/aBcD1234eFgH5678i/records/cover-7583279464440777998",
    "originalCoverUrl": "https://p19-common-sign.tiktokcdn-eu.com/tos-useast5-p-0068-...",
    "definition": "720p",
    "format": "mp4",
    "downloadAddr": "https://v16-webapp-prime.tiktok.com/video/tos/alisg/...",
    "subtitleLinks": [
      {
        "language": "eng-US",
        "tiktokLink": "https://v19-webapp.tiktokcdn-eu.com/d56585b611d7e7d78558ba76...",
        "downloadLink": "https://api.apify.com/v2/key-value-stores/aBcD1234eFgH5678i/records/subtitle-7583279464440777998-eng-US",
        "source": "MT",
        "version": "4"
      },
      {
        "language": "kor-KR",
        "tiktokLink": "https://v19-webapp.tiktokcdn-eu.com/c005fbda84cc7e85d6b3ed23...",
        "downloadLink": "https://api.apify.com/v2/key-value-stores/aBcD1234eFgH5678i/records/subtitle-7583279464440777998-kor-KR",
        "source": "ASR",
        "version": "1:whisper_lid"
      }
    ]
  },
  "diggCount": 105000,
  "shareCount": 35200,
  "playCount": 2000000,
  "commentCount": 1027,
  "collectCount": 6741,
  "repostCount": 0,
  "mentions": [],
  "detailedMentions": [],
  "hashtags": [
    { "id": "34199", "name": "cutecat" },
    { "id": "107738", "name": "funnyvideos" },
    { "id": "5424", "name": "funny" },
    { "id": "7551", "name": "cat" },
    { "id": "1601336200518658", "name": "catsoftiktok" }
  ],
  "isSlideshow": false,
  "isPinned": false,
  "input": "cats",
  "searchHashtag": {
    "name": "cats",
    "views": 439047125953
  }
}
```

#### Output fields

| Field | Description |
|---|---|
| `id` | TikTok post ID. |
| `text` | The caption, including hashtags and mentions. |
| `textLanguage` | The caption language TikTok detected, for example `en` or `uk`. `un` means TikTok couldn't tell. |
| `createTime`, `createTimeISO` | Publish time as a Unix timestamp and as an ISO 8601 string in UTC. |
| `webVideoUrl` | Link to the post. Videos use `/video/`, photo posts use `/photo/`. |
| `isAd` | `true` for paid ads. |
| `authorMeta` | The author's profile. `name` is the username (the part after `@`), `nickName` is the display name, `signature` is the bio, `fans` is followers, `heart` is total likes received, `digg` is likes given, `video` is the number of posts. |
| `musicMeta` | The sound: name, artist, album, ID, audio link, and whether the author recorded it (`musicOriginal`). |
| `videoMeta` | Size, length in seconds, quality, format, cover image, a link to the video file, and subtitles when TikTok has them. |
| `locationMeta` | The place a post is tagged with. Only geotagged posts have it. `cityCode` and `countryCode` are TikTok's own IDs, not ISO codes. |
| `slideshowImageLinks` | One entry per image in a photo post. |
| `playCount`, `diggCount`, `commentCount`, `shareCount`, `collectCount`, `repostCount` | Views, likes, comments, shares, saves, and reposts. |
| `hashtags` | Hashtags in the caption, with TikTok's hashtag ID when TikTok provides one. |
| `mentions`, `detailedMentions` | Users tagged in the caption. |
| `effectStickers` | Effects and stickers used in the video. |
| `isSlideshow` | `true` for photo posts. |
| `isPinned` | `true` if the author pinned the post. |
| `input` | The hashtag or profile username from your input that found this post. |
| `searchHashtag` | The hashtag's name and its total views on TikTok. Only posts found through a hashtag have it. |
| `fromProfileSection` | `videos` or `reposts`: the profile section the post came from. Only posts found through a profile have it. |

### Downloading covers, avatars, images, and subtitles

TikTok signs its media links, and they stop working after a few hours. If you plan to show the images in a report, a dashboard, or your app later, turn on the downloads you need. The actor then saves each file to the run's key-value store and puts a permanent link in the result:

- `videoMeta.coverUrl` points to the saved cover, and `videoMeta.originalCoverUrl` keeps TikTok's link.
- `authorMeta.avatar` points to the saved avatar, and `authorMeta.originalAvatarUrl` keeps TikTok's link.
- `musicMeta.coverMediumUrl` points to the saved sound cover, and `musicMeta.originalCoverMediumUrl` keeps TikTok's link.
- `slideshowImageLinks[].downloadLink` and `videoMeta.subtitleLinks[].downloadLink` point to the saved images and subtitle files.

With downloads off, both fields of each pair hold TikTok's link.

The actor saves each avatar and sound cover once, even when the same author or sound appears in many posts. When TikTok refuses to serve a file, the result keeps TikTok's link and the run carries on. Subtitles come in the format TikTok serves them, WebVTT or JSON.

Downloads make a run slower and use more storage, so turn on only what you need.

### Scraping profiles

Add usernames to `profiles` to collect a profile's posts. For each profile you choose:

- **Sections.** `videos` returns the profile's own posts. `reposts` returns the posts it reposted, so their `authorMeta` describes the original creators. Take one section or both.
- **Order.** `latest` lists videos newest first, `popular` most viewed first, and `oldest` oldest first, the same way TikTok's own Latest, Popular, and Oldest buttons do.

The actor skips profiles that don't exist and private profiles, since logged-out visitors can't see their posts, and says so in the log.

### Proxy

By default the actor browses TikTok through Apify datacenter proxy at no extra charge. When TikTok cuts a hashtag or profile short, the actor retries it from a new IP, up to 5 times.

Set `proxyCountryCode` to a country code such as `US`, `GB`, or `DE` to switch to Apify residential proxy in that country. Use it when you want posts as TikTok shows them to people in a given country, or when hashtags keep coming back short. Residential proxy needs an Apify plan that includes it.

### How many posts can I get?

Without a logged-in session, TikTok shows the first 2 or 3 pages of a hashtag, which is about 60 to 90 posts. After that, TikTok returns empty pages, and the actor moves on to the next hashtag. To collect more posts on a topic, add related hashtags. For example, use `cats`, `catsoftiktok`, `cutecat`, and `catlover` instead of `cats` alone.

Profiles give less: TikTok shows logged-out visitors about one page of each profile section, around 25 posts. Use `popular` or `oldest` to reach videos the latest page doesn't show.

Each hashtag and profile section runs in a fresh browser session. If TikTok blocks one, the others still run.

### How fast is it?

In our tests, two hashtags with 40 posts each and every download turned on finished in under a minute. Without downloads, one hashtag takes about 20 seconds. The actor doesn't load the videos while it scrolls, which keeps runs fast and saves proxy traffic.

### How much does it cost?

You pay only for what you get:

| What | Price |
|---|---|
| Post saved to the dataset | $1.00 per 1,000 posts |
| File saved with the download options (cover, avatar, music cover, slideshow image, or subtitle file) | $0.50 per 1,000 files |
| Post collected through residential proxy | $2.00 per 1,000 posts, on top of the post price |

With the default settings, 1,000 posts cost $1.00. The same 1,000 posts with covers downloaded cost $1.50. An avatar or sound cover shared by many posts is saved and billed once.

### Export and integrations

The results go into an Apify dataset. From there you can:

- download them as JSON, CSV, Excel, XML, HTML, or RSS from the **Output** tab;
- send them to Google Sheets, Slack, Zapier, Make, and other tools through Apify integrations;
- schedule runs, for example every morning, to track a hashtag over time;
- start runs and read the results from your own code through the Apify API.

#### Run it through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/<username>~tiktok-hashtag-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"hashtags": ["cats"], "resultsPerPage": 30}'
```

The call waits for the run to finish and returns the posts as a JSON array. You'll find your API token in the integrations section of Apify Console settings.

### FAQ

#### Do I need a TikTok account?

No. The actor reads public hashtag and profile pages the same way a logged-out visitor sees them.

#### Can I scrape TikTok profiles?

Yes. Add usernames or profile URLs to `profiles`. You can take each profile's videos, its reposts, or both, and sort the videos by latest, popular, or oldest.

#### Can I scrape TikTok search results?

Not with this actor. TikTok's search asks logged-out visitors to solve a captcha, so this actor works with hashtags and profiles, which stay open.

#### Why did I get fewer posts than I asked for?

TikTok shows logged-out visitors about 60 to 90 posts per hashtag and about 25 per profile section. Small hashtags and profiles can have fewer posts in total. Add related hashtags, or switch a profile's order, to collect more.

#### Why are some fields missing from some posts?

TikTok doesn't send every field for every post. `locationMeta` appears only on geotagged posts, `subtitleLinks` only when TikTok has generated captions, `slideshowImageLinks` only on photo posts, and `musicAlbum` only when TikTok knows the album.

#### Why do the TikTok links in my results stop working?

TikTok signs its media links for a few hours. Turn on the downloads for covers, avatars, images, or subtitles to get permanent copies.

#### Are the numbers exact?

The counts match what TikTok shows on its site, and TikTok rounds large ones. That's why you'll see values like `2000000` views or `105000` likes.

#### Is it legal to scrape TikTok?

The actor collects only public data that anyone can see without logging in. Public posts can still contain personal data, so make sure you have a legitimate reason to collect it and follow the GDPR and other laws that apply to you. If you're not sure, ask a lawyer.

### Disclaimer

This actor is provided as is, without warranty. You're responsible for how you use it and for following TikTok's terms of service and the laws that apply to you. TikTok isn't affiliated with this actor.

# Actor input Schema

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

Hashtags to scrape, with or without #. Full https://www.tiktok.com/tag/... URLs work too. Add hashtags, profiles, or both.

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

Profiles to scrape: a username (nasa), an @username (@nasa), or a full https://www.tiktok.com/@nasa URL.

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

Which posts to take from each profile: its own videos, the posts it reposted, or both.

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

The order TikTok lists a profile's videos in: newest first, most viewed first, or oldest first. Reposts always come newest first.

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

The maximum number of posts to scrape from each hashtag and from each profile, counting all of the profile's sections together. Without a logged-in session TikTok serves roughly 60–90 posts per hashtag and about 25 per profile section.

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

Skip posts the author pinned.

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

Store video covers in the key-value store and link them from videoMeta.coverUrl.

## `shouldDownloadSlideshowImages` (type: `boolean`):

Store slideshow images and link them from slideshowImageLinks\[].downloadLink.

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

Store author avatars and link them from authorMeta.avatar.

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

Store sound covers and link them from musicMeta.coverMediumUrl.

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

Store subtitle files and link them from videoMeta.subtitleLinks\[].downloadLink.

## `proxyCountryCode` (type: `string`):

Two-letter country code (US, DE, ...) to route the browser through Apify residential proxy in that country. "None" uses Apify datacenter proxy.

## Actor input object example

```json
{
  "hashtags": [
    "fyp"
  ],
  "profileScrapeSections": [
    "videos"
  ],
  "profileSorting": "latest",
  "resultsPerPage": 100,
  "excludePinnedPosts": false,
  "shouldDownloadCovers": false,
  "shouldDownloadSlideshowImages": false,
  "shouldDownloadAvatars": false,
  "shouldDownloadMusicCovers": false,
  "downloadSubtitlesOptions": "NEVER_DOWNLOAD_SUBTITLES",
  "proxyCountryCode": "None"
}
```

# Actor output Schema

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

One item per TikTok post found under the input hashtags.

## `files` (type: `string`):

Covers, avatars, music covers, slideshow images, and subtitles saved by the download options. Empty when all downloads are off.

# 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 = {
    "hashtags": [
        "fyp"
    ],
    "resultsPerPage": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("donjuan_mime/tiktok-parser").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 = {
    "hashtags": ["fyp"],
    "resultsPerPage": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("donjuan_mime/tiktok-parser").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 '{
  "hashtags": [
    "fyp"
  ],
  "resultsPerPage": 100
}' |
apify call donjuan_mime/tiktok-parser --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,donjuan_mime/tiktok-parser"
        }
    }
}
```

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/cNVZaCLVtWrgPtBTL/builds/Hox97lKN0TPlBCgLz/openapi.json
