# TikTok Ads Library Scraper — EU Library & Creative Center (`brilliant_gum/tiktok-ads-library-scraper`) Actor

Scrape TikTok Ads Library (EU/EEA/UK) and Creative Center (global). Extract ad creatives, targeting data, reach estimates, CTR, video URLs, and industry insights. Dual-source coverage — no login required. Residential proxies built-in.

- **URL**: https://apify.com/brilliant\_gum/tiktok-ads-library-scraper.md
- **Developed by:** [Yuliia Kulakova](https://apify.com/brilliant_gum) (community)
- **Categories:** Social media
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

<p align="center">
  <img src="https://i.postimg.cc/9XkQ4sKK/tiktok-banner-clean.png" alt="TikTok Ads Library Scraper" width="100%" />
</p>

<p align="center">
  <b>Spy · Analyze · Outperform</b><br/>
  The only TikTok ad scraper that covers <strong>both</strong> the EU Ads Library <em>and</em> the global Creative Center —<br/>
  targeting data, reach estimates, CTR, video URLs, and industry insights. All in one run.
</p>

<p align="center">
  <a href="#-what-makes-this-different">Why this one?</a> ·
  <a href="#-data-sources-explained">Data sources</a> ·
  <a href="#-input">Input</a> ·
  <a href="#-output-schema">Output</a> ·
  <a href="#-use-cases">Use cases</a> ·
  <a href="#-pricing">Pricing</a> ·
  <a href="#-limitations">Limitations</a>
</p>

---

**TikTok Ads Library Scraper** pulls ad data from two complementary TikTok sources:

- **[TikTok Ads Library](https://library.tiktok.com/)** — TikTok's official DSA transparency database for EU/EEA/UK. No login required. Returns targeting details, audience reach, and ad creatives for all ads shown in Europe.
- **[TikTok Creative Center](https://ads.tiktok.com/business/creativecenter/)** — TikTok's global top-performing ads showcase. Covers US, APAC, LATAM, and every other market. Returns CTR, engagement metrics, video URLs, and industry data.

Both sources are public and require no TikTok account.

---

### ✨ What makes this different

| Feature | This actor | Most others |
|---|---|---|
| Covers **both** Ads Library + Creative Center | ✅ dual-source | ❌ one source only |
| Global coverage via Creative Center (US, APAC, LATAM…) | ✅ | ❌ EU-only |
| EU DSA reach estimates (`uniqueUsersSeen`, `usersTargetedEstimate`) | ✅ | ❌ |
| CTR and engagement metrics (Creative Center) | ✅ | ❌ |
| Video CDN URLs + thumbnail | ✅ | Partial |
| Industry + campaign objective (Creative Center) | ✅ | ❌ |
| Budget tier (LOW / MEDIUM / HIGH) | ✅ | ❌ |
| Graceful handling of rate limits (429/403 logging) | ✅ | Silent failures |
| Warns when 3,600-result cap is reached | ✅ | No warning |
| Zero-result detection — no wasted compute | ✅ | ❌ |
| Residential proxies built-in (required for TikTok) | ✅ | ❌ |

---

### 📡 Data sources explained

#### Source 1 — TikTok Ads Library (`library`)

| Property | Detail |
|---|---|
| URL | https://library.tiktok.com/ |
| Login required | ❌ No |
| Coverage | EU-27 + EEA (IS, LI, NO) + Switzerland + UK |
| Why EU only? | Mandated by EU Digital Services Act (DSA), Article 39 |
| Result cap | **3,600 ads per query** (TikTok platform limit — 300 pages × 12 ads) |
| Unique fields | `targetAgeGroups`, `targetGender`, `targetInterests`, `targetBehaviors`, `uniqueUsersSeen`, `uniqueUsersSeenByCountry`, `adPaidForBy`, `rejectedInCountries` |

**Use this source when:** you want DSA transparency data — who targeted whom, with what message, reaching how many people in Europe.

---

#### Source 2 — TikTok Creative Center (`creative_center`)

| Property | Detail |
|---|---|
| URL | https://ads.tiktok.com/business/creativecenter/ |
| Login required | ❌ No |
| Coverage | **Global** — US, GB, AU, BR, JP, KR, IN, and 50+ more |
| Data type | Top-performing ads (sorted by CTR and engagement) |
| Unique fields | `ctr`, `likes`, `industry`, `campaignObjective`, `budgetRange`, `videoMetrics` |

**Use this source when:** you want global competitive intelligence — what's performing best in your category, market, or country right now.

---

#### Source 3 — Both (`both`)

Runs both sources in a single actor run. Results are deduplicated automatically. Each result includes a `source` field so you always know where the data came from.

---

### ⚙️ Input

| Field | Type | Default | Description |
|---|---|---|---|
| `source` | string | `"library"` | `library` · `creative_center` · `both` |
| `searchTerms` | string[] | `["Nike"]` | Keywords or brand names (library source only) |
| `countries` | string[] | `["DE"]` | ISO 2-letter codes. Library: EU/EEA/UK only. Creative Center: any country. |
| `adType` | string | `"ALL"` | `ALL` · `VIDEO` · `IMAGE` |
| `dateFrom` | string | — | Show ads first seen on/after this date (`YYYY-MM-DD`). Library only. |
| `dateTo` | string | — | Show ads first seen on/before this date (`YYYY-MM-DD`). Library only. |
| `maxResults` | integer | `50` | Max ads per search term + country pair. Hard cap: 3,600 (library). |
| `resolveAdDetails` | boolean | `false` | **Library only.** Fetch each ad's detail page to unlock: `adPaidForBy`, `advertiserBusinessId`, `targetAgeGroups`, `targetGender`, `targetInterests`, `targetCountries`, `targetBehaviors`. Adds ~3 sec per ad. |

> **Note on countries:** For `source: "library"`, only European countries work (see [supported list](#supported-library-countries)). For `source: "creative_center"`, any country code works including `US`, `GB`, `AU`, `BR`, `JP`.

---

#### Example inputs

**Quick test — Nike EU ads (library)**

```json
{
  "source": "library",
  "searchTerms": ["Nike"],
  "countries": ["DE"],
  "adType": "ALL",
  "maxResults": 25
}
````

**Multi-country competitor research — 3 brands × 3 EU markets**

```json
{
  "source": "library",
  "searchTerms": ["Adidas", "Nike", "Puma"],
  "countries": ["DE", "FR", "NL"],
  "adType": "ALL",
  "maxResults": 100
}
```

**Global top video ads — US market (Creative Center)**

```json
{
  "source": "creative_center",
  "countries": ["US"],
  "adType": "VIDEO",
  "maxResults": 50
}
```

**Combined — EU library + global Creative Center**

```json
{
  "source": "both",
  "searchTerms": ["Samsung"],
  "countries": ["DE", "US"],
  "adType": "ALL",
  "maxResults": 50
}
```

**Date range — campaign window analysis**

```json
{
  "source": "library",
  "searchTerms": ["Zalando"],
  "countries": ["DE"],
  "dateFrom": "2025-01-01",
  "dateTo": "2025-03-31",
  "maxResults": 200
}
```

**E-commerce swipe file — top image ads in UK**

```json
{
  "source": "creative_center",
  "countries": ["GB"],
  "adType": "IMAGE",
  "maxResults": 100
}
```

***

#### Supported library countries

The Ads Library source works only for EU/EEA/Switzerland/UK countries. Unsupported countries are automatically skipped with a warning — the actor does not crash.

```
EU-27:  AT BE BG CY CZ DE DK EE ES FI FR GR HR HU IE IT LT LU LV MT NL PL PT RO SE SI SK
EEA:    IS LI NO
Other:  CH (Switzerland)  GB (United Kingdom)
```

For any other country (US, AU, BR, JP…) use `source: "creative_center"`.

***

### 📦 Output schema

Each item in the dataset represents **one ad**. The `source` field tells you whether it came from the Ads Library or Creative Center.

```json
{
  "adId": "7318291038472910337",
  "source": "library",
  "advertiserName": "Zalando SE",
  "advertiserBusinessId": null,
  "adPaidForBy": null,
  "adText": null,
  "videoUrl": "https://v19-webapp.tiktok.com/video/tos/.../.mp4",
  "thumbnailUrl": "https://p19-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/.../cover.jpg",
  "imageUrls": [],
  "firstShownDate": "2025-02-10",
  "lastShownDate": "2025-03-28",
  "adStatus": "INACTIVE",
  "daysRunning": 46,
  "uniqueUsersSeen": null,
  "uniqueUsersSeenByCountry": [],
  "targetCountries": [],
  "targetAgeGroups": [],
  "targetGender": null,
  "targetInterests": [],
  "targetAudienceType": null,
  "targetBehaviors": null,
  "usersTargetedEstimate": null,
  "rejectedInCountries": [],
  "industry": null,
  "campaignObjective": null,
  "budgetRange": null,
  "ctr": null,
  "likes": null,
  "videoMetrics": null,
  "scrapedAt": "2025-04-04T14:23:11.000Z"
}
```

> **Library (default — `resolveAdDetails: false`):** Returns advertiser name, video/image creatives, ad dates, and run status. Reach estimates and targeting data require `resolveAdDetails: true`.

**Library example with `resolveAdDetails: true`** (full targeting data unlocked):

```json
{
  "adId": "7318291038472910337",
  "source": "library",
  "advertiserName": "Zalando SE",
  "advertiserBusinessId": "7123456789012345",
  "adPaidForBy": "Zalando SE",
  "adText": null,
  "videoUrl": "https://v19-webapp.tiktok.com/video/tos/.../.mp4",
  "thumbnailUrl": "https://p19-sign.tiktokcdn-us.com/tos-useast5-p-0068-tx/.../cover.jpg",
  "imageUrls": [],
  "firstShownDate": "2025-02-10",
  "lastShownDate": "2025-03-28",
  "adStatus": "INACTIVE",
  "daysRunning": 46,
  "uniqueUsersSeen": { "range": "10M-20M" },
  "uniqueUsersSeenByCountry": [
    { "country": "DE", "impressions": "8.4M" },
    { "country": "AT", "impressions": "1.2M" }
  ],
  "targetCountries": ["DE", "AT", "CH"],
  "targetAgeGroups": ["18-24", "25-34", "35-44"],
  "targetGender": "Female",
  "targetInterests": ["Fashion & Accessories", "Shopping"],
  "targetAudienceType": null,
  "targetBehaviors": { "videoInteractions": true, "creatorInteractions": false },
  "usersTargetedEstimate": "8.5M-10.4M",
  "rejectedInCountries": [],
  "industry": null,
  "campaignObjective": null,
  "budgetRange": null,
  "ctr": null,
  "likes": null,
  "videoMetrics": null,
  "scrapedAt": "2025-04-04T14:23:11.000Z"
}
```

> **Note:** `adText` is always null for Library source — TikTok does not expose ad copy through any public Library API endpoint.

**Creative Center example:**

```json
{
  "adId": "7401234567890123456",
  "source": "creative_center",
  "advertiserName": "GlowLab Skincare",
  "advertiserBusinessId": null,
  "adPaidForBy": null,
  "adText": "We tested 100 skincare products. This one actually works.",
  "videoUrl": "https://v19-webapp.tiktok.com/video/tos/.../video.mp4",
  "thumbnailUrl": "https://p16-sign-va.tiktokcdn.com/tos/.../cover.jpg",
  "imageUrls": [],
  "firstShownDate": null,
  "lastShownDate": null,
  "daysRunning": null,
  "adStatus": "ACTIVE",
  "uniqueUsersSeen": null,
  "uniqueUsersSeenByCountry": [],
  "targetCountries": ["US"],
  "targetAgeGroups": [],
  "targetGender": null,
  "targetInterests": [],
  "targetAudienceType": null,
  "targetBehaviors": null,
  "usersTargetedEstimate": null,
  "rejectedInCountries": [],
  "industry": "Beauty & Personal Care",
  "campaignObjective": "TRAFFIC",
  "budgetRange": "HIGH",
  "ctr": 3.24,
  "likes": 18400,
  "videoMetrics": {
    "duration": 28.5,
    "width": 1080,
    "height": 1920
  },
  "scrapedAt": "2025-04-04T14:23:45.000Z"
}
```

> **Creative Center:** Returns ad title, video creative, performance metrics (CTR, likes), industry, campaign objective, and budget tier. Dates, reach figures, and targeting details are not available from TikTok's Creative Center API.

***

#### Field reference

| Field | Source | Type | Notes |
|---|---|---|---|
| `adId` | both | string | Unique TikTok ad ID |
| `source` | both | string | `library` or `creative_center` |
| `advertiserName` | both | string | Brand running the ad |
| `advertiserBusinessId` | library\* | string|null | Requires `resolveAdDetails: true`. TikTok business platform ID |
| `adPaidForBy` | library\* | string|null | Requires `resolveAdDetails: true`. DSA transparency: who paid for the ad |
| `adText` | creative\_center | string|null | Ad title/copy. Null for library source |
| `videoUrl` | both | string|null | Direct CDN video URL (.mp4) |
| `thumbnailUrl` | both | string|null | Cover image URL |
| `imageUrls` | both | string\[] | Static image creative URLs. Populated for IMAGE ads |
| `firstShownDate` | library | string|null | First impression date (YYYY-MM-DD). Null for CC |
| `lastShownDate` | library | string|null | Most recent impression date. Null for CC |
| `daysRunning` | library | integer|null | Days since first shown. Null for CC |
| `adStatus` | both | string | `ACTIVE` or `INACTIVE` (CC always returns `ACTIVE`) |
| `uniqueUsersSeen` | library\* | object|null | `{range: "10M-20M"}` impression estimate. Requires `resolveAdDetails: true`. Null for CC |
| `uniqueUsersSeenByCountry` | library\* | object\[] | Per-country breakdown `[{country, impressions}]`. Requires `resolveAdDetails: true`. Empty array otherwise |
| `targetCountries` | library\* / CC | string\[] | Library: requires `resolveAdDetails: true`. CC: always populated |
| `targetAgeGroups` | library\* | string\[] | Requires `resolveAdDetails: true`. Age brackets: `18-24`, `25-34`, etc. |
| `targetGender` | library\* | string|null | Requires `resolveAdDetails: true`. `Male`, `Female`, or `All` |
| `targetInterests` | library\* | string\[] | Requires `resolveAdDetails: true`. Interest categories |
| `targetAudienceType` | library\* | string|null | Requires `resolveAdDetails: true` |
| `targetBehaviors` | library\* | object|null | Requires `resolveAdDetails: true`. `{videoInteractions, creatorInteractions}` |
| `usersTargetedEstimate` | library | integer|null | Estimated targeted audience size. Null for CC |
| `rejectedInCountries` | library | string\[] | Countries where ad was rejected. Empty for CC |
| `industry` | creative\_center | string|null | Advertiser industry category. Null for library |
| `campaignObjective` | creative\_center | string|null | TRAFFIC, CONVERSIONS, REACH, etc. Null for library |
| `budgetRange` | creative\_center | string|null | LOW / MEDIUM / HIGH. Null for library |
| `ctr` | creative\_center | float|null | Click-through rate. Null for library |
| `likes` | creative\_center | integer|null | Video like count. Null for library |
| `videoMetrics` | creative\_center | object|null | `{duration, width, height}`. Null for library |
| `scrapedAt` | both | string | ISO 8601 scrape timestamp |

***

#### Field availability by source

| Field | `library` | `creative_center` | Notes |
|---|---|---|---|
| `advertiserName` | ✅ | ✅ | |
| `adText` | ❌ | ✅ | Not returned by TikTok Library search API |
| `videoUrl` / `thumbnailUrl` | ✅ | ✅ | |
| `imageUrls` | ✅ | ✅ | Populated for IMAGE ads |
| `firstShownDate` / `lastShownDate` | ✅ | ❌ | Library only |
| `daysRunning` | ✅ | ❌ | Computed from dates |
| `adStatus` | ✅ | ✅ (always ACTIVE) | |
| `uniqueUsersSeen` | ✅\* | ❌ | Requires `resolveAdDetails: true`. Returns `{range: "10M-20M"}` |
| `uniqueUsersSeenByCountry` | ✅\* | ❌ | Requires `resolveAdDetails: true`. Per-country impressions |
| `usersTargetedEstimate` | ✅\* | ❌ | Requires `resolveAdDetails: true`. Targeted audience size range |
| `targetAgeGroups` / `targetGender` | ✅\* | ❌ | Library: enable `resolveAdDetails: true` |
| `targetInterests` / `targetBehaviors` | ✅\* | ❌ | Library: enable `resolveAdDetails: true` |
| `targetCountries` | ✅\* | ✅ | Library: enable `resolveAdDetails: true` |
| `advertiserBusinessId` / `adPaidForBy` | ✅\* | ❌ | Library: enable `resolveAdDetails: true` |
| `rejectedInCountries` | ✅ | ❌ | DSA compliance data |
| `industry` / `campaignObjective` | ❌ | ✅ | CC-only metrics |
| `budgetRange` | ❌ | ✅ | LOW / MEDIUM / HIGH tier |
| `ctr` / `likes` | ❌ | ✅ | Performance metrics from CC |
| `videoMetrics` | ❌ | ✅ | Duration, dimensions |

> **Why are some fields null?** TikTok's public APIs only expose a subset of ad data. Fields marked ❌ are not returned by TikTok — this is a platform limitation, not a scraper bug. No TikTok scraper can retrieve data that TikTok doesn't expose publicly.

***

### 🎯 Use cases

**Competitor creative intelligence**
Pull all active ads from your competitor's brand in their key markets. Analyze which video hooks, CTAs, and creative formats they're investing in — and how large an audience they're reaching.

**Building a TikTok ad swipe file**
Use Creative Center source to extract top-performing video ads by country, industry, and objective. Filter by `budgetRange: HIGH` and `ctr > 2.0` to collect only proven performers for your creative research.

**EU DSA compliance monitoring**
Track political, social, or issue-based advertisers in Europe using the Ads Library source. The `adPaidForBy`, `targetAgeGroups`, `targetGender`, and `targetInterests` fields reveal who is being targeted and by whom — exactly what DSA Article 39 requires to be transparent.

**Agency multi-brand reporting**
Run weekly scrapes for a portfolio of brands across multiple EU markets. Export to CSV, push to Google Sheets, or integrate via Apify API into your reporting dashboard.

**E-commerce market intelligence**
Monitor competitor ads in specific countries before entering a new market. See what formats (video vs image), what hooks, and which brands are getting the highest CTR in your niche.

**Ad spend estimation (EU only)**
While TikTok doesn't expose exact spend, `uniqueUsersSeen` + `targetCountries` gives you a strong signal of which campaigns are getting real budget. A campaign reaching 500K+ users across 5 EU countries is clearly a priority for that advertiser.

**Creative trend analysis**
Track how creative formats are shifting over time. Run the same query monthly and compare: are competitors shifting from video to image? Are they testing new CTA types? Which hooks are disappearing and which are growing?

**Influencer & creator strategy**
The `targetBehaviors.creatorInteractions` field reveals which advertisers are targeting users who engage with specific creator profiles — a strong signal about which creator niches are commercially attractive.

***

### 💰 Pricing

**From $15.00 / 1,000 ads** — no monthly fees, pay only for what you scrape.

| Mode | Coverage | ~Cost per 1,000 ads |
|---|---|---|
| `source: "library"` | EU/EEA/UK DSA data | **~$15** |
| `source: "creative_center"` | Global top ads | **~$15** |
| `source: "both"` | Combined — max data | **~$16–17** |

> The `both` mode runs two browser sessions (one per source) which adds a small amount of Apify platform compute on top of the base event fee. No monthly fees — pay only for what you scrape.

***

### ⚠️ Limitations

**TikTok Ads Library is EU/EEA/UK only**
This is a hard platform constraint — TikTok built the Ads Library specifically for EU Digital Services Act compliance. US, APAC, LATAM, and Middle East markets are not available through this source. Use `source: "creative_center"` for global coverage.

**3,600-result hard cap per query (library)**
TikTok caps the Ads Library at 300 pages × 12 ads = 3,600 results per search. The scraper detects this and logs a clear warning. To get more comprehensive data, run multiple narrower searches (e.g., different date ranges, different keywords).

**No spend data**
TikTok does not expose actual ad spend figures — not even ranges. This is unlike Meta, which provides `{min, max}` spend for political ads. All TikTok spend intelligence tools (AdSpyder, PiPiAds, etc.) are using estimates, not real figures.

**`adText` is null for Library source**
TikTok's Ads Library API does not expose ad copy text — not in the search API, not in the detail API. This is a deliberate platform choice. The Creative Center source does return `adText` (ad title) when the advertiser configured it.

**Residential proxies required**
TikTok aggressively blocks datacenter IP ranges. The scraper uses residential proxies automatically — no configuration needed on your end.

**Creative Center shows only top-performing ads**
The Creative Center does not return all ads — only ads that TikTok's algorithm has identified as top performers in a given period, country, and category. This is by design: it's a creative inspiration tool, not a complete ad archive.

**TikTok page structure may change**
TikTok periodically updates their frontend. If results become empty after an update, open an issue and we'll push a fix within 24–48 hours.

***

### 🌍 Supported countries — quick reference

**Ads Library (EU only)**

| Code | Country |
|---|---|
| AT | Austria |
| BE | Belgium |
| BG | Bulgaria |
| CY | Cyprus |
| CZ | Czech Republic |
| DE | Germany |
| DK | Denmark |
| EE | Estonia |
| ES | Spain |
| FI | Finland |
| FR | France |
| GR | Greece |
| HR | Croatia |
| HU | Hungary |
| IE | Ireland |
| IT | Italy |
| LT | Lithuania |
| LU | Luxembourg |
| LV | Latvia |
| MT | Malta |
| NL | Netherlands |
| PL | Poland |
| PT | Portugal |
| RO | Romania |
| SE | Sweden |
| SI | Slovenia |
| SK | Slovakia |
| IS | Iceland |
| LI | Liechtenstein |
| NO | Norway |
| CH | Switzerland |
| GB | United Kingdom |

**Creative Center (global — examples)**

`US` `GB` `AU` `CA` `DE` `FR` `BR` `MX` `JP` `KR` `IN` `ID` `TH` `PH` `VN` `SG` `MY` `ZA` `AE` `SA` — and many more.

# Actor input Schema

## `source` (type: `string`):

Which TikTok data source to scrape. 'library' = TikTok Ads Library (EU/EEA/UK only, no login, DSA transparency data). 'creative\_center' = TikTok Creative Center Top Ads (global, performance metrics). 'both' = both sources combined.

## `searchTerms` (type: `array`):

Brand names or keywords to search. Each term is searched separately. Used for 'library' source only — Creative Center is browsed by category/country.

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

ISO 2-letter country codes. For Ads Library: EU/EEA/UK countries only (DE, FR, IT, ES, NL, PL, SE, etc.). For Creative Center: any country including US, GB, AU, BR, JP, etc.

## `adType` (type: `string`):

Filter by creative format.

## `dateFrom` (type: `string`):

Show ads first seen on or after this date. Format: YYYY-MM-DD. Leave empty to skip. Applies to Ads Library source only.

## `dateTo` (type: `string`):

Show ads first seen on or before this date. Format: YYYY-MM-DD. Leave empty to skip. Applies to Ads Library source only.

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

Maximum ads to collect per search term + country pair. Note: TikTok Ads Library is capped at 3,600 results per query (300 pages × 12 ads). The scraper will warn you when approaching this limit.

## `resolveAdDetails` (type: `boolean`):

For each Library ad, fetch its full detail page to collect: advertiser business ID, 'Ad paid for by', targeting age groups, targeting gender, targeting interests, target countries, and behavior targeting. Adds ~3 sec per ad — disable for large bulk runs, enable when you need full targeting data.

## Actor input object example

```json
{
  "source": "library",
  "searchTerms": [
    "Nike"
  ],
  "countries": [
    "DE"
  ],
  "adType": "ALL",
  "dateFrom": "",
  "dateTo": "",
  "maxResults": 10,
  "resolveAdDetails": false
}
```

# Actor output Schema

## `adId` (type: `string`):

Unique TikTok ad identifier. Always populated.

## `source` (type: `string`):

"library" (EU/EEA/UK DSA transparency data) or "creative\_center" (global top ads). Always populated.

## `advertiserName` (type: `string`):

Brand or business name running the ad. Always populated.

## `advertiserBusinessId` (type: `string`):

TikTok internal business identifier. Library source only — requires resolveAdDetails: true. Null otherwise.

## `adPaidForBy` (type: `string`):

Entity that paid for the ad (DSA transparency). Library source only — requires resolveAdDetails: true. Null otherwise.

## `adText` (type: `string`):

Ad title or caption. Creative Center source only — populated when advertiser configured it. Always null for Library source (not exposed by TikTok Library API).

## `videoUrl` (type: `string`):

Direct CDN URL of the video creative (.mp4). Populated for VIDEO ads from both sources.

## `thumbnailUrl` (type: `string`):

Cover image URL. Populated for both sources when available.

## `imageUrls` (type: `string`):

Array of image creative URLs. Populated for IMAGE ads. Empty array for video-only ads.

## `firstShownDate` (type: `string`):

Date the ad first appeared (YYYY-MM-DD). Library source only. Null for Creative Center.

## `lastShownDate` (type: `string`):

Most recent date the ad was shown (YYYY-MM-DD). Library source only. Null for Creative Center.

## `adStatus` (type: `string`):

ACTIVE or INACTIVE. Library: derived from audit\_status. Creative Center: always ACTIVE (only running ads are shown).

## `daysRunning` (type: `string`):

Days since first shown. Library source only — computed from firstShownDate to lastShownDate (or today if still ACTIVE). Null for Creative Center.

## `uniqueUsersSeen` (type: `string`):

Impression range estimate from TikTok (e.g. {range: '10M-20M'}). Library source only — populated when resolveAdDetails: true. Null for Creative Center or when resolveAdDetails is off.

## `uniqueUsersSeenByCountry` (type: `string`):

Per-country impression breakdown (e.g. \[{country:'DE', impressions:'15.2M'}]). Library source only — populated when resolveAdDetails: true. Empty array otherwise.

## `targetCountries` (type: `string`):

Countries the ad was targeted to. Library: requires resolveAdDetails: true (populated from targeting data). Creative Center: populated from ad metadata. Empty array when not available.

## `targetAgeGroups` (type: `string`):

Age brackets targeted (e.g. 18-24, 25-34). Library source only — requires resolveAdDetails: true. Empty array otherwise.

## `targetGender` (type: `string`):

Gender targeted: Male, Female, or All. Library source only — requires resolveAdDetails: true. Null otherwise.

## `targetInterests` (type: `string`):

Interest categories targeted. Library source only — requires resolveAdDetails: true. Empty array otherwise.

## `targetAudienceType` (type: `string`):

Custom or lookalike audience type. Library source only — requires resolveAdDetails: true. Null otherwise.

## `targetBehaviors` (type: `string`):

Behavioral targeting flags: {videoInteractions, creatorInteractions}. Library source only — requires resolveAdDetails: true. Null otherwise.

## `usersTargetedEstimate` (type: `string`):

Estimated size of targeted audience. Library source only — basic estimate from search API; more precise value when resolveAdDetails: true. Null for Creative Center.

## `rejectedInCountries` (type: `string`):

Countries where the ad was rejected by TikTok. Library source only. Empty array if not rejected or not applicable.

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

Advertiser industry category. Creative Center source only. Null for Library.

## `campaignObjective` (type: `string`):

Campaign goal: TRAFFIC, CONVERSIONS, REACH, APP\_INSTALL, etc. Creative Center source only. Null for Library.

## `budgetRange` (type: `string`):

Relative budget level: LOW, MEDIUM, or HIGH. Creative Center source only. Null for Library.

## `ctr` (type: `string`):

Click-through rate (%). Creative Center source only. Null for Library.

## `likes` (type: `string`):

Number of likes on the ad video. Creative Center source only. Null for Library.

## `videoMetrics` (type: `string`):

Video technical details: {duration (seconds), width (px), height (px)}. Creative Center source only. Null for Library or if not available.

## `scrapedAt` (type: `string`):

ISO 8601 timestamp when this ad record was collected.

# 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 = {
    "searchTerms": [
        "Nike"
    ],
    "countries": [
        "DE"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brilliant_gum/tiktok-ads-library-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 = {
    "searchTerms": ["Nike"],
    "countries": ["DE"],
}

# Run the Actor and wait for it to finish
run = client.actor("brilliant_gum/tiktok-ads-library-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "Nike"
  ],
  "countries": [
    "DE"
  ]
}' |
apify call brilliant_gum/tiktok-ads-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=brilliant_gum/tiktok-ads-library-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "TikTok Ads Library Scraper — EU Library & Creative Center",
        "description": "Scrape TikTok Ads Library (EU/EEA/UK) and Creative Center (global). Extract ad creatives, targeting data, reach estimates, CTR, video URLs, and industry insights. Dual-source coverage — no login required. Residential proxies built-in.",
        "version": "1.0",
        "x-build-id": "AXDvfyXZKvFYl8pXX"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/brilliant_gum~tiktok-ads-library-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-brilliant_gum-tiktok-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/brilliant_gum~tiktok-ads-library-scraper/runs": {
            "post": {
                "operationId": "runs-sync-brilliant_gum-tiktok-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/brilliant_gum~tiktok-ads-library-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-brilliant_gum-tiktok-ads-library-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "source"
                ],
                "properties": {
                    "source": {
                        "title": "Data Source",
                        "enum": [
                            "library",
                            "creative_center",
                            "both"
                        ],
                        "type": "string",
                        "description": "Which TikTok data source to scrape. 'library' = TikTok Ads Library (EU/EEA/UK only, no login, DSA transparency data). 'creative_center' = TikTok Creative Center Top Ads (global, performance metrics). 'both' = both sources combined.",
                        "default": "library"
                    },
                    "searchTerms": {
                        "title": "Search Terms / Keywords",
                        "type": "array",
                        "description": "Brand names or keywords to search. Each term is searched separately. Used for 'library' source only — Creative Center is browsed by category/country.",
                        "default": [
                            "Nike"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "countries": {
                        "title": "Countries",
                        "type": "array",
                        "description": "ISO 2-letter country codes. For Ads Library: EU/EEA/UK countries only (DE, FR, IT, ES, NL, PL, SE, etc.). For Creative Center: any country including US, GB, AU, BR, JP, etc.",
                        "default": [
                            "DE"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "adType": {
                        "title": "Ad Type / Format",
                        "enum": [
                            "ALL",
                            "VIDEO",
                            "IMAGE"
                        ],
                        "type": "string",
                        "description": "Filter by creative format.",
                        "default": "ALL"
                    },
                    "dateFrom": {
                        "title": "Date From (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Show ads first seen on or after this date. Format: YYYY-MM-DD. Leave empty to skip. Applies to Ads Library source only.",
                        "default": ""
                    },
                    "dateTo": {
                        "title": "Date To (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Show ads first seen on or before this date. Format: YYYY-MM-DD. Leave empty to skip. Applies to Ads Library source only.",
                        "default": ""
                    },
                    "maxResults": {
                        "title": "Max Results Per Search",
                        "minimum": 1,
                        "maximum": 3600,
                        "type": "integer",
                        "description": "Maximum ads to collect per search term + country pair. Note: TikTok Ads Library is capped at 3,600 results per query (300 pages × 12 ads). The scraper will warn you when approaching this limit.",
                        "default": 10
                    },
                    "resolveAdDetails": {
                        "title": "Resolve Ad Details (Library source only)",
                        "type": "boolean",
                        "description": "For each Library ad, fetch its full detail page to collect: advertiser business ID, 'Ad paid for by', targeting age groups, targeting gender, targeting interests, target countries, and behavior targeting. Adds ~3 sec per ad — disable for large bulk runs, enable when you need full targeting data.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
