# TikTok Scraper: Hashtag, Search & Trending Videos, No Login (`themineworks/tiktok-hashtag-search-scraper`) Actor

Scrape TikTok videos by hashtag, keyword search or trending feed: plays, likes, shares, saves, comments, caption, music and author followers. Free date filter, optional MP4 download and a views vs creator median score to spot viral videos. No login or cookies. Works via API and MCP.

- **URL**: https://apify.com/themineworks/tiktok-hashtag-search-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (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 $0.80 / 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: Hashtag, Search and Trending Videos

Scrape public **TikTok videos by hashtag, keyword search or the trending feed**. Every video comes back as one flat row with **plays, likes, shares, saves and comments**, the caption and its hashtags, music, author followers and the exact posting time. Filter by how recently a video was posted **at no extra charge**, save the **MP4 files**, and see which videos beat the creator's usual reach. No login, no cookies and no TikTok API key.

**At a glance**

- **Inputs:** hashtags, search keywords, and the Explore (trending) feed across 21 categories
- **Per video:** plays, likes, shares, saves, comments, caption, hashtags, duration, cover, music, author followers and video count, ad and TikTok Shop flags, effects used
- **Date filter included:** keep only videos posted in the last N days, and pay only for what you keep
- **Viral check:** optional author median plays, so every video gets a "times above this creator's normal" score
- **MP4 download:** optional, saved to a link that opens anywhere without TikTok cookies
- **Fair billing:** pay per video delivered. Duplicates, videos outside your date window and blocked requests are never charged.

### What does this TikTok scraper do?

You give it hashtags, search terms, or ask for the trending feed. It reads TikTok's own feeds the way the TikTok website does, from a US browser session, and returns one row per video until it reaches your `maxItems` for each input or the feed runs out. A video found by two inputs is returned once, credited to the first input that found it, and `sourceType` and `sourceInput` tell you which one surfaced it.

### How do I scrape TikTok videos by hashtag?

Add hashtags to **Hashtags**, one per line, with or without the `#`. A `tiktok.com/tag/...` link works too. Set **Max videos per input** and, if you only want recent videos, **Posted within the last N days**.

```json
{
  "hashtags": ["jewelrytok", "engagementring"],
  "maxItems": 60,
  "postedWithinDays": 14
}
```

In our test on 26 Sep 2026, #jewelrytok, #labgrowndiamonds and #engagementring returned 60, 46 and 51 videos from the previous 14 days in one 81 second run, with plays, shares and saves filled on every row.

### How do I scrape TikTok search results for a keyword?

Add terms to **Search keywords** exactly as you would type them into TikTok's search box, for example `lab grown diamond ring`. You get the videos TikTok's video search shows for that term. TikTok's web search ignores its own date and sort options, so the date filter is applied after the results come back, and you are only charged for the videos that pass it.

### How do I get trending TikTok videos?

Turn on **Trending videos** and pick a category: All, Singing & Dancing, Comedy, Sports, Anime & Comics, Relationship, Shows, Lipsync, Daily Life, Beauty Care, Games, Society, Outfit, Cars, Food, Animals, Family, Drama, Fitness & Health, Education or Technology. Each run is a fresh draw from TikTok's Explore feed, so repeated runs return different videos.

### How do I find TikTok videos that are going viral?

Big play counts alone mislead: a creator with 5 million followers gets a million plays on an average day. Turn on **Author median plays** and each video gets:

- `authorMedianPlays`: the median play count of that creator's recent videos
- `playsVsAuthorMedian`: this video's plays divided by that median

A `playsVsAuthorMedian` of 8 means the video did eight times the creator's normal reach, which is the real sign that a format, hook or sound is taking off. Sort by it to find breakout videos from small accounts that raw play counts would bury.

### What data do I get for each TikTok video?

A real row, from a verified jewellery brand found through the #jewelry hashtag (the long video and cover links are shortened here):

```json
{
  "id": "7612802409273806110",
  "webVideoUrl": "https://www.tiktok.com/@traxnyc/video/7612802409273806110",
  "createTime": 1772493706,
  "createTimeISO": "2026-03-02T23:21:46.000Z",
  "text": "A Gold hand holding a giant diamond #diamonds #gold #jewelry #traxnyc ",
  "textLanguage": "en",
  "hashtags": ["diamonds", "gold", "jewelry", "traxnyc"],
  "playCount": 1600000,
  "diggCount": 154900,
  "shareCount": 985,
  "collectCount": 5196,
  "commentCount": 581,
  "durationSec": 17,
  "videoUrl": "https://v16-webapp-prime.us.tiktok.com/video/tos/useast8/tos...",
  "coverUrl": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-...",
  "isSlideshow": false,
  "musicId": "7612802442572466974",
  "musicTitle": "original sound",
  "musicAuthor": "TraxNYC",
  "musicOriginal": true,
  "authorUsername": "traxnyc",
  "authorNickname": "TraxNYC",
  "authorId": "6606429515621908486",
  "authorFollowers": 3200000,
  "authorVideoCount": 1094,
  "authorVerified": true,
  "isAd": false,
  "isSponsored": false,
  "isECVideo": false,
  "effectStickers": ["HD Clarity"],
  "sourceType": "hashtag",
  "sourceInput": "jewelry",
  "scrapedAt": "2026-09-26T12:30:27.282Z"
}
```

| Field | What it holds |
|---|---|
| `id`, `webVideoUrl` | TikTok's video id and the public link |
| `createTime`, `createTimeISO` | When the video was posted (unix seconds and ISO) |
| `text`, `hashtags`, `textLanguage` | Caption, its hashtags, and the caption language |
| `playCount` | Views |
| `diggCount` | Likes |
| `shareCount` | Shares |
| `collectCount` | Saves (favourites) |
| `commentCount` | Comments |
| `durationSec`, `isSlideshow` | Length in seconds; whether it is a photo slideshow |
| `coverUrl` | Cover image |
| `musicId`, `musicTitle`, `musicAuthor`, `musicOriginal` | The sound, and whether it is the creator's original sound |
| `authorUsername`, `authorNickname`, `authorId`, `authorSecUid` | Who posted it |
| `authorFollowers`, `authorVideoCount`, `authorVerified` | The creator's audience size, output and verification |
| `isAd`, `isSponsored`, `isECVideo` | Paid ad, branded or sponsored content, TikTok Shop video |
| `effectStickers` | Effects and filters used in the video |
| `locationCreated`, `poiName`, `poiAddress`, `poiCity`, `poiCategory` | Location tags, when the creator added one |
| `authorMedianPlays`, `authorMedianSample`, `playsVsAuthorMedian` | With Author median plays on |
| `videoFileUrl`, `videoFileBytes` | With Download videos on |
| `videoUrl`, `downloadAddr` | TikTok's own video addresses (see the download question below) |
| `sourceType`, `sourceInput`, `scrapedAt` | Which input found it, and when |

A run summary is saved to the key-value store record `OUTPUT`: for each input, videos requested, delivered, filtered out by date, duplicates and pages read, plus a `blocked` flag that is true only if TikTok refused every session for an input.

### Can I download the TikTok videos as MP4 files?

Yes. Turn on **Download videos** and each MP4 is saved to the run's key-value store, with a public link in `videoFileUrl` that opens in any browser or editor without a TikTok login. TikTok's own `videoUrl` only plays with the cookies of the session that fetched it and expires within hours, which is why it is not useful on its own.

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

Everything is on the **Pricing** tab:

| Charge | Free plan | Starter (Bronze) | Scale (Silver) | Business (Gold) and up |
|---|---|---|---|---|
| Per video delivered | $0.0028 | $0.0022 | $0.0015 | $0.0008 |
| Per MP4 downloaded | $0.002 | $0.002 | $0.002 | $0.002 |
| Per run started, default 2 GB memory | $0.005 | $0.005 | $0.005 | $0.005 |

The date filter and author median plays cost nothing extra. Compute and proxies are included.

What real jobs cost:

| Job | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 50 videos from one hashtag | $0.15 | $0.12 | $0.08 | $0.05 |
| 1,000 videos (10 hashtags, 100 each) | $2.81 | $2.21 | $1.51 | $0.81 |
| 100 videos with MP4 download | $0.49 | $0.43 | $0.36 | $0.29 |

Apify's free monthly credit covers about 1,700 videos.

**Charged:** each video delivered to your dataset, each MP4 that saved, and one start charge per run.

**Never charged:** videos outside your date window, duplicates found by several inputs, failed downloads, and anything TikTok refused to serve.

### Can I filter TikTok videos by date?

Yes, with **Posted within the last N days**. It is included in the price, and filtered out videos are not charged. Note that TikTok's hashtag feed is not in date order, so the actor reads the whole feed until it has enough recent videos or the feed ends.

### Why did a hashtag return fewer videos than I asked for?

TikTok's web hashtag feed only holds a few hundred videos (160 to 195 in our tests), mixed in age. With a strict date window, only the recent part counts. The `OUTPUT` record shows `feed_items_seen` and `pages` for each input, so you can see the feed was read to the end. Very broad tags such as #fyp return nothing on TikTok's web feed at all. Add search keywords alongside hashtags to widen coverage.

### Which countries does it work from?

The United States. On 26 Sep 2026 TikTok refused its web video feeds to logged out visitors from the UK, Europe, Canada, Australia, Brazil, Japan and Mexico, so the actor browses from the US. The videos themselves can be from creators anywhere; searching in another language or for a local hashtag finds local content.

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

No. The actor reads public data the way the TikTok website shows it to a visitor who is not logged in. There is nothing of yours to connect, block or ban.

### How do I use it from the API, Python or JavaScript?

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("themineworks/tiktok-hashtag-search-scraper").call(run_input={
    "hashtags": ["jewelrytok"],
    "maxItems": 50,
    "postedWithinDays": 14,
})
for video in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(video["playCount"], video["webVideoUrl"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('themineworks/tiktok-hashtag-search-scraper').call({
    keywords: ['lab grown diamond ring'],
    maxItems: 40,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'videos');
```

It also runs on a **schedule** (for example every morning for your niche hashtags), and connects to **n8n, Make, Zapier, Google Sheets and webhooks** through Apify's integrations.

### Can AI agents use it through MCP?

Yes. Add Apify's MCP server to Claude, ChatGPT, Cursor or any MCP client with this actor enabled:

```
https://mcp.apify.com/?tools=themineworks/tiktok-hashtag-search-scraper
```

Your agent can then ask for "the most saved #skincare videos from the last week" and reason over real numbers.

### What is it used for?

- **Trend and format research:** find the hooks, sounds and formats taking off in your niche before they peak
- **Content planning:** see which videos in a hashtag earn saves and shares, not just views
- **Influencer discovery:** find creators whose videos beat their own average, with follower counts to size them
- **Competitor and brand monitoring:** track what gets posted under your brand, product or campaign hashtag
- **Ad and TikTok Shop research:** separate paid ads, sponsored content and Shop videos from organic posts
- **Datasets for analysis and AI:** clean, flat rows ready for spreadsheets, BI tools and LLM pipelines

### Limitations

- Browses from the US only (see above).
- A hashtag feed holds a few hundred videos at most; #fyp and similar catch-all tags return none.
- Search returns what TikTok's search shows and ignores date or sort, so recent-only keyword runs can come back short.
- Private videos, deleted videos and anything behind a login are not reachable.
- TikTok changes its site often. If a feed stops answering, the run says so in `OUTPUT` with `blocked: true`, and nothing is charged for it.

### Is it legal to scrape TikTok?

This actor collects only publicly visible video data and never logs in. In *hiQ Labs v. LinkedIn* a US federal appeals court found that accessing publicly available data is unlikely to breach the Computer Fraud and Abuse Act, but platform terms and privacy laws such as GDPR still apply to how you store and use personal data like usernames. Use the data responsibly and get advice for your own situation. This is not legal advice.

### Need something else?

Open an issue on the **Issues** tab with the input that did not work or the field you need. Issues are read and answered.

# Actor input Schema

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

TikTok hashtags to scrape, one per line, with or without the # (for example jewelrytok or #engagementring). A tiktok.com/tag/... link also works. TikTok's hashtag feed is not in date order and usually holds a few hundred videos at most, so use postedWithinDays to keep only recent ones.

## `keywords` (type: `array`):

Search terms, one per line, exactly as you would type them in the TikTok search box (for example lab grown diamond ring). Returns the videos TikTok's video search shows for the term. TikTok's web search ignores its own date and sort options, so the date filter below is applied after fetching.

## `trending` (type: `boolean`):

Also scrape the videos TikTok's Explore page is currently showing (its trending feed) for the category below. Each call is a fresh draw, so repeated runs return different videos.

## `trendingCategory` (type: `string`):

Explore page category used when Trending videos is on.

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

Most videos to return for EACH hashtag, keyword and the trending feed. A shallow hashtag feed can hold fewer; the run summary (OUTPUT) then reports how deep the feed went. You only pay for videos delivered.

## `postedWithinDays` (type: `integer`):

Keep only videos posted in the last N days, based on each video's createTime. Older videos are skipped and never charged. Leave empty for no date filter.

## `region` (type: `string`):

Country TikTok is browsed from. Only the United States is available: tested on 26 Sep 2026, TikTok refuses its web video feeds to logged out visitors from the UK, EU, Canada, Australia, Brazil, Japan and Mexico, and TikTok is not available in India. Videos from creators anywhere still appear in US hashtag, search and trending feeds.

## `downloadVideos` (type: `boolean`):

Save each video's MP4 to this run's key-value store and put a public link to it in videoFileUrl. TikTok's own videoUrl only plays with TikTok session cookies, so this is the way to get a file you can open anywhere. Charged per file actually saved; a failed download is not charged. Slideshow (photo) posts have no MP4 and are skipped.

## `includeAuthorMedianPlays` (type: `boolean`):

For each unique author, read their most recent posts and add authorMedianPlays (the median play count of those posts) and playsVsAuthorMedian (this video's plays divided by that median). A value of 3 means the video did three times the author's usual. Fetched once per author per run.

## Actor input object example

```json
{
  "hashtags": [
    "jewelrytok"
  ],
  "trending": false,
  "trendingCategory": "120",
  "maxItems": 10,
  "region": "US",
  "downloadVideos": false,
  "includeAuthorMedianPlays": false
}
```

# 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 = {
    "hashtags": [
        "jewelrytok"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/tiktok-hashtag-search-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": ["jewelrytok"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/tiktok-hashtag-search-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": [
    "jewelrytok"
  ],
  "maxItems": 10
}' |
apify call themineworks/tiktok-hashtag-search-scraper --silent --output-dataset

```

## MCP server setup

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