# TikTok Creator Search Insights (`cunning_soil/tiktok-creator-search-insights`) Actor

Scrape TikTok Creator Search Insights feeds, keyword search, and direct query-ID lookups. Enrich topics with popularity charts, demographics, related topics and videos, and AI video outlines. Returns one structured dataset row per topic.

- **URL**: https://apify.com/cunning\_soil/tiktok-creator-search-insights.md
- **Developed by:** [Rizla Piker](https://apify.com/cunning_soil) (community)
- **Categories:** SEO tools, Social media, Videos
- **Stats:** 15 total users, 12 monthly users, 98.9% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $10.00 / 1,000 api requests

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/platform/actors/running/actors-in-store#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

### What does TikTok Creator Search Insights do?

This Actor scrapes **TikTok Creator Search Insights** — the in-app tool TikTok gives creators to find trending topics, content gaps, audience demographics, and AI-generated video outlines.

It covers **all 16 home tabs**, keyword search, and direct topic lookup by query ID. Every result is returned as a flat dataset row you can download as JSON, CSV, or Excel.

***

### Why use it?

- **Full coverage** — Suggested, Trending, Fashion, Featured, Food, Sports, Hobbies, Science & Tech, Dance, Travel, Home & Living, Education, Careers, Vehicles, Local life, Photo posts, plus keyword search.
- **Topic detail enrichment** — popularity charts, audience demographics (gender/age/country), related topics, AI video outlines (titles, hashtags, scripts), and related videos.
- **Direct query-ID lookup** — re-fetch any topic's full detail page without re-scraping feeds.
- **Production-ready** — automatic retries with backoff, device rotation on session blocks, and clean failure messages.

***

### What data can you extract?

| Data point | Dataset column |
|---|---|
| Topic title | `queryText` |
| Search volume (159K, 300) | `searchVolumeLabel`, `popularityScore` |
| Card subtitle | `cardSubtitle` |
| Post count (93.8K+ posts) | `videoCountLabel`, `videoCount` |
| Trend spike (1000%+) | `trendGrowthPercent` |
| 7-day volume sparkline | `trendingVolume7d` |
| Content gap flag | `isContentGap` |
| Category tree | `categoryL1` – `categoryL4` |
| Popularity chart (7/30/60 day) | `popularityChart` |
| Audience demographics | `demographics` |
| Related topics | `relatedTopics` |
| AI outline — insights, titles, hashtags, script | `outlineInsights`, `outlineTitles`, `outlineHashtags`, `outlineScript` |
| Related videos | `relatedVideos` |

***

### How to scrape TikTok Creator Search Insights

1. Pick **What to scrape** (one complete destination, e.g. Suggested → Content gap).
2. If you chose **Search by keyword**, type the keyword. For anything else, leftover keyword text is ignored.
3. Leave **How many results** at 20 for a cheap first run.
4. Click **Start**. Download the dataset when it finishes.

That’s it. Extra filters, query-ID lookup, and enrichment options stay collapsed.

| You pick | You also fill | Result |
|---|---|---|
| Suggested → Content gap (or any home tab) | Nothing else | That feed |
| Search by keyword | Search keyword (e.g. `iphone`) | Keyword search |
| Lookup by query ID | Query IDs | Those topics only |

***

### Input reference

| Field | Description | Default |
|---|---|---|
| `feedChannel` | Destination: `suggested_content_gap`, `search`, `trending_topics`, `education`, … | `suggested` |
| `feedTab` | Legacy sub-tab (hidden in Console; used with `suggested` / `trending`) | `all` |
| `searchKeyword` | Used only when `feedChannel` is `search` | — |
| `queryIds` | Direct topic lookup by ID | — |
| `categories` | Optional filter: Fashion, Food, Gaming, Tourism, Science, Sports | — |
| `language` | Content language | `en` |
| `location` | Trending location: `local`, `global`, or country code | — |
| `timeWindow` | Hot trends / Events window: `4H`, `24H`, `48H`, `7D` | — |
| `maxPages` | Pages to fetch | `10` |
| `resultsPerPage` | Items per page (max 20) | `20` |
| `maxItems` | Total result cap (0 = unlimited) | `0` |
| `delaySeconds` | Pause between pages | `0.5` |
| `includeTopicDetail` | Enrich with charts, demographics, AI outline | `true` |
| `detailDateRange` | Chart window: `7day`, `30day`, `60day`, `6month` | `7day` |
| `detailCountryCodes` | Countries for popularity chart | `["US"]` |
| `relatedTopicsLimit` | Max related topics per item | `10` |
| `detailDelaySeconds` | Pause between detail API calls | `0.3` |

#### Section mapping (feedChannel)

| TikTok app tab | `feedChannel` | Sub-tab needed? |
|---|---|---|
| Suggested | `suggested` | Yes — `feedTab`: `all` or `content_gap` |
| Trending | `trending` | Yes — `feedTab`: `topics`, `sounds`, `hashtags`, etc. |
| Fashion | `fashion` | No |
| Featured | `featured` | No |
| Food | `food` | No |
| Sports | `sports` | No |
| Hobbies | `hobbies` | No |
| Science & Tech | `science` | No |
| Dance | `dance` | No |
| Travel | `travel` | No |
| Home & Living | `home_living` | No |
| Education | `education` | No |
| Careers | `careers` | No |
| Vehicles | `vehicles` | No |
| Local life | `local_life` | No |
| Photo posts | `photo_posts` | No |

For keyword search, set `feedChannel` to `search` and provide `searchKeyword`. Combined values such as `suggested_content_gap` replace the old Section + Filter pair.

***

### Sample output

Topic details are on by default, so a typical row looks like this (Suggested → Content gap):

```json
{
  "type": "topic",
  "feedChannel": "suggested",
  "feedTab": "content_gap",
  "sectionLabel": "Suggested → Content gap",
  "queryId": "7623251614337368120",
  "queryText": "GamingContent",
  "primaryType": "search",
  "popularity": 74,
  "popularityScore": 272281,
  "searchVolumeLabel": "272.3K",
  "videoCount": 31479,
  "videoCountLabel": "31.5K+ posts",
  "isContentGap": true,
  "trendGrowthPercent": 118.8,
  "categoryL1": "ACGN",
  "categoryL2": "Games",
  "topicDetailEnriched": true,
  "detailDateRange": "7day",
  "detailCreatorPostCount": 31479,
  "popularityChart": {
    "US": [
      {"date": "2026-08-11", "popularity": 38924},
      {"date": "2026-08-18", "popularity": 28878}
    ],
    "global": [
      {"date": "2026-08-11", "popularity": 254504},
      {"date": "2026-08-18", "popularity": 272280}
    ]
  },
  "demographics": {
    "gender": [
      {"category": "male", "popularity": 12903},
      {"category": "female", "popularity": 6301}
    ],
    "age": [
      {"category": "18-24", "popularity": 12003},
      {"category": "25-34", "popularity": 8102}
    ]
  },
  "relatedTopics": [
    {"queryId": "7525795980659130373", "queryText": "GamerTikTok", "popularityScore": 104768, "searchVolumeLabel": "104.8K"},
    {"queryId": "7600837050664747029", "queryText": "GameContent", "popularityScore": 3800, "searchVolumeLabel": "3.8K"}
  ],
  "outlineInsights": "Quirky Roblox/VR mini-stories with AI actor comedy go viral because they’re fast, funny, and instantly replayable.",
  "outlineHook": "Your game skit turns into instant laughs!",
  "outlineTitles": ["Roblox VR Comedy Remix", "AI Actor Game Skit Challenge", "Newbie Hacker Fails, But Funny"],
  "outlineHashtags": ["gamingcontent", "tiktokgaming", "robloxvr"],
  "outlineScript": [
    {"key": "intro", "section": "Intro", "instruction": "Open with a funny game twist.", "script": "Stop scrolling—your VR game can be pure chaos in 15 seconds!"}
  ]
}
```

**Search by keyword** (`iphone`):

```json
{
  "type": "topic",
  "feedChannel": "search",
  "sectionLabel": "Search",
  "searchKeyword": "iphone",
  "queryId": "101670035",
  "queryText": "iPhone Phones",
  "primaryType": "search",
  "popularity": 72,
  "popularityScore": 189505,
  "searchVolumeLabel": "189.5K",
  "videoCount": 76838,
  "videoCountLabel": "76.8K+ posts",
  "isContentGap": false,
  "trendGrowthPercent": 309.5,
  "categoryL1": "Science and Technology",
  "categoryL2": "Digital",
  "topicDetailEnriched": true,
  "detailDateRange": "7day",
  "detailCreatorPostCount": 76838,
  "popularityChart": {
    "US": [
      {"date": "2026-08-11", "popularity": 1368},
      {"date": "2026-08-18", "popularity": 13759}
    ],
    "global": [
      {"date": "2026-08-11", "popularity": 165310},
      {"date": "2026-08-18", "popularity": 189504}
    ]
  },
  "demographics": {
    "gender": [
      {"category": "male", "popularity": 21689},
      {"category": "female", "popularity": 15092}
    ],
    "age": [
      {"category": "25-34", "popularity": 24487},
      {"category": "18-24", "popularity": 20489}
    ]
  },
  "relatedTopics": [
    {"queryId": "7414271978632544262", "queryText": "17 pro iphone", "popularityScore": 480351, "searchVolumeLabel": "480.4K"},
    {"queryId": "7411674612460814342", "queryText": "pro max phones", "popularityScore": 300, "searchVolumeLabel": "300"}
  ],
  "outlineInsights": "Fast phone-unboxing promos with clear feature callouts and urgency cues drive clicks and DMs.",
  "outlineHook": "Brand-new iPhone look in seconds—watch this demo!",
  "outlineTitles": ["iPhone Deals: Spot The Upgrade", "Face ID To True Tone Demo", "Which iPhone Fits Your Budget?"],
  "outlineHashtags": ["iphone", "appledeals", "facid", "trutone"],
  "outlineScript": [
    {"key": "intro", "section": "Intro", "instruction": "Start with a bold iPhone reveal.", "script": "This iPhone upgrade is wild—watch the quick reveal!"}
  ]
}
```

***

### Topic detail enrichment

Turn on **Include topic details** (`includeTopicDetail`, on by default) to match the in-app topic detail screen. Each enriched row adds the fields above. Turn it off for a cheaper list-only scrape.

Sub-toggles let you pick exactly what to fetch:

- `includePopularityChart` — search trend chart
- `includeDemographics` — gender, age, country breakdown
- `includeRelatedTopics` — "Explore more" topics
- `includeRelatedVideos` — videos for the topic keyword
- `includeAiOutline` — AI-generated titles, hashtags, script

**Cost note:** enrichment adds roughly 4–5 requests per topic. Use `maxItems` to control how many topics are enriched per run.

***

### Lookup by query ID

Every list row includes a `queryId`. Use it to re-fetch the full detail page later without scraping feeds again.

Set `queryIds` in the Actor input:

```json
{
  "queryIds": ["7452903671676796934", "7479258928920969222"],
  "detailDateRange": "7day",
  "detailCountryCodes": ["US"]
}
```

Detail enrichment turns on automatically. Optional sub-toggles still apply.

***

### API usage

#### REST API (cURL)

**Scrape Suggested → All topics:**

```bash
curl -X POST "https://api.apify.com/v2/acts/cunning_soil~tiktok-creator-search-insights/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "feedChannel": "suggested",
    "feedTab": "all",
    "maxPages": 2,
    "maxItems": 20
  }'
```

**Retrieve the dataset:**

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&token=YOUR_TOKEN"
```

#### JavaScript (apify-client)

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

const client = new ApifyClient({ token: 'YOUR_TOKEN' });

// Scrape education topics with enrichment
const run = await client.actor('cunning_soil/tiktok-creator-search-insights').call({
    feedChannel: 'education',
    maxPages: 2,
    maxItems: 10,
    includeTopicDetail: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} topics`);
items.forEach(item => {
    console.log(item.queryText, item.searchVolumeLabel, item.outlineTitles);
});
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient(token="YOUR_TOKEN")

## Look up specific topics by query ID
run = client.actor("cunning_soil/tiktok-creator-search-insights").call(run_input={
    "queryIds": ["7452903671676796934"],
    "detailDateRange": "7day",
    "detailCountryCodes": ["US"],
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["queryText"], item.get("popularityChart"))
```

***

### Pricing

This Actor uses **pay-per-event** pricing on the Apify Store. You are billed **per API request** the Actor makes to TikTok — not per result — so bulk list scraping is cheap and you only pay more when you ask for richer data.

| Event | Price | What it covers |
|---|---|---|
| **API request** | $0.01 ($10 / 1,000) | One request to TikTok. A feed page is one request (returns up to 20 results). Each enrichment call (detail, popularity chart, demographics, related topics, AI outline, related videos) is one request. Retries are not billed. |
| **Actor start** | $0.00005 | Charged when a run starts (scales with memory: 1 event per GB, minimum 1). |

**What a request means**

- **List scraping:** 1 request per page = up to 20 results. So ~50 requests ($0.50) returns ~1,000 results.
- **Enrichment:** each enriched topic makes roughly 4–6 requests (~$0.04–$0.06 per topic), depending on which detail toggles are on.

**Example costs**

| Run | Requests | Approx. charge |
|---|---|---|
| 1,000 list results (50 pages) | ~50 | ~$0.50 |
| 100 list results (5 pages) | ~5 | ~$0.05 |
| 20 enriched topics | ~100–120 | ~$1.00–$1.20 |
| 5 query-ID lookups (full enrichment) | ~25–30 | ~$0.25–$0.30 |

Set a **maximum charge** on each run to cap spending. The Actor stops making new requests once that limit is reached, so you are never billed beyond it. For first-time tests, $0.50–$1.00 is plenty.

***

### Tips

- **Start with a small run** — set `maxItems` to 5 and `maxPages` to 1 to preview results before scaling up.
- **Topic details are on by default** — uncheck Include topic details for a cheaper list-only scrape.
- **Choose the right Trending sub-tab** — Trending → Topics returns search queries, while Trending → Sounds returns music.
- **Find content gaps** — set `feedChannel` to `suggested_content_gap`.
- **Reuse query IDs** — save the `queryId` values from a list run and pass them back via `queryIds` to re-fetch full detail later.

***

### Troubleshooting

| Symptom | Cause | What to do |
|---|---|---|
| Empty dataset | That destination had no topics, or the session needs refreshing | Try Suggested → All, or Search by keyword |
| Search ran when I wanted a feed | You selected Search by keyword | Switch What to scrape to a home tab — leftover keyword text is ignored |
| `relatedVideosBlocked: "hit_shark"` in a row | TikTok's anti-bot protection blocked the related-video request | Retry later, or disable `includeRelatedVideos`; other fields are unaffected |
| Run fails with a TikTok API status message | The upstream TikTok session expired or blocked the request | Re-run the Actor; if it persists, the maintainer needs to refresh the session credentials |

***

### Limitations

- **Related videos** rely on TikTok's general video search, which its anti-bot systems may block. When this happens, the row includes `relatedVideosBlocked` and all other fields remain populated.
- **Session lifetime** — the Actor authenticates against TikTok using pre-configured session credentials that are refreshed periodically by the maintainer. Runs may fail if a session expires before it is renewed.

# Actor input Schema

## `feedChannel` (type: `string`):

One complete destination — you do not need to combine a section and a filter.

## `searchKeyword` (type: `string`):

Used only when What to scrape is Search by keyword (e.g. iphone, skincare). Ignored for every other destination — leftover text will not change the run.

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

Stop after this many topics. Prefill is 20 so a first run with details stays predictable. 0 means no cap (uses Max pages instead).

## `includeTopicDetail` (type: `boolean`):

On by default. Adds popularity charts, audience demographics, related topics, related videos, and AI video outlines. About 4–6 extra API requests per topic. Turn off for a cheaper list-only scrape.

## `includePopularityChart` (type: `boolean`):

Search trend chart. Used when topic details are on.

## `includeDemographics` (type: `boolean`):

Gender, age, and country breakdown. Used when topic details are on.

## `includeRelatedTopics` (type: `boolean`):

Explore-more topics. Used when topic details are on.

## `includeRelatedVideos` (type: `boolean`):

May be empty if TikTok anti-bot blocks the request.

## `includeAiOutline` (type: `boolean`):

Titles, hashtags, and script sections. Used when topic details are on.

## `queryIds` (type: `array`):

TikTok query\_id values (e.g. 7452903671676796934).

## `categories` (type: `array`):

Extra filter for Suggested or Trending → Topics.

## `language` (type: `string`):

Language used to filter results.

## `location` (type: `string`):

For Trending tabs: local, global, or a country code (US, GB, …).

## `timeWindow` (type: `string`):

For Trending → Hot trends or Events only.

## `feedTab` (type: `string`):

Legacy API field. New runs should pick a complete destination in What to scrape.

## `maxPages` (type: `integer`):

Maximum feed pages to request.

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

Items requested per page (max 20).

## `delaySeconds` (type: `number`):

Pause between feed page requests.

## `includeViewerInsights` (type: `boolean`):

Optional; often empty.

## `detailDateRange` (type: `string`):

Window for popularity chart and demographics.

## `detailCountryCodes` (type: `array`):

ISO country codes (global is always included).

## `relatedTopicsLimit` (type: `integer`):

Maximum related topics per enriched item.

## `detailDelaySeconds` (type: `number`):

Pause after enriching each topic.

## `requestTimeout` (type: `integer`):

HTTP timeout per API request.

## `maxRetries` (type: `integer`):

Retries for network errors and transient TikTok blocks.

## `retryBackoffSeconds` (type: `number`):

Base delay between retries (multiplied by attempt number).

## Actor input object example

```json
{
  "feedChannel": "suggested_content_gap",
  "searchKeyword": "iphone",
  "maxItems": 20,
  "includeTopicDetail": true,
  "includePopularityChart": true,
  "includeDemographics": true,
  "includeRelatedTopics": true,
  "includeRelatedVideos": true,
  "includeAiOutline": true,
  "language": "en",
  "feedTab": "all",
  "maxPages": 10,
  "resultsPerPage": 20,
  "delaySeconds": 0.5,
  "includeViewerInsights": false,
  "detailDateRange": "7day",
  "detailCountryCodes": [
    "US"
  ],
  "relatedTopicsLimit": 10,
  "detailDelaySeconds": 0.3,
  "requestTimeout": 30,
  "maxRetries": 3,
  "retryBackoffSeconds": 1
}
```

# Actor output Schema

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

Default dataset containing one row per topic, sound, hashtag, effect, or template.

## `runInfo` (type: `string`):

Run mode, selected feed, item count, and elapsed time.

# 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 = {
    "feedChannel": "suggested_content_gap",
    "searchKeyword": "iphone",
    "maxItems": 20,
    "includeTopicDetail": true,
    "includePopularityChart": true,
    "includeDemographics": true,
    "includeRelatedTopics": true,
    "includeRelatedVideos": true,
    "includeAiOutline": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("cunning_soil/tiktok-creator-search-insights").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 = {
    "feedChannel": "suggested_content_gap",
    "searchKeyword": "iphone",
    "maxItems": 20,
    "includeTopicDetail": True,
    "includePopularityChart": True,
    "includeDemographics": True,
    "includeRelatedTopics": True,
    "includeRelatedVideos": True,
    "includeAiOutline": True,
}

# Run the Actor and wait for it to finish
run = client.actor("cunning_soil/tiktok-creator-search-insights").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 '{
  "feedChannel": "suggested_content_gap",
  "searchKeyword": "iphone",
  "maxItems": 20,
  "includeTopicDetail": true,
  "includePopularityChart": true,
  "includeDemographics": true,
  "includeRelatedTopics": true,
  "includeRelatedVideos": true,
  "includeAiOutline": true
}' |
apify call cunning_soil/tiktok-creator-search-insights --silent --output-dataset

```

## MCP server setup

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

```

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/tchLtq3QzXbBoNAbj/builds/okw27A3naRRjbUGzi/openapi.json
