# TikTok Trends Scraper — Hashtags, Videos, Creators & Sounds (`memo23/tiktok-trends-scraper`) Actor

TikTok Trends Scraper: ranked Creative Center hashtags across 27 markets with posts, views and popularity curves, plus trending videos, creators and sounds from public Explore. Views, likes, comments and shares on every video row. No login, no cookies, no ad account. JSON or CSV out.

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

## Pricing

from $15.00 / 1,000 trend rows

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Trends Scraper

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/tiktok-trends-logo.png" width="140" alt="TikTok Trends Scraper">
</p>

See what is climbing on TikTok before it peaks: ranked hashtags from the Creative Center across 27 markets, plus the videos, creators and sounds trending right now on public Explore. No login, no cookies, no ad account.

| Trend type | Where it comes from | What one row is |
|---|---|---|
| `hashtag` | Creative Center ranking | one hashtag, in one country, for one look-back window |
| `video` | public TikTok Explore | one video trending at scrape time, with full engagement counts |
| `creator` | derived | one creator, aggregated across the trends they surfaced in |
| `sound` | public TikTok Explore | one sound, aggregated across the trending videos using it |

> Hashtags arrive over plain HTTP — no browser, no token. Only the Explore surfaces need a browser.

### Why Use This Scraper

- **Four trend surfaces in one run**, not four separate actors to stitch together.
- **27 markets in one sweep.** Leave the country list empty and every supported market is scraped, so you see what is rising in Brazil and Japan, not only at home.
- **A popularity curve on every hashtag**, plus a `trendDirection` of rising / falling / flat, so an early climb is distinguishable from a fading peak.
- **Real engagement on videos** — views, likes, comments, shares, saves and a derived engagement rate, not just a view count.
- **Creators come with context**: which hashtags and videos they surfaced in, and how many times.
- **Optional media persistence.** TikTok CDN links expire within hours; switch `saveMedia` on and covers and avatars are copied into your run's storage.

### Overview

Every row is flat and carries a `trendType` telling you which of the four shapes it is. Nothing is nested inside a per-country wrapper — filter by `trendType` and `country` and you have the ranking you asked for.

Two things worth knowing before planning a run:

- **TikTok returns three hashtags per country per look-back window** to a logged-out client. Its own response says so. Volume comes from sweeping countries and windows, never from a bigger `maxResults`.
- **Explore has no look-back window.** Videos and sounds are what is trending at scrape time, so those rows carry `period: null` and follow the exit IP rather than your country list.

### Supported Inputs

| Input | What it does |
|---|---|
| `trendTypes` | any combination of `hashtag`, `video`, `creator`, `sound` |
| `countries` | ISO-2 codes; an empty list sweeps all 27 supported markets |
| `periods` | any of `7`, `30`, `120` days — hashtags only |
| `maxResults` | cap per trend type per country (hashtags are capped at 3 by TikTok) |
| `industry` | keep only hashtags carrying a given Creative Center industry id |
| `saveMedia` | copy covers and avatars into the run's key-value store |

Supported markets: US, GB, FR, DE, IT, ES, AR, AU, BR, CA, CO, EG, ID, IL, JP, KR, MY, MX, PH, SA, SG, ZA, TW, TH, TR, AE, VN.

**Not supported**, so you know before you start:

- **Start URLs.** This actor takes filters, not links. To scrape a specific hashtag, profile or video, use the dedicated hashtag, profile or post scrapers listed further down.
- **Countries outside the 27 above.** The Creative Center's own filter config defines the list; an unsupported code returns nothing for that market.
- **Look-back windows other than 7, 30 or 120 days.** Those three are what the surface accepts.
- **Per-country trending videos or sounds.** Explore follows the exit IP, not a country parameter.
- **More than three hashtags per country and window.** That is TikTok's cap for a logged-out client, not a setting.

### Use Cases

| You are | What you get from it |
|---|---|
| Social media manager | tomorrow's hashtags for the content calendar, per market |
| Brand or agency strategist | which trends are rising vs fading, before the brief is written |
| Influencer marketer | creators ranked by followers, with the trends they actually appear in |
| Music or label researcher | sounds ranked by how many trending videos carry them |
| Market analyst | the same ranking across 27 countries, in one dataset |
| Dashboard builder | a scheduled run feeding a table with a stable row shape |

### How It Works

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-tiktok-trends.png" width="900" alt="How the TikTok Trends Scraper works">
</p>

1. **You pick the surfaces and the markets** — trend types, country codes, look-back windows.
2. **Hashtags are fetched over plain HTTP.** One request per country and window hits the Creative Center's own SSR data loader, which answers with clean JSON and needs no token, no cookies and no browser.
3. **Explore runs once in a stealth browser.** Its `item_list` responses carry both the trending videos and the music attached to them, so one pass covers two surfaces.
4. **Creators are derived on the way out**, by aggregating the top-creator lists that ride inside every hashtag row together with the authors of the trending videos, then ranking by follower count.
5. **Rows are pushed as they are produced**, each tagged with its `trendType`, country and window. A run that finds nothing fails instead of finishing green and empty.

### Input Configuration

| Field | Type | Required | Notes |
|---|---|---|---|
| `trendTypes` | array | yes | `hashtag`, `video`, `creator`, `sound`. Default `["hashtag"]` |
| `countries` | array | no | ISO-2 codes. Empty → all 27 markets. Default `["US"]` |
| `periods` | array | no | `"7"`, `"30"`, `"120"`. Default `["7"]` |
| `maxResults` | integer | no | 1–100 per type per country. Default `30` |
| `industry` | string | no | Creative Center industry id, matched against `industryIds` |
| `saveMedia` | boolean | no | Adds `*Stored` fields with permanent URLs. Default `false` |
| `proxy` | object | no | Override the built-in residential proxy |

#### One market, fast

```json
{
  "trendTypes": ["hashtag"],
  "countries": ["US"],
  "periods": ["7"]
}
```

#### Everything, everywhere

```json
{
  "trendTypes": ["hashtag", "video", "creator", "sound"],
  "countries": [],
  "periods": ["7", "30"],
  "maxResults": 50,
  "saveMedia": true
}
```

### Output Overview

One row per trending entity. Hashtag and creator rows carry `country` and `period`; video and sound rows carry the run's first country as a label and `period: null`, because Explore is a right-now surface.

### Output Samples

#### A hashtag row

```jsonc
{
  "trendType": "hashtag",
  "country": "US",
  "period": 7,
  "rank": 1,
  "hashtagName": "dollyparton",
  "hashtagId": "2534",
  "posts": 218880,
  "views": 852867790,
  "industryIds": ["23000000000"],
  "trendDirection": "rising",
  "popularityCurve": [
    { "timestamp": 1787184000, "value": 0.874 },
    { "timestamp": 1787270400, "value": 2.072 }
  ],
  "topCreators": [
    {
      "handle": "dailymail",
      "nickname": "Daily Mail",
      "followers": 26613005,
      "avatarUrl": "https://p16-common-sign.tiktokcdn.com/…",
      "ttUid": "6739867522710406149"
    }
  ],
  "url": "https://www.tiktok.com/tag/dollyparton",
  "scrapedAt": "2026-08-28T05:39:08.275Z"
}
```

#### A video row

```jsonc
{
  "trendType": "video",
  "country": "US",
  "period": null,
  "rank": 1,
  "videoId": "7664782256527002901",
  "title": "@Légende peyi a 😂🔥 #menlégende #funnyvideo #talent",
  "videoUrl": "https://www.tiktok.com/@menlegende/video/7664782256527002901",
  "coverUrl": "https://p16-common-sign.tiktokcdn-us.com/…",
  "duration": 12,
  "createTime": 1784596201,
  "authorHandle": "menlegende",
  "authorNickname": "Menlégende😂🔥",
  "authorFollowers": 1400000,
  "authorVerified": false,
  "views": 115600000,
  "likes": 3800000,
  "comments": 39700,
  "shares": 305200,
  "saves": 240500,
  "engagementRate": 0.035856,
  "hashtags": ["menlégende", "funnyvideo", "talent", "funnybike", "fyp"],
  "soundId": "7437246680426122030",
  "soundTitle": "original sound",
  "source": "public-tiktok-explore"
}
```

#### A creator row

```jsonc
{
  "trendType": "creator",
  "country": "US",
  "period": 7,
  "rank": 1,
  "handle": "dailymail",
  "nickname": "Daily Mail",
  "followers": 26612999,
  "ttUid": "6739867522710406149",
  "trendingAppearances": 2,
  "surfacedVia": "hashtag",
  "trendingContexts": ["#dollyparton", "#timcurry"],
  "url": "https://www.tiktok.com/@dailymail",
  "derived": true
}
```

#### A sound row

```jsonc
{
  "trendType": "sound",
  "country": "US",
  "rank": 1,
  "soundId": "7437246680426122030",
  "title": "original sound",
  "authorName": "daily_laugh_akrobetoo",
  "isOriginal": true,
  "duration": 23,
  "playUrl": "https://v19.tiktokcdn-us.com/…",
  "trendingVideoCount": 1,
  "combinedPlays": 115600000,
  "url": "https://www.tiktok.com/music/original-sound-7437246680426122030",
  "source": "public-tiktok-explore",
  "derived": true
}
```

### Key Output Fields

**Shared** — `trendType`, `country`, `period`, `rank`, `url`, `scrapedAt`

**Hashtag** — `hashtagName`, `hashtagId`, `posts`, `views`, `industryIds`, `trendDirection`, `popularityCurve[]`, `topCreators[]`

**Video** — `videoId`, `title`, `videoUrl`, `coverUrl`, `duration`, `createTime`, `authorHandle`, `authorNickname`, `authorBio`, `authorId`, `authorAvatarUrl`, `authorFollowers`, `authorVerified`, `views`, `likes`, `comments`, `shares`, `saves`, `engagementRate`, `hashtags[]`, `soundId`, `soundTitle`, `source`

**Creator** — `handle`, `nickname`, `followers`, `avatarUrl`, `ttUid`, `trendingAppearances`, `surfacedVia`, `trendingContexts[]`, `derived`

**Sound** — `soundId`, `title`, `authorName`, `isOriginal`, `duration`, `coverUrl`, `playUrl`, `trendingVideoCount`, `combinedPlays`, `source`, `derived`

With `saveMedia` on, each media field gains a sibling — `coverUrlStored`, `avatarUrlStored` — pointing at a permanent copy in the run's key-value store.

### FAQ

**Why only three hashtags per country?** That is TikTok's own cap for a logged-out client; the response itself carries `pagination: {hasMore: false, totalCount: 3}`. Raising `maxResults` will not change it. Sweep more countries and more look-back windows instead — 27 markets × 3 windows is 243 hashtag rows in one run.

**Why do video rows have `period: null`?** Explore has no look-back window. Those videos are what is trending at scrape time, which is a different question from what ranked over the last 30 days.

**Can I get trending videos per country?** Not reliably. Explore follows the exit IP rather than a country parameter, so video and sound rows are labelled with the first country you asked for and are US-centric by default.

**Are creators scraped or derived?** Derived, and every creator row says so with `derived: true`. The Creative Center's own creator tab serves nothing to a logged-out client, so creators are aggregated from the top-creator lists inside hashtag rows and from the authors of trending videos.

**Do I need a TikTok account or cookies?** No. Nothing in this actor logs in.

**Why do image and audio URLs stop working after a while?** TikTok signs CDN links with an expiry. Turn on `saveMedia` to keep permanent copies in the run's storage.

**Can I schedule it?** Yes. A daily run with the same input gives a clean time series, since every row carries `scrapedAt`, `country` and `period`.

**What happens if TikTok returns nothing?** The run fails loudly rather than finishing green with an empty dataset, so a broken schedule is visible immediately.

### Support

Found a bug or need a field added? Open an issue on the Actor's **Issues** tab in Apify Console, or email <muhamed.didovic@gmail.com>.

### Additional Services

Need a custom TikTok or social-media scraper, or a private version of this Actor? Reach out at <muhamed.didovic@gmail.com>.

### Explore More Scrapers

- **[TikTok Hashtag Scraper](https://apify.com/memo23/tiktok-hashtag-scraper)** — every video under a hashtag, with stats and creators
- **[TikTok Music & Sound Scraper](https://apify.com/memo23/tiktok-music-scraper)** — search sounds by keyword and see who uses them
- **[TikTok Profile Scraper](https://apify.com/memo23/tiktok-profile-scraper)** — account stats and every post
- **[TikTok Search Scraper](https://apify.com/memo23/tiktok-search-scraper)** — TikTok's ranked search results for any keyword
- **[TikTok Comments Scraper](https://apify.com/memo23/tiktok-comments-scraper)** — comments and replies with commenter data

Browse the full portfolio: [muhamed-didovic.github.io](https://muhamed-didovic.github.io/)

### 🤖 For AI Agents & LLM Apps

**Purpose:** Return what is trending on TikTok — ranked hashtags per country and look-back window, plus videos, creators and sounds trending right now.

**Minimal tested input:**

```json
{ "trendTypes": ["hashtag"], "countries": ["US"], "periods": ["7"] }
```

**Output:** array of flat objects. Every row carries `trendType`, one of `hashtag`, `video`, `creator`, `sound`. Shared fields: `trendType`, `country`, `period`, `rank`, `url`, `scrapedAt`. Hashtag rows add `hashtagName`, `hashtagId`, `posts`, `views`, `industryIds`, `trendDirection`, `popularityCurve`, `topCreators`. Video rows add `videoId`, `title`, `videoUrl`, `coverUrl`, `duration`, `createTime`, `authorHandle`, `authorNickname`, `authorBio`, `authorId`, `authorAvatarUrl`, `authorFollowers`, `authorVerified`, `views`, `likes`, `comments`, `shares`, `saves`, `engagementRate`, `hashtags`, `soundId`, `soundTitle`, `source`. Creator rows add `handle`, `nickname`, `followers`, `avatarUrl`, `ttUid`, `trendingAppearances`, `surfacedVia`, `trendingContexts`, `derived`. Sound rows add `soundId`, `title`, `authorName`, `isOriginal`, `duration`, `coverUrl`, `playUrl`, `trendingVideoCount`, `combinedPlays`, `source`, `derived`.

**Critical for agents:** branch on `trendType` before reading fields — the four shapes differ. Hashtags are capped at three rows per country per look-back window by TikTok, so scale a request by adding countries and periods, never by raising `maxResults`. Video and sound rows carry `period: null` and are US-centric regardless of the country list. Creator rows are aggregated rather than scraped, and say so via `derived: true`.

**Behavior & billing:** Pay-per-event — one charge per row, plus a run-start charge. A run that scrapes nothing fails rather than returning an empty dataset. No login or cookies required.

### ⚠️ Disclaimer

This Actor accesses publicly available data on TikTok for legitimate research, market-intelligence, and business-analysis purposes. It does not log in, bypass authentication, or access private content. Use of this Actor must comply with TikTok's Terms of Service and all applicable laws, including data-protection and copyright law. The authors are not responsible for any misuse. Users must:

- Respect rate limits and avoid overloading TikTok's infrastructure
- Not use scraped data to violate user privacy or platform terms
- Process any personal data only with a lawful basis and in compliance with their jurisdiction
- **Not download, republish or monetize audio or video without the rights to do so** — a returned media URL does not grant a licence to the recording

We do not store scraped data; the Actor returns it directly to your Apify dataset for your authorized use. TikTok is a trademark of ByteDance Ltd.; this Actor is not affiliated with or endorsed by TikTok or ByteDance.

### SEO Keywords

tiktok trends scraper, tiktok trending hashtags, tiktok creative center scraper, trending hashtags by country, tiktok hashtag ranking, tiktok trending videos, tiktok trending sounds, tiktok trending creators, tiktok trend analysis, tiktok hashtag popularity curve, tiktok explore scraper, tiktok trend api, social media trend monitoring, tiktok content strategy data, tiktok influencer discovery, tiktok market research, apify tiktok trends scraper

# Actor input Schema

## `trendTypes` (type: `array`):

Which trend surfaces to scrape; pick any combination. 'hashtag' = ranked hashtags from TikTok Creative Center, with posts, views, a popularity curve and top creators. 'video' = videos trending right now on public TikTok Explore, with views, likes, comments, shares. 'creator' = creators derived from the top-creator lists inside trending hashtags and from the authors of trending videos, ranked by followers. 'sound' = sounds aggregated from trending Explore videos, ranked by how many use them. Example: \["hashtag","sound"]. Default: \["hashtag"].

## `countries` (type: `array`):

ISO 3166-1 alpha-2 country codes for the hashtag ranking, e.g. \["US","GB","DE"]. Supported: US, GB, FR, DE, IT, ES, AR, AU, BR, CA, CO, EG, ID, IL, JP, KR, MY, MX, PH, SA, SG, ZA, TW, TH, TR, AE, VN. Leave the list EMPTY to sweep all 27 markets in one run. TikTok returns 3 hashtags per country per period, so more countries is how you get more rows. Videos and sounds come from Explore, which follows the exit IP rather than this list. Default: \["US"].

## `periods` (type: `array`):

Trend look-back windows for hashtags. Valid values: 7, 30, 120 — pick any combination, each one costs one extra request per country and returns its own 3 hashtags. Example: \[7,30]. Ignored for videos and sounds, which are 'right now' surfaces. Default: \[7].

## `maxResults` (type: `integer`):

Upper bound on rows per trend type, per country. Hashtags are capped by TikTok itself at 3 per country per period regardless of this value — raising it does nothing for hashtags. It does control how many videos, creators and sounds are kept. Range 1–100. Example: 50. Default: 30.

## `industry` (type: `string`):

Keep only hashtags tagged with this Creative Center industry id (matched against each row's industryIds). Leave empty for all industries. Example: "22001" (Apparel & Accessories). Applied after scraping, so it never increases the row count. Default: empty.

## `saveMedia` (type: `boolean`):

Copy avatars and video covers into this run's key-value store and add a \*Stored field next to each original URL (e.g. coverUrlStored). TikTok CDN links carry an expiry signature and rot within hours, so switch this on when the images must stay reachable. Slows the run and adds storage. Values: true or false. Default: false.

## `proxy` (type: `object`):

Optional proxy override. Leave it alone to use the built-in residential proxy, which is what the Explore surface needs — TikTok blocks datacenter IPs there. Set useApifyProxy with RESIDENTIAL groups, or supply your own proxyUrls, only if you have a reason to. Default: built-in residential.

## Actor input object example

```json
{
  "trendTypes": [
    "hashtag",
    "sound"
  ],
  "countries": [
    "US"
  ],
  "periods": [
    "7"
  ],
  "maxResults": 30,
  "saveMedia": false,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `trends` (type: `string`):

Every row in the default dataset, across all requested trend types.

# 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 = {
    "trendTypes": [
        "hashtag",
        "sound"
    ],
    "countries": [
        "US"
    ],
    "periods": [
        "7"
    ],
    "maxResults": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/tiktok-trends-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 = {
    "trendTypes": [
        "hashtag",
        "sound",
    ],
    "countries": ["US"],
    "periods": ["7"],
    "maxResults": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/tiktok-trends-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 '{
  "trendTypes": [
    "hashtag",
    "sound"
  ],
  "countries": [
    "US"
  ],
  "periods": [
    "7"
  ],
  "maxResults": 30
}' |
apify call memo23/tiktok-trends-scraper --silent --output-dataset

```

## MCP server setup

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