# TikTok Creative Center Top Ads Scraper (`steadyscrape/tiktok-creative-center-scraper`) Actor

TikTok's own top-performing ads from Creative Center by country, keyword, industry and objective: ad copy, brand, CTR rank, likes, budget tier, MP4 links, plus each ad's landing page, comments, shares, markets and AI analysis. No login.

- **URL**: https://apify.com/steadyscrape/tiktok-creative-center-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Social media, Marketing, Videos
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 ads

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 Creative Center Top Ads Scraper

Get the ads **TikTok itself ranks as top performers** in [Creative Center's Top Ads](https://ads.tiktok.com/business/creativecenter/inspiration/topads/pc/en): the ad copy, the brand, TikTok's CTR rank, likes, budget tier, campaign objective, industry and direct MP4 links. You can search by country, keyword, industry, objective, language and Spark / non-Spark format. Turn on details and each ad also brings its **landing page**, comments, shares, every market it ran in, and the AI analysis Creative Center writes about its hook and structure.

No TikTok account, no login, no cookies, no browser. You pay per ad delivered, from US$0.001, with no start fee.

### What you can do with it

- **TikTok ad spy**: see which creatives win in your vertical and market, and which offers and landing pages competitors send traffic to.
- **Swipe files** for media buyers and creative strategists: hooks, ad copy and downloadable videos, sorted by CTR, reach or likes.
- **Creative research by industry**: TikTok's own industry tree (258 industries, from *Skincare* to *Mobile Games*), its objectives (conversions, app installs, lead generation…) and 28 markets.
- **Monitoring**: schedule it with *Only ads new since the last run* and get only the ads that entered the ranking since your last run.

### How it works

Every combination of **country × keyword × industry** is one search, and TikTok ranks up to **400 ads** for each search. The Actor reads TikTok's ranking page by page, in TikTok's order, up to your maximum. An ad that turns up in two searches of the same run is delivered and charged **once**.

A search that finds nothing, an industry name TikTok does not have (the row suggests similar names), or a refused request comes back as **one free row that says why**. You never pay for it.

### Input example

```json
{
    "countries": ["US", "GB"],
    "period": "30",
    "keywords": ["skincare", "protein powder"],
    "industries": [],
    "objectives": ["conversions", "product_sales"],
    "sortBy": "ctr",
    "maxAdsPerSearch": 100,
    "includeDetails": true
}
```

That is 4 searches (2 countries × 2 keywords): at most 400 ads, each with its own page.

| field | what it does |
|---|---|
| `countries` | ISO codes of the 28 markets Creative Center covers (US, GB, DE, FR, JP, BR, MX, CA, AU…). Leave it empty for one search across all markets together. |
| `period` | `7`, `30` or `180` days. 180 gives the most ads. |
| `keywords` | Product, brand or theme words. Each one is a separate search. |
| `industries` | TikTok industry names (`Apparel & Accessories`, `Skincare`, `Games`, `Women's Clothing`…, any case, "and" works for "&") or their numeric ids. Each one is a separate search. |
| `objectives` | `traffic`, `app_installs`, `conversions`, `video_views`, `reach`, `lead_generation`, `product_sales`, `app_promotion`. |
| `sortBy` | `for_you` (TikTok's pick), `reach`, `ctr`, `cvr`, `view_rate_2s`, `view_rate_6s`, `likes`. |
| `adLanguage`, `adFormat` | Optional filters: 16 ad languages; Spark ads (boosted creator posts) or non-Spark. |
| `maxAdsPerSearch` | 1–400, in TikTok's order. |
| `includeDetails` | Adds each ad's page: landing page, comments, shares, markets, objectives, Creative Center's highlight and AI analysis. |
| `onlyNewAds` | Monitor mode: skips, for free, every ad an earlier monitor run of yours already delivered. |

### Output example

One row per ad (links shortened here):

```json
{
    "status": "ok",
    "adId": "7532523651482353682",
    "title": "WINNER of 'Best Barrier Protector' 2025! Dr Sam Bunting's science-led moisturizer is a game-changer.",
    "brandName": "Dr Sam's Skincare",
    "industry": "Skincare",
    "industryId": 14103000000,
    "industryCategory": "Beauty & Personal Care",
    "objective": "Product sales",
    "likes": 155,
    "ctrTopPercent": 18,
    "budget": "high",
    "isSearchAd": false,
    "badge": null,
    "videoId": "v10033g50000d5bovevog65rm335r040",
    "videoUrl": "https://v16m-default.tiktokcdn.com/…/video/tos/useast2a/…",
    "videoUrls": { "360p": "https://…", "480p": "https://…", "540p": "https://…", "720p": "https://…" },
    "coverUrl": "https://p16-common-sign.tiktokcdn.com/…",
    "durationSeconds": 43.468,
    "width": 720,
    "height": 1280,
    "url": "https://ads.tiktok.com/business/creativecenter/topads/7532523651482353682/pc/en?period=180&countryCode=US",
    "details": {
        "comments": 2,
        "shares": 0,
        "landingPage": "https://us.drsambunting.com/pages/lp-flawless-moisturiser-intense/…",
        "countries": ["GB", "US"],
        "highlight": null,
        "keywords": [],
        "hasVoiceOver": false,
        "objectives": ["Product sales", "Conversions"],
        "source": "TikTok Ads Manager",
        "analysis": null
    },
    "rank": 2,
    "search": { "country": "US", "period": 180, "keyword": "skincare", "industry": null, "objectives": [], "sortBy": "for_you", "adLanguage": null, "adFormat": null },
    "scrapedAt": "2026-10-13T15:33:36.312Z"
}
```

### Fields

| field | meaning |
|---|---|
| `status` | `ok` for an ad. The free rows are `no_ads` (the search has no ads), `invalid` (TikTok does not have that industry, or refused the search) and `blocked` (TikTok did not answer after retries). `reason` says why. |
| `title`, `brandName` | The ad copy (the hook) and the advertiser's name; `null` when TikTok shows none. |
| `industry`, `industryId`, `industryCategory` | TikTok's industry, its id, and the top-level industry it belongs to. |
| `objective` | The campaign objective, e.g. *Conversions*, *App installs*. |
| `likes` | The ad's likes. |
| `ctrTopPercent` | TikTok's CTR rank: the ad is in the top N % of comparable ads, so **lower is better**. TikTok's UI shows it as "Top 18%". |
| `budget` | TikTok's spend tier: `low`, `medium` or `high`. |
| `badge` | TikTok's label, when it gives one: *Expert's choice*, *High engagement* or *Most favored*. |
| `isSearchAd` | Whether the ad also runs in TikTok search. |
| `videoUrl`, `videoUrls`, `coverUrl` | The MP4 at the best resolution offered, every resolution, and the cover image. **They are signed links that expire within hours**: download them during or right after the run. |
| `durationSeconds`, `width`, `height` | The video's length and size. |
| `url` | The ad's page in Creative Center. |
| `details` | Only with `includeDetails`: `comments`, `shares`, `landingPage`, `countries` (every market the ad ran in), `highlight` (Creative Center's note on why it works), `keywords`, `hasVoiceOver`, `objectives`, `source`, and `analysis` (Creative Center's AI analysis, for the ads it wrote one for). |
| `rank` | The ad's position in TikTok's ranking for that search. |
| `search` | The search that found the ad, so you can tell the rows of several searches apart. |

### Pricing

Pay per event, with no start fee and no charge for platform usage on top:

| event | price |
|---|---|
| `ad`: one ad from the list | US$0.001 |
| `ad-with-details`: one ad with its page | US$0.003 |

Free rows (`no_ads`, `invalid`, `blocked`), duplicates within a run and ads a monitor already delivered cost nothing. If TikTok does not answer an ad's page, the ad is still delivered and charged as a plain `ad`. The run stops cleanly at your spending limit.

### Limits

- **400 ads per search** is TikTok's ceiling, logged in or not. To get more, add countries, keywords or industries. In practice a page sometimes comes a few ads short, so a full search gives about 380–390 ads.
- **"For You" is TikTok's personalised order.** The Actor keeps one visitor for a whole search, so the order holds from page to page, but two runs can rank the same ads differently. For a stable order, sort by CTR, reach or likes.
- **Trending hashtags, songs and creators** are no longer public in Creative Center: logged out, TikTok shows only the top 3 hashtags and the top 4 videos. This Actor does Top Ads, which are still fully public.
- Ads are the ones advertisers allowed TikTok to show, as Creative Center itself states. They are not every ad running on TikTok.

### Is it legal?

The Actor reads only what Creative Center shows any visitor without logging in: ads TikTok publishes as public inspiration for advertisers. It collects no personal data about TikTok users. You are responsible for how you use the creatives, which belong to their advertisers. Use them for research and inspiration, not to republish them as your own.

### Questions and issues

Open an issue on the Actor's Issues tab. Every issue is answered.

# Actor input Schema

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

The markets whose top ads you want; each country is its own search of up to 400 ads. Leave the list empty for one search across all markets together.

## `period` (type: `string`):

Ads that ran in the last 7, 30 or 180 days. 180 days gives the most ads (TikTok shows at most 400 per search).

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

Search the ads by product, brand or theme (<code>skincare</code>, <code>running shoes</code>, <code>temu</code>). Each keyword is its own search. Leave empty for the overall ranking.

## `industries` (type: `array`):

TikTok's industry names, as in Creative Center: <code>Apparel & Accessories</code>, <code>Beauty & Personal Care</code>, <code>Games</code>, <code>Women's Clothing</code>, <code>Skincare</code>… (any case; "and" works for "&"), or their numeric ids. Each industry is its own search. An unknown name comes back as a free row with similar names.

## `objectives` (type: `array`):

Keep only ads bought for these objectives. Empty for all.

## `sortBy` (type: `string`):

The order TikTok ranks the ads in. With a maximum below 400, it decides which ads you get.

## `adLanguage` (type: `string`):

Keep only ads in this language.

## `adFormat` (type: `string`):

Spark ads are creators' own posts boosted as ads; non-Spark ads are uploaded by the advertiser.

## `maxAdsPerSearch` (type: `integer`):

In TikTok's order. TikTok ranks at most 400 ads for one search; to get more, add countries, keywords or industries.

## `includeDetails` (type: `boolean`):

Opens each ad's page in Creative Center: the landing page URL, comments and shares, every country the ad ran in, the campaign objectives, Creative Center's note on why the ad works and, for the ads it has one, its AI analysis of the hook and structure. Charged as <code>ad-with-details</code> instead of <code>ad</code>.

## `onlyNewAds` (type: `boolean`):

Turns a scheduled run into a monitor: ads an earlier monitor run of yours already delivered are skipped for free, so each run delivers only the ads that entered the ranking since.

## Actor input object example

```json
{
  "countries": [
    "US"
  ],
  "period": "30",
  "keywords": [],
  "sortBy": "for_you",
  "adLanguage": "any",
  "adFormat": "any",
  "maxAdsPerSearch": 10,
  "includeDetails": false,
  "onlyNewAds": false
}
```

# Actor output Schema

## `ads` (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 = {
    "countries": [
        "US"
    ],
    "keywords": [],
    "maxAdsPerSearch": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/tiktok-creative-center-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 = {
    "countries": ["US"],
    "keywords": [],
    "maxAdsPerSearch": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/tiktok-creative-center-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 '{
  "countries": [
    "US"
  ],
  "keywords": [],
  "maxAdsPerSearch": 10
}' |
apify call steadyscrape/tiktok-creative-center-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/tiktok-creative-center-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/dgtL4l5hrzdeBlLae/builds/qjQOsK6ewnVB3ayTz/openapi.json
