# TikTok Hashtag Scraper - Video & Sound Downloader (`mrdoe/tiktok-hashtag-scraper`) Actor

Scrape TikTok videos by hashtag - play, like, comment, share and favorite counts, captions, creator and sound info - plus optional MP4 video and MP3 sound download. No TikTok login required.

- **URL**: https://apify.com/mrdoe/tiktok-hashtag-scraper.md
- **Developed by:** [MrDoe](https://apify.com/mrdoe) (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 $1.50 / 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.
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?

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 Hashtag Scraper](./assets/hero.png)

## TikTok Hashtag Scraper — scrape videos by hashtag & download them (MP4 + MP3)

**Give it a TikTok hashtag and get every video under it as clean data — play, like, comment, share and favorite counts, the caption, the creator, and the sound — plus an optional download of the video file and its audio track.** No TikTok login, no cookies, no account.

This Actor is a **TikTok hashtag scraper**, a **TikTok video downloader**, and a **TikTok sound / audio downloader** in one.

***

### What does the TikTok Hashtag Scraper do?

Point it at one or more TikTok hashtags (`#cooking`, `cooking`, or `https://www.tiktok.com/tag/cooking`). It collects the videos under each hashtag and returns one dataset row per video. By default it also downloads each video as an `.mp4` and its sound as an `.mp3` to storage, with direct links on the row.

![How the TikTok Hashtag Scraper works](./assets/how-it-works.png)

### Why use this TikTok hashtag scraper?

- **Trend & campaign tracking** — pull the full engagement set (plays, likes, comments, shares, favorites) for every recent video on a hashtag, in one run.
- **Sound & creator research** — every row carries the video's music/sound (title, author, original vs. licensed) and the creator's handle, nickname and verification.
- **Content archives** — download the actual `.mp4` and `.mp3` files straight into Apify storage, not just links that expire.
- **No login** — no account, no cookies, nothing to connect and no account to get restricted.
- **Just works** — the Actor handles the hard part (bot detection, rate limits, rotating identities, retries) so you don't manage any of it.
- **Standard exports** — JSON, CSV, Excel, XML, or the Apify API.

### What makes this Actor different?

- **Complete data in one pass** — every engagement count, the caption, the creator, the sound, and the actual video and audio files. No second tool, no stitching results together.
- **Reliable at scale** — built to keep working through TikTok's frequent anti-scraping changes, with automatic retries and identity rotation handled for you.
- **Real downloads** — MP4 + MP3 saved straight to storage with permanent links, so what you collect today still opens next month.
- **No account risk** — nothing is ever logged in, so there's no account to rate-limit, flag or ban.

### How it works

1. **Your input** — one or more hashtags, plus `maxItems` per hashtag and a `downloadType`.
2. **The Actor collects the data** — it takes care of everything between your input and clean results: anti-bot handling, rate limiting, rotating identities over residential IPs, retries and pagination.
3. **Output** — one dataset row per video, plus the downloaded media files in the key-value store.

### What data you get

| Field                                                         | Description                                                                         |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `url` / `id`                                                  | Video permalink and ID                                                              |
| `hashtag`                                                     | The input hashtag this video was collected under                                    |
| `hashtagsInCaption`                                           | Every hashtag used in the video's caption                                           |
| `postedAt`                                                    | Publish time, ISO 8601                                                              |
| `description`                                                 | Caption text                                                                        |
| `playCount`                                                   | Views                                                                               |
| `likeCount` / `commentCount` / `shareCount` / `favoriteCount` | Engagement counts                                                                   |
| `duration`                                                    | Video length in seconds                                                             |
| `videoTemporaryUrl`                                           | TikTok CDN link to the video (expires)                                              |
| `audioTemporaryUrl`                                           | TikTok CDN link to the sound (expires; original sounds only)                        |
| `videoStorageUrl`                                             | Permanent key-value-store link to the `.mp4` — set when the download includes video |
| `audioStorageUrl`                                             | Permanent key-value-store link to the `.mp3` — set when the download includes audio |
| `music`                                                       | `{ id, title, authorName, original }`                                               |
| `author`                                                      | `{ id, uniqueId, nickname, avatarUrl, verified, signature }`                        |

### Where do the downloaded video and audio go?

Based on `downloadType` (default **Video + sound**), the files are written to the run's **key-value store**:

| downloadType  | Files saved                                             | Fields with the links                |
| ------------- | ------------------------------------------------------- | ------------------------------------ |
| `video+audio` | `<hashtag>-<videoId>.mp4` and `<hashtag>-<videoId>.mp3` | `videoStorageUrl`, `audioStorageUrl` |
| `video`       | `<hashtag>-<videoId>.mp4`                               | `videoStorageUrl`                    |
| `audio`       | `<hashtag>-<videoId>.mp3`                               | `audioStorageUrl`                    |

Each link looks like:

```text
https://api.apify.com/v2/key-value-stores/<storeId>/records/<hashtag>-<videoId>.mp4
```

Those links are **permanent** (they live as long as the run's storage) and need no auth for a public run. Browse every file under the run's **Storage → Key-value store** tab in the Apify Console, or list them via the API.

`videoTemporaryUrl` / `audioTemporaryUrl` are temporary source links that **expire within hours** — use them only if you're fetching immediately; otherwise use the storage links.

**The MP3:** for original sounds you get the clean source track; for licensed / commercial tracks the audio is taken straight from the video. Either way you get one `.mp3` per video.

### Input parameters

| Parameter                | Type    | Required | Default           | Description                                                                               |
| ------------------------ | ------- | -------- | ----------------- | ----------------------------------------------------------------------------------------- |
| `hashtags`               | Array   | Yes      | —                 | TikTok hashtags to scrape (`#name`, `name`, or a `tiktok.com/tag/name` URL).              |
| `maxItems`               | Integer | No       | `5`               | Stop after this many videos **per hashtag**. Raise it for a full export.                  |
| `downloadType`           | Select  | No       | `video+audio`     | `video+audio` (MP4 + MP3), `video` (MP4 only), or `audio` (MP3 only).                     |
| `proxyConfiguration`     | Object  | Yes      | Apify Residential | Required. TikTok flags datacenter IPs hard — a residential proxy is strongly recommended. |
| `notificationWebhookUrl` | String  | No       | —                 | A Discord or Slack incoming webhook (or any endpoint) to notify when the run finishes.    |

### Example output

```json
{
    "url": "https://www.tiktok.com/@chefkate/video/7541116064218877215",
    "id": "7541116064218877215",
    "hashtag": "cooking",
    "hashtagsInCaption": ["cooking", "foodie", "pasta"],
    "postedAt": "2026-08-10T14:32:00.000Z",
    "description": "weeknight pasta that actually slaps 🍝 #cooking #foodie #pasta",
    "playCount": 4600000,
    "likeCount": 227800,
    "commentCount": 2453,
    "shareCount": 9972,
    "favoriteCount": 15208,
    "duration": 61,
    "videoTemporaryUrl": "https://v16-webapp-prime.tiktok.com/video/tos/...",
    "videoStorageUrl": "https://api.apify.com/v2/key-value-stores/abc123/records/cooking-7541116064218877215.mp4",
    "audioTemporaryUrl": "https://sf16-ies-music-va.tiktokcdn.com/obj/...",
    "audioStorageUrl": "https://api.apify.com/v2/key-value-stores/abc123/records/cooking-7541116064218877215.mp3",
    "music": { "id": "7006274970402473986", "title": "original sound", "authorName": "chefkate", "original": true },
    "author": {
        "id": "6841234567890123456",
        "uniqueId": "chefkate",
        "nickname": "Chef Kate",
        "avatarUrl": "https://p16-common-sign.tiktokcdn.com/...",
        "verified": false,
        "signature": "dinner in 20 min or less"
    }
}
```

You can download the dataset as JSON, CSV, Excel, or XML.

### How to use the TikTok Hashtag Scraper

1. Open the Actor's **Input** tab.
2. Add one or more **`hashtags`** (`#cooking`, `cooking`, or a `tiktok.com/tag/...` URL).
3. Set **`maxItems`** — how many videos per hashtag.
4. Pick a **`downloadType`** — video + sound, video only, or sound only.
5. Press **Start**. Rows appear in the **Dataset** tab; the `.mp4` / `.mp3` files land in the **Key-value store** tab.

### Usage examples

**Sound library from a hashtag — audio files only**

```json
{ "hashtags": ["cooking"], "maxItems": 30, "downloadType": "audio" }
```

**Download every video + sound for a campaign hashtag**

```json
{ "hashtags": ["myBrandChallenge"], "maxItems": 100, "downloadType": "video+audio" }
```

**Several hashtags with a Slack ping on finish**

```json
{
    "hashtags": ["cooking", "baking", "mealprep"],
    "maxItems": 25,
    "downloadType": "video",
    "notificationWebhookUrl": "https://hooks.slack.com/services/..."
}
```

### Tips for best results

- **Residential proxy, always.** A good residential proxy pool is the single biggest reliability factor. If a run returns 0 videos, try a different proxy country.
- **Temporary links expire.** Use `videoStorageUrl` / `audioStorageUrl` (or download promptly) for anything you keep.
- **`maxItems` is per hashtag**, not per run.
- **A retried request is normal** and clears on its own.

### Limitations

- **Public content only.** Private or age-restricted videos, and hashtags with no public videos, return nothing.
- TikTok's anti-scraping posture changes often; a run may need a retry or two, and very large exports go faster with a bigger residential proxy pool.
- `videoTemporaryUrl` / `audioTemporaryUrl` expire within hours.
- A row is a snapshot at collection time; counts keep moving.
- For licensed / commercial tracks the `.mp3` is taken from the video rather than a standalone source.

### FAQ

**Can I download TikTok videos by hashtag with this Actor?**
Yes. Set `downloadType` to `video` or `video+audio` — each video's `.mp4` is saved to the key-value store with a permanent link in `videoStorageUrl`.

**Can I download the sound / music from hashtag videos?**
Yes. Set `downloadType` to `audio` or `video+audio` — you get an `.mp3` per video in `audioStorageUrl`: the clean source track for original sounds, and the track taken from the video for licensed music.

**Where are the downloaded files saved?**
In the run's key-value store, as `<hashtag>-<videoId>.mp4` / `.mp3`. The dataset rows carry the links, and you can browse or download them from the Storage tab in the Apify Console.

**Do I need a TikTok account or login?**
No. It only uses what TikTok shows to logged-out visitors — no account, no cookies.

**How many videos can it collect per hashtag?**
As many as `maxItems`. It keeps paging through the hashtag feed until it reaches your limit or the end of the feed.

**Why did a run return 0 videos?**
Almost always a temporary block (try a different residential proxy country) or a hashtag with no public videos. The run log says which.

**How fresh is the data?**
Every run reads the live feed. Schedule the Actor to build a trend history for a hashtag.

### Support

Found a bug or a field that changed shape? Open an issue on the Actor's **Issues** tab in the Apify Console.

### Legal / responsible use

This Actor accesses only data TikTok serves publicly to logged-out visitors and does not use login credentials. You are responsible for how you use the Actor and its output, including compliance with TikTok's Terms of Service, copyright in the videos and music you download, and the data-protection laws that apply to you.

# Actor input Schema

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

TikTok hashtags to scrape videos from. Enter them with or without the leading "#" (e.g. "cooking" or "#cooking"), or paste a full URL like "https://www.tiktok.com/tag/cooking". Each hashtag returns its feed of videos, newest and trending first, up to "Max videos per hashtag".

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

Stop scraping a hashtag once this many videos have been collected. Raise it for a larger export.

## `downloadType` (type: `string`):

Video + sound stores both an MP4 and an MP3 per video. Video only stores just the MP4. Sound only stores just the MP3 (from TikTok's music CDN, or extracted from the video with ffmpeg for licensed tracks). Files land in the run's key-value store, with links added to each dataset row.

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

Required - TikTok aggressively rate-limits and flags datacenter IPs. A residential proxy is strongly recommended.

## `notificationWebhookUrl` (type: `string`):

Get notified when the run finishes. Paste a Discord or Slack incoming webhook URL to post a message there, or any other webhook endpoint (Zapier, Make, Pipedream, an email-forwarding webhook) to receive a JSON summary. Leave blank to disable.

## Actor input object example

```json
{
  "hashtags": [
    "cooking"
  ],
  "maxItems": 5,
  "downloadType": "video+audio",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "hashtags": [
        "cooking"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/tiktok-hashtag-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 = { "hashtags": ["cooking"] }

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/tiktok-hashtag-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 '{
  "hashtags": [
    "cooking"
  ]
}' |
apify call mrdoe/tiktok-hashtag-scraper --silent --output-dataset

```

## MCP server setup

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