# TikTok Ads Library Scraper (`datascoutlab/tiktok-ads-library-scraper`) Actor

Scrape the TikTok Ads Library: advertisers, creatives, reach and DSA targeting data across the EU, EEA and UK.

- **URL**: https://apify.com/datascoutlab/tiktok-ads-library-scraper.md
- **Developed by:** [Anton DataScout](https://apify.com/datascoutlab) (community)
- **Categories:** Marketing, Business, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Ads Library Scraper — Ad Copy, Reach & Targeting

[![TikTok Ads Library Scraper status](https://apify.com/actor-badge?actor=datascoutlab/tiktok-ads-library-scraper)](https://apify.com/datascoutlab/tiktok-ads-library-scraper)

**Scrape the TikTok Ads Library** by advertiser and country, and get back what competitors are actually running: the ad copy, the creative, the landing page — plus the transparency data TikTok is legally required to publish under the EU Digital Services Act: **how many people saw each ad, in which country, split by age and gender**.

No login, no API key, no browser.

### Table of contents

- [Why this TikTok ads scraper](#why-this-tiktok-ads-scraper)
- [The targeting data nobody bills you extra for](#the-targeting-data-nobody-bills-you-extra-for)
- [Broad vs exact advertiser match](#broad-vs-exact-advertiser-match)
- [Use cases](#use-cases)
- [Input](#input)
- [Output](#output)
- [Cost](#cost)
- [Honest limits](#honest-limits)
- [FAQ](#faq)
- [Related Actors](#related-actors)

***

### Why this TikTok ads scraper

| | Typical TikTok ads scraper | This Actor |
|---|---|---|
| Advertiser and creatives | ✅ | ✅ |
| **Ad copy** | often documented as *"not available"* | ✅ returned |
| **Impressions per country** | paid add-on or missing | ✅ included |
| **Age × gender breakdown** | paid add-on or missing | ✅ included |
| Advertiser's **TikTok account + followers** | ❌ | ✅ included |
| Who paid for the ad (`paidForBy`) | rarely | ✅ |
| Landing page + objective + CTA | partial | ✅ |
| Exact-advertiser mode | ❌ | ✅ returns the advertiser's full ad set |
| Failed detail requests | silently empty columns | ✅ reported with the HTTP status |

Competing Actors put ad copy and targeting behind a `resolveAdDetails`-style toggle and bill it separately, on top of the per-ad price. Here it is on by default and included in the price.

***

### The targeting data nobody bills you extra for

The TikTok Ads Library exists because Article 39 of the EU Digital Services Act forces large platforms to publish an ad repository. That law is why this data is unusually good — and this Actor keeps all of it:

```json
"totalImpressionsLabel": "1M-10M",
"topAgeGroup": "25-34",
"topGender": "FEMALE",
"impressionsByCountry": [{ "country": "DE", "impressions": 5300000, "impressionsLabel": "5.3M" }],
"ageGenderBreakdown": [
  { "country": "DE", "age": "18-24", "gender": "MALE",   "impressions": 767000 },
  { "country": "DE", "age": "18-24", "gender": "FEMALE", "impressions": 900000 }
]
```

Every display string like `"5.3M"` also gets a numeric twin, so you can sort and sum in a spreadsheet without cleaning anything first. `topAgeGroup` and `topGender` are computed by summing impressions across the grid, not by taking the first row.

***

### Broad vs exact advertiser match

This matters more than it sounds:

- **Broad match** — finds any advertiser whose name contains your text. Searching `Nike` returns roughly a thousand ads, mixed with unrelated accounts that merely have "nike" in the name.
- **Exact advertiser name** — matches the registered company in full, e.g. `NIKE Retail B.V.`. In testing this returned **4,198 ads, all genuinely Nike's**.

Start broad to discover the exact legal name (it comes back as `advertiserName`), then re-run in exact mode to pull that advertiser's complete history.

***

### Use cases

#### 1. Competitor ad research

See every ad a competitor ran in a market, with the copy, the creative and the landing page. Long-running ads with high reach are the ones worth studying.

#### 2. Creative swipe file

Download video and image creatives with their objective and call to action attached, so you know what each creative was actually trying to do.

#### 3. Audience validation

Before you guess who a product sells to, look at who the ads actually reached: impressions by age and gender, per country, straight from the platform.

#### 4. Market entry research

Compare the same advertiser across countries — who advertises in France but not Poland, and how reach differs between them.

#### 5. Agency and sponsor mapping

`paidForBy` names the media agency behind the ad, and `advertiserRegistryLocation` gives the registered country. Useful for mapping who buys media for whom.

#### 6. Influencer and brand-account discovery

Every ad links back to the TikTok account that ran it, with follower count and verification status.

#### 7. Compliance and brand monitoring

Track ads mentioning your brand, and spot rejected ads through the `isRejected` flag.

***

### Input

| Field | Description |
|---|---|
| **Countries** | Two-letter codes. EU-27, EEA, UK, Switzerland and Türkiye — 33 in total. |
| **Search terms** | Advertiser names. Required — TikTok returns nothing for an empty query. |
| **Match mode** | Broad, or exact registered company name. |
| **Advertiser business ID** | Optional. Pins the search to one exact advertiser. |
| **Time window** | Days back, or an explicit start and end date. |
| **Sort by** | Most recent, or highest reach first. |
| **Include ad copy and targeting** | On by default. One extra request per ad. |
| **Max ads per country and term** | Your cost ceiling. |

```json
{
  "regions": ["DE", "FR"],
  "searchTerms": ["NIKE Retail B.V."],
  "searchBy": "exact",
  "daysBack": 90,
  "sortBy": "impression,desc",
  "maxResultsPerQuery": 200
}
```

***

### Output

42 fields per ad. A trimmed sample:

```json
{
  "adId": "1866065258633346",
  "adUrl": "https://library.tiktok.com/ads/detail/?ad_id=1866065258633346",
  "adText": "Wenn du deinem Instinkt vertraust, gehört das Spiel dir.",
  "callToAction": "Learn more",
  "advertisingObjective": "Video views",
  "externalUrl": "https://www.nike.com/de/fussball",
  "firstShownDate": "2026-05-24",
  "lastShownDate": "2026-07-15",
  "daysRunning": 53,
  "estimatedAudience": "1M-10M",
  "topAgeGroup": "25-34",
  "topGender": "FEMALE",
  "advertiserName": "NIKE Retail B.V.",
  "advertiserRegistryLocation": "Netherlands",
  "paidForBy": "INITIATIVE MEDIA B.V.",
  "accountUsername": "nikefootball",
  "accountFollowers": 573400,
  "accountIsVerified": true
}
```

Grouped into **identity** · **creative** (copy, CTA, objective, landing page, video and image URLs) · **schedule** (first shown, last shown, days running) · **reach** · **DSA targeting** · **advertiser** · **TikTok account** · **status** · **provenance**.

***

### Cost

Pay per ad returned. `maxResultsPerQuery` caps each country/term pair, so the bill is knowable before the run starts.

Ad copy and targeting are **included** — no separate enrichment fee. A 36-ad run with full details takes about 25 seconds.

***

### Honest limits

- **EU, EEA, UK, Switzerland and Türkiye only — 33 countries.** The library is a DSA compliance product; there is no US or APAC data in it. Codes outside the list are skipped with a warning instead of failing the run.
- **A search term is required.** An empty query returns zero results from TikTok, so the Actor refuses it up front rather than finishing with an empty dataset.
- **No spend figures.** TikTok publishes reach, not money. Any tool claiming TikTok ad spend is estimating.
- **Reach is banded.** Audience sizes come as ranges like `1M-10M`; the numeric `estimatedAudienceMin`/`Max` fields expose both ends.
- **Some detail requests are refused.** TikTok rate-limits ad detail calls per IP. The Actor spreads them across a pool of independent sessions and retries on a fresh one, which recovers the large majority — but any ad that still fails is logged with its HTTP status and keeps its search-level fields. An empty `adText` is always traceable to a real refusal, never a silent gap.
- **Proxy**: datacenter proxies are enough. The library answers from any region, so residential proxies only add cost.

***

### FAQ

**Do I need a TikTok account or API key?**
No. The Ads Library is public by law.

**Why is there no US data?**
Because the library only exists to satisfy EU regulation. TikTok publishes no equivalent archive for the US.

**Can I get a competitor's complete ad history?**
Yes — run a broad search first to learn their exact registered name, then re-run in exact mode.

**Can I download the videos?**
`videoUrls` and `imageUrls` contain direct CDN links you can fetch or hand to Apify's storage.

**How current is it?**
Ads appear in the library while they run, so a daily scheduled run gives you a live feed of competitor activity.

**Is scraping the TikTok Ads Library legal?**
It collects only the public transparency data TikTok is required to publish, with no login and no personal data. How you use the data is your responsibility.

***

### Related Actors

- [Facebook Ads Library Scraper](https://apify.com/datascoutlab/fb-ads-library-scraper) — the same competitive research on Meta, with days-running per creative.
- [YouTube Outlier Finder](https://apify.com/datascoutlab/youtube-outlier-finder) — spot breakout video topics before they get crowded.
- [Google Trends Scraper](https://apify.com/datascoutlab/google-trends-reliable) — check whether the demand behind a campaign is actually growing.
- [Telegram Channel Scraper](https://apify.com/datascoutlab/telegram-channels-scraper) — track how campaigns spread in public communities.
- [Eventbrite Scraper](https://apify.com/datascoutlab/eventbrite-scraper) — events, organizers and demand signals.

# Actor input Schema

## `regions` (type: `array`):

Two-letter country codes. The TikTok Ads Library exists because of the EU Digital Services Act, so it covers the EU-27, EEA (IS, LI, NO), Switzerland, the UK and Türkiye. Codes outside that list are skipped with a warning rather than failing the run.

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

Advertiser names to search, one per line. Each term is searched separately in each country. At least one term is required — TikTok's library returns nothing for an empty query.

## `searchBy` (type: `string`):

`Exact advertiser` matches the registered company name in full ("NIKE Retail B.V.") and returns that advertiser's complete ad set — far more ads and no unrelated accounts. `Broad` matches any advertiser whose name contains your text, which is what you want when you don't know the exact legal name.

## `advertiserIds` (type: `string`):

Optional. Pins the search to one exact advertiser, avoiding name collisions. You get this ID as `advertiserBusinessId` in any previous run.

## `daysBack` (type: `integer`):

How far back to look, counting from today. Ignored when you set an explicit start and end date below.

## `startDate` (type: `string`):

Optional exact window start, `YYYY-MM-DD`. Set both start and end to override `Days back`.

## `endDate` (type: `string`):

Optional exact window end, `YYYY-MM-DD`.

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

`Most recently shown` follows the library default. Sorting by reach puts the ads that actually got impressions on top — usually what you want when researching what works.

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

On by default, and the main reason to use this Actor. Adds the ad text, call to action, landing page, the advertiser's TikTok account with follower count, and the DSA targeting breakdown — impressions per country split by age and gender. Costs one extra request per ad.

## `maxResultsPerQuery` (type: `integer`):

Upper bound for each country and term combination. You are billed per ad returned, so this is also your cost ceiling. TikTok serves results in pages of 12.

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

Datacenter proxies are enough — the Ads Library answers from any region, so residential proxies only add cost.

## Actor input object example

```json
{
  "regions": [
    "DE"
  ],
  "searchTerms": [
    "Nike"
  ],
  "searchBy": "broad",
  "daysBack": 30,
  "sortBy": "last_shown_date,desc",
  "includeDetails": true,
  "maxResultsPerQuery": 120,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `ads` (type: `string`):

Every ad found, with copy, creatives, reach and targeting in one flat row.

## `adsCsv` (type: `string`):

The same rows as CSV in a readable column order — open in Excel or pull into Google Sheets with IMPORTDATA().

## `runSummary` (type: `string`):

Ads collected per country and term, details retrieved, and the reason for any failed request.

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

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

# Run the Actor and wait for it to finish
run = client.actor("datascoutlab/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 '{
  "regions": [
    "DE"
  ],
  "searchTerms": [
    "Nike"
  ]
}' |
apify call datascoutlab/tiktok-ads-library-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/kJzjiPYF5H2QvgwLK/builds/ASEAqWufeS6jwjkO3/openapi.json
