# TikTok Ads Library Scraper: EU Ads, Targeting and Reach (`themineworks/tiktok-ads-library-scraper`) Actor

Scrape TikTok's EU Ad Library (DSA) by keyword, advertiser name or id: advertiser, paid for by, first and last shown, unique users by country with age and gender split, targeting, ad text, landing page, video and image links. No login.

- **URL**: https://apify.com/themineworks/tiktok-ads-library-scraper.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Social media, Marketing, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.09 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## TikTok Ads Library Scraper: EU Ads, Targeting and Reach

[![120 TikTok EU ads with targeting in 166 s](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/tiktok-ads-library-scraper-hero.png)](https://console.apify.com/actors/u8QEKVgwuRJcrobwP/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

From **The Mine Works**, makers of [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) and [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), with over 140,000 runs across 170+ public actors.

### Why choose this actor?

- **The full disclosure record of every ad, not just the thumbnail.** Each row carries what TikTok publishes under the EU Digital Services Act: advertiser, who paid for the ad, first and last day shown, unique users reached (the range, and by country with the age and gender split) and the targeting the advertiser chose. Our proof run returned **120 ads from 3 searches in 5 countries in 166 seconds**, every one with its detail record. For 40 of them someone other than the advertiser paid, mostly agencies, and 11 reached between 16 and 25 countries.
- **Search the way you think about competitors.** Keywords and advertiser names, exact phrases in quotes, or an advertiser's complete ad history by its exact name, which the actor looks up in the library for you. In our proof run `NIKE Retail B.V.` was found by name and the library reported 75,628 matching ads for it in the five countries; the actor read the first 40 with details. You never need an advertiser id, and you can run up to 100 searches of up to 5,000 ads each.
- **You pay only for ads you receive.** One charge per ad row saved to your dataset, plus a flat start fee per run. Ads seen twice in a run, ads an earlier run already gave you (when you switch that on), ads whose details TikTok would not serve, advertiser names the library does not know and searches that match nothing are never charged. No TikTok account, no cookies, no proxy add-on.

[![Run it on Apify](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/button-run.png)](https://console.apify.com/actors/u8QEKVgwuRJcrobwP/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Part of The Mine Works Social media and video family:** [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Reddit Scraper](https://apify.com/themineworks/reddit-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Threads Search Scraper](https://apify.com/themineworks/threads-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Instagram Profile Scraper](https://apify.com/themineworks/instagram-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Instagram Followers & Following](https://apify.com/themineworks/instagram-followers-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Reddit Search Scraper](https://apify.com/themineworks/reddit-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral).

### Try it in one minute

Paste this input and press Start. It returns 20 adidas ads shown in Germany, each with its advertiser, paid for by, reach by country and targeting, in about 30 seconds:

```json
{
  "searchTerms": ["adidas"],
  "countries": ["DE"],
  "maxAdsPerSearch": 20
}
```

You can ask for ads in four ways, and mix them in one run:

- **Search terms**: keywords or advertiser names, matched the way the Ad Library's own search box matches them, against advertiser names and ad text (`nike`, `running shoes`, `zalando`).
- **Exact phrases**: a term in double quotes matches that phrase only (`"black friday"`, `"just do it"`).
- **Advertisers**: every ad of one advertiser, by the exact name the library shows (`NIKE Retail B.V.`, `Zalando SE`). The actor finds the advertiser with the library's own advertiser lookup. To pin one advertiser account, write `name | id` from the `advertiser_name` and `advertiser_id` of an earlier row, for example `adidas AG | 6885261436319171329`.
- **Browse**: no term at all. Tick `browseWithoutSearch` to list every ad shown in your countries and dates, sorted by last shown, first shown or reach.

Apify's free plan includes $5 of credit every month, which covers about 2,400 results at this actor's price.

#### Copy to your AI assistant

```text
themineworks/tiktok-ads-library-scraper on Apify. Returns ads from TikTok's public EU Ad Library (the Digital Services Act repository for ads shown in the EU and EEA, Switzerland, the United Kingdom and Turkey), one row per ad with advertiser name and id, paid for by, first and last shown date, unique users reached (range, and by country with age and gender split), targeting (countries, age groups, genders, interests, audience size, custom audience), objective, call to action, landing page, ad text and video and image links. Call ApifyClient("TOKEN").actor("themineworks/tiktok-ads-library-scraper").call(run_input={"searchTerms": ["adidas"], "countries": ["DE"], "maxAdsPerSearch": 20}), then client.dataset(run["defaultDatasetId"]).list_items().items. Required: at least one of searchTerms (keywords or advertiser names; "quoted" for exact phrases), advertisers (exact advertiser names, or "name | id"), or browseWithoutSearch true. Optional: countries (default all covered countries, ISO codes such as DE, FR, GB), dateFrom and dateTo (YYYY-MM-DD, default the last 365 days), maxAdsPerSearch (default 20, 20 to 5000), includeDetails (default true), onlyNewAds (default false), sortBy, adStatus, mediaType, targetGender, targetAges, uniqueUsers. Skip rows that have "_type": "info". Full spec: GET https://api.apify.com/v2/acts/themineworks~tiktok-ads-library-scraper/builds/default (Bearer TOKEN), which returns inputSchema and readme. Token: https://console.apify.com/account/integrations?fpr=ymnoit&utm_source=apify-readme&utm_medium=referral
```

### Key features

- **Over 50 fields per ad with details on**: ad id and link, advertiser name, account id and country of registration, paid for by, the TikTok account the ad ran from (username, display name, followers, link, account type), ad text, media type, video, cover and image links, industry, objective, call to action, landing page, first and last shown date and days shown, unique users (range, minimum and maximum as numbers), unique users by country with the age and gender split, and the targeting: countries, age groups, genders, interests, video and creator interactions, audience size, custom audience and exclusion, high spending power, cities, provinces, languages, devices and operating systems.
- **33 countries**: every country the library covers, the 27 EU members, Iceland, Liechtenstein, Norway, Switzerland, the United Kingdom and Turkey. Pick some or leave the list empty for all.
- **Up to 5,000 ads per search and 100 searches per run**, the most the library lists for one search. Each search line has its own status, match count and stop reason in the run summary.
- **The library's own filters**: date range shown, active or inactive ads, video or image ads, targeted gender, targeted age groups and unique users reached (under 10K, 10K to 100K, over 100K), and the sort order for browsing.
- **Advertiser lookup built in**: write an advertiser's name and the actor finds the matching advertiser accounts in the library, runs one search per account, and reports names it cannot find with the closest names it saw.
- **Only new ads on repeat runs**: switch on `onlyNewAds` for a schedule and each run returns, and charges, only ads no earlier run in your account delivered. In our test the second run skipped the 20 ads of the first and delivered 20 others.

### How to use it

#### Basic: one brand's ads in one country

```json
{
  "searchTerms": ["zalando"],
  "countries": ["DE"],
  "maxAdsPerSearch": 100
}
```

You get up to 100 rows, best matches first, each with the detail record. A search term also matches ads from other advertisers that mention it in their text, which is how the library's own search box works. For one advertiser only, use `advertisers` instead.

#### Several searches and countries at once

```json
{
  "searchTerms": ["zalando", "\"black friday\""],
  "advertisers": ["NIKE Retail B.V."],
  "countries": ["DE", "FR", "IT", "ES", "NL"],
  "maxAdsPerSearch": 40
}
```

This is our proof run: three searches, 40 ads each, in five countries. In JSON the quotes of an exact phrase are written as `\"`; in the Console form you type them as normal quotes.

#### Weekly competitor creative report

```json
{
  "advertisers": ["Zalando SE", "NIKE Retail B.V.", "adidas AG"],
  "dateFrom": "2026-09-28",
  "dateTo": "2026-10-05",
  "maxAdsPerSearch": 200,
  "onlyNewAds": true
}
```

Every ad your competitors showed in the EU in the week, with the creative, the landing page, the objective and who it was aimed at. Schedule it weekly in Apify Console (Schedules, Add schedule) and move the dates along, or leave the dates out and let `onlyNewAds` keep each run to ads you have not seen. A name that matches two advertiser accounts (the library knows both `Adidas AG` and `adidas AG`) runs one search for each.

#### Who reaches the most people in a country

```json
{
  "browseWithoutSearch": true,
  "countries": ["DE"],
  "sortBy": "most_users",
  "maxAdsPerSearch": 500,
  "includeDetails": false
}
```

The ads with the most unique users in Germany over the last year, whoever ran them. With `includeDetails` off the actor reads the result list only, which is several times faster; turn it on when you need paid for by, reach by country and targeting. In our test the 200 widest reaching German ads came back in 75 seconds, led by Samsung, Subway, L'Oréal and Rossmann, each in the 1M to 10M band.

#### Targeting research for one audience

```json
{
  "searchTerms": ["skincare", "protein"],
  "countries": ["FR", "DE"],
  "mediaType": "video",
  "targetAges": ["18-24"],
  "targetGender": "female",
  "adStatus": "active",
  "maxAdsPerSearch": 100
}
```

Active video ads aimed at women aged 18 to 24, with the interests, audience sizes and custom audience flags their advertisers disclosed. Useful for agencies planning a launch and for researchers who study how ads are targeted.

#### Political and transparency research

Ads in the library carry who paid for them (`paid_for_by`), which often differs from the advertiser (an agency, a parent company or a reseller), where the advertiser is registered, whether the ad was removed and why. Browse a country and date window with details on, then group by `paid_for_by` or `advertiser_registered_in`. TikTok's ad policies do not allow political ads, so you will mostly find brands, shops and services.

### Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `searchTerms` | array of strings | none (an input with no searches at all runs `adidas`) | One search per line: keywords or advertiser names, matched like the library's search box. A term in double quotes is an exact phrase. Up to 100 searches per run. |
| `advertisers` | array of strings | none | Every ad of one advertiser per line: its exact name as the library shows it, or `name \| id` from an earlier row. |
| `browseWithoutSearch` | boolean | `false` | With no search terms and no advertisers, list every ad shown in the chosen countries and dates. |
| `countries` | array of strings | all covered countries | Country codes: AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR, or `all`. |
| `dateFrom` | string (YYYY-MM-DD) | 365 days before `dateTo` | Ads shown on or after this day. The library search does not accept days before 2023-08-01. |
| `dateTo` | string (YYYY-MM-DD) | today | Ads shown on or before this day. |
| `maxAdsPerSearch` | integer | `20` | Ads to collect for each search line, 20 to 5,000. |
| `includeDetails` | boolean | `true` | Read each ad's detail record: advertiser id and country, paid for by, objective, landing page, call to action, reach by country and targeting. Off returns the list fields only, about three times faster. |
| `onlyNewAds` | boolean | `false` | Skip ads an earlier run of this actor already delivered to you. |
| `sortBy` | string | `last_shown_newest` | Order when browsing: `last_shown_newest`, `last_shown_oldest`, `first_shown_newest`, `first_shown_oldest`, `most_users`, `fewest_users`. With a search term TikTok ranks by match. |
| `adStatus` | string | `all` | `all`, `active` or `inactive`. |
| `mediaType` | string | `all` | `all`, `video` or `image`. |
| `targetGender` | string | `all` | `all`, `female` or `male`: only ads whose targeting includes it. |
| `targetAges` | array of strings | all ages | Any of `13-17`, `18-24`, `25-34`, `35-44`, `45-54`, `55+`. |
| `uniqueUsers` | array of strings | any reach | Any of `under_10k`, `10k_100k`, `over_100k`. |

### What data do you get?

One row per ad. Fields marked (details) need `includeDetails`, which is on by default.

**The ad**: `ad_id`, `ad_url` (its page in the library), `ad_text`, `media_type` (video or image), `industry`, `video_urls`, `video_cover_urls`, `image_urls`, `first_shown_date`, `last_shown_date`, `days_shown`, `audit_status`, `removed`, `removal_reasons`, `objective` (details), `call_to_action` (details), `landing_page_url` (details).

**The advertiser**: `advertiser_name`, and with details `advertiser_id`, `advertiser_registered_in`, `paid_for_by`, and the TikTok account the ad ran from when the library names one: `tiktok_username`, `tiktok_display_name`, `tiktok_followers`, `tiktok_profile_url`, `tiktok_account_type`.

**Reach**: `unique_users_seen` (the range the library shows, such as `1M-10M`), `unique_users_min` and `unique_users_max` as numbers, and with details `unique_users_total`, `countries_reached` and `unique_users_by_country`: per country the unique users and the split by age group and gender. The library writes a dash where it hides a small number.

**Targeting** (details): `target_countries`, `target_age_groups`, `target_genders`, `target_audience_size`, `target_interests`, `target_video_interactions`, `target_creator_interactions`, `custom_audience`, `audience_exclusion`, `high_spending_power`, `target_cities`, `target_provinces`, `target_languages`, `target_devices`, `target_operating_systems`. Interests and interactions appear only when the advertiser used them: 17 of the 120 ads in our proof run named interests, such as Online Shopping and Sports & Fitness.

**The run**: `has_details`, `position` (rank in the search results), `search` (the search line, or for an advertiser its name and id), `countries_filter`, `scraped_at`.

#### Stable fields for automations

These fields were present in every row of our test runs, with details on and off:

| Field | Meaning |
|---|---|
| `ad_id` | The library's ad id; use it to dedupe |
| `ad_url` | Link to the ad's page in the library |
| `media_type` | `video` or `image` |
| `first_shown_date` | First day shown, YYYY-MM-DD |
| `last_shown_date` | Last day shown, YYYY-MM-DD |
| `days_shown` | Days from first to last shown, both counted |
| `unique_users_seen` | Unique users reached, as the range the library shows |
| `unique_users_min` | Lower end of that range as a number |
| `audit_status` | `1` shown normally, `2` shown as removed |
| `removed` | `true` when the library shows the ad as removed |
| `has_details` | `true` when the detail record was read |
| `position` | Rank in the search results |
| `search` | The search line the ad came from |
| `countries_filter` | Countries the search covered |
| `scraped_at` | When the row was read |

These names will not change. New fields may be added; existing ones keep their name and meaning.

#### Output examples

Real rows from our test runs on 6 October 2026, trimmed: long media links are cut, and lists of countries and age and gender splits are shortened.

**A brand ad with details and interest targeting** (search `zalando`):

```json
{
  "ad_id": "1850682199250961",
  "ad_url": "https://library.tiktok.com/ads/detail/?ad_id=1850682199250961",
  "advertiser_name": "Zalando SE",
  "ad_text": "Zalando",
  "media_type": "video",
  "first_shown_date": "2025-12-09",
  "last_shown_date": "2025-12-31",
  "days_shown": 23,
  "unique_users_seen": "1M-10M",
  "unique_users_min": 1000000,
  "unique_users_max": 10000000,
  "industry": "Apparel & Accessories",
  "video_urls": ["https://library.tiktok.com/api/v1/cdn/1791234952/video/aHR0cHM6Ly92MTZ..."],
  "audit_status": "1",
  "removed": false,
  "has_details": true,
  "advertiser_id": "6876456332912755458",
  "advertiser_registered_in": "Germany",
  "paid_for_by": "Zalando SE",
  "tiktok_username": "zalando",
  "tiktok_display_name": "Zalando",
  "tiktok_followers": "2.2M",
  "tiktok_account_type": "BLUEV_BA",
  "landing_page_url": "https://www.zalando.es/live/show/01kbq22xg50262vk9e3sv27n5g/?wmc=smp330__.52522860___..&opc=2211",
  "call_to_action": "Watch now",
  "objective": "Traffic",
  "unique_users_total": "1M-10M",
  "countries_reached": 1,
  "unique_users_by_country": [
    { "country": "ES", "unique_users": "1.8M", "unique_users_approx": 1800000, "by_age_gender": [ { "age": "25-34", "gender": "female", "unique_users": "-" } ] }
  ],
  "target_countries": ["ES"],
  "target_age_groups": ["25-34", "35-44", "45-54"],
  "target_genders": ["female", "male", "unknown"],
  "target_audience_size": "6.3M-7.6M",
  "target_interests": ["Online Shopping"],
  "target_creator_interactions": ["Fashion & Beauty"],
  "custom_audience": false,
  "audience_exclusion": false,
  "high_spending_power": false,
  "target_operating_systems": ["ALL"],
  "search": "zalando",
  "countries_filter": "DE,FR,IT,ES,NL",
  "position": 6
}
```

**An ad paid for by an agency, shown in 16 countries** (exact phrase `"black friday"`):

```json
{
  "ad_id": "1878076455406610",
  "advertiser_name": "南京同诺仓储设备制造有限公司",
  "advertiser_id": "7454123072484950032",
  "advertiser_registered_in": "China",
  "paid_for_by": "BLUEVISION INTERACTIVE LIMITED",
  "ad_text": "BLACK FRIDAY 50% OFF FOR A LIMITED TIME",
  "media_type": "video",
  "first_shown_date": "2026-10-04",
  "last_shown_date": "2026-10-04",
  "unique_users_seen": "0-1K",
  "objective": "Sales",
  "landing_page_url": "https://newblood66.com/products/eye-2-eye-polo?utm_source=tiktok&utm_c...",
  "countries_reached": 16,
  "unique_users_by_country": [
    { "country": "ES", "unique_users": "0-1K", "by_age_gender": [ { "age": "18-24", "gender": "male", "unique_users": "0-1K" } ] },
    { "country": "FR", "unique_users": "0-1K", "by_age_gender": [ { "age": "18-24", "gender": "male", "unique_users": "0-1K" } ] }
  ],
  "target_countries": ["ES", "FR", "GB", "NO", "NL", "PT", "CH", "BE", "DE", "FI", "IE", "PL", "DK", "IT", "SE", "AT"],
  "target_age_groups": ["18-24", "25-34", "35-44", "45-54", "55+"],
  "target_audience_size": "151.1M-184.6M",
  "custom_audience": false,
  "search": "\"black friday\""
}
```

**A list-only row** (`browseWithoutSearch`, Germany, `most_users`, details off):

```json
{
  "ad_id": "1859234897655858",
  "ad_url": "https://library.tiktok.com/ads/detail/?ad_id=1859234897655858",
  "advertiser_name": "Shopify (USA) Inc.",
  "ad_text": "Wachse mit Shopify",
  "media_type": "video",
  "first_shown_date": "2026-03-17",
  "last_shown_date": "2026-06-08",
  "days_shown": 84,
  "unique_users_seen": "1M-10M",
  "unique_users_min": 1000000,
  "unique_users_max": 10000000,
  "video_urls": ["https://library.tiktok.com/api/v1/cdn/1791235147/video/aHR0cHM6Ly92MTZ..."],
  "audit_status": "1",
  "removed": false,
  "has_details": false,
  "search": "all ads",
  "countries_filter": "DE",
  "position": 1
}
```

**A removed ad** (same run): the library hides the media and the advertiser, and says why.

```json
{
  "ad_id": "1835161482072097",
  "ad_text": "Conoce una profesión de alta demanda. Fórmate en 6 meses y mejora tu carrera. Clase gratis.",
  "media_type": "video",
  "first_shown_date": "2025-06-17",
  "last_shown_date": "2025-11-25",
  "days_shown": 162,
  "unique_users_seen": "1M-10M",
  "video_urls": [],
  "audit_status": "2",
  "removed": true,
  "removal_reasons": ["Our review shows that your advertising content may violate TikTok's advertising policies by promoting misleading employment or money-making opportunities. ..."],
  "has_details": false,
  "search": "all ads",
  "countries_filter": "DE",
  "position": 6
}
```

### Pricing

Pay per event: you pay for each ad delivered to your dataset, plus a flat $0.005 per run, whatever memory you choose. The price is the same with details on or off. Nothing else is billed: no proxy add-on, no charge per search or per page.

| Event | Free plan | Bronze (Starter) | Silver (Scale) | Gold (Business) and above |
|---|---|---|---|---|
| Ad delivered, per 1,000 ads | $1.99 | $1.69 | $1.39 | $1.09 |
| Run start, once per run | $0.005 | $0.005 | $0.005 | $0.005 |

**Never charged:** the same ad found by two searches in one run, ads an earlier run already delivered when `onlyNewAds` is on, ads whose details TikTok would not serve after six tries when `includeDetails` is on (they are left out of the dataset and listed in the run summary), advertiser names the library does not know, searches that match nothing, refused requests, and the information row at the end of a run. A run that delivers nothing costs only the start fee.

To cap a run's cost, set Maximum cost per run in the run options; the actor stops delivering, and charging, when that budget is used.

### FAQ

#### What is TikTok's Ad Library?

A public website, library.tiktok.com/ads, where TikTok lists the ads it showed in the European Union and the EEA, Switzerland, the United Kingdom and Turkey, as the EU Digital Services Act requires of very large platforms. For each ad it publishes the advertiser, who paid, when it ran, how many unique users saw it and how it was targeted. This actor reads exactly what that site shows any visitor.

#### Which countries are covered?

The 33 the library covers: Austria, Belgium, Bulgaria, Croatia, Cyprus, the Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Iceland, Ireland, Italy, Latvia, Liechtenstein, Lithuania, Luxembourg, Malta, the Netherlands, Norway, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Switzerland, Turkey and the United Kingdom. Ads shown only outside these countries, in the United States for example, are not in the library.

#### How many ads can I get?

Up to 5,000 per search, which is the most the library lists for one search, and up to 100 searches per run. For a bigger set, split it: one search per country, or narrower date windows.

#### How far back does it go?

The library lists ads shown in about the last year, and its search does not accept a start date before 1 August 2023. An ad that started earlier but was still shown inside your window is included: in our tests we found ads first shown in October 2022 that were still running in July 2026.

#### How fresh is the data?

Each run reads the library live, so you get what it shows at that moment. In our runs on 5 and 6 October 2026 the newest ads had last been shown on 4 and 5 October.

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

No. The actor reads the library as a logged-out visitor. You do not need TikTok's research API either.

#### Why are runs with details slower, and how slow?

The detail record of each ad is a separate request, and TikTok answers only one or two of them per visitor before asking that visitor to wait several minutes. The actor therefore opens a fresh visitor session for each ad: a headless Chrome page receives the library's visitor token, and the requests themselves go out as plain web requests. Our proof run read 120 ads with details in 166 seconds, about 1.4 seconds per ad. With `includeDetails` off the actor reads only the result lists, 12 ads a request, and 200 ads took 75 seconds.

#### What happens with ads whose details TikTok will not serve?

Each is tried on up to six fresh visitor sessions. If none answers, the ad is left out and not charged, and its id is listed in the run summary (`details_failed_ad_ids`). If five ads in a row fail like this the run stops, so you never pay for a run TikTok is blocking. In our proof run every one of the 120 ads came back with its details.

#### Do the video links keep working?

No, not for long. The video and image links are signed by TikTok and stop working after some hours, so download the media soon after the run if you need it. The `ad_url` link to the ad's library page does not expire.

#### Can I monitor competitors for new ads?

Yes. Put their names in `advertisers`, switch on `onlyNewAds` and add a schedule (Apify Console, this actor, Schedules, Add schedule). Each run then returns, and charges, only ads you have not received before. In our test a second run of the same search skipped the 20 ads the first had delivered and returned 20 others.

#### Why did my advertiser name return nothing?

The name must match the library's spelling of the advertiser, which is often the legal entity, such as `NIKE Retail B.V.` rather than `Nike`. The run summary lists the closest names the library knows, so copy one of those. Or search the brand as a search term first, then use the `advertiser_name` and `advertiser_id` of a row as `name | id`.

#### In what formats can I export the data?

JSON, CSV, Excel, XML, RSS or an HTML table from the run's dataset, in Apify Console or through the API. Nested fields such as `unique_users_by_country` stay nested in JSON and are flattened into columns in CSV and Excel.

#### Can I use it from Claude, ChatGPT or another AI assistant?

Yes, through Apify's MCP server.

- Connector URL: https://mcp.apify.com/?tools=themineworks/tiktok-ads-library-scraper
- Claude: Settings > Connectors > Add custom connector, paste the URL, sign in with Apify.
- ChatGPT: turn on developer mode, add an MCP connector with the URL, sign in with Apify.
- Cursor or VS Code: add it as an HTTP MCP server with that URL.
- Claude Code: `claude mcp add -t http tiktok-ads-library-scraper "https://mcp.apify.com/?tools=themineworks/tiktok-ads-library-scraper"`

#### Is it legal to scrape TikTok's Ad Library?

The library exists so that the public can inspect these ads, and the actor collects only what it shows to anyone, without logging in. You are responsible for how you use the data: check TikTok's terms for your use case and the data protection laws that apply to you, such as GDPR and CCPA. Most advertisers are companies, but some are individual creators, so treat their names with care.

### Integrations

- **Google Sheets**: send each run's dataset to a sheet with Apify's Google Sheets integration, one row per ad.
- **Make, Zapier and n8n**: start a run and read its dataset with the Apify apps and nodes, for example to post a competitor's new ads to Slack every Monday.
- **Webhooks**: have Apify call your URL when a run finishes, then fetch the dataset.
- **API**: start runs and read results from any language with the Apify API or the Python and JavaScript clients (see "Copy to your AI assistant" above).
- **MCP clients**: Claude, ChatGPT, Cursor, VS Code and Claude Code, through the connector URL in the FAQ.

Related actors from us: [Facebook Ad Library Scraper](https://apify.com/themineworks/meta-ad-library-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) for Meta's ads, [Google Ads Transparency Scraper](https://apify.com/themineworks/google-ads-transparency?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) for an advertiser's Google ads, and [TikTok Creator Scraper](https://apify.com/themineworks/tiktok-creator-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) for the accounts behind the ads.

### More from The Mine Works

**Social media and video**

- [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Reddit Scraper](https://apify.com/themineworks/reddit-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Threads Search Scraper](https://apify.com/themineworks/threads-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Instagram Profile Scraper](https://apify.com/themineworks/instagram-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Instagram Followers & Following](https://apify.com/themineworks/instagram-followers-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Reddit Search Scraper](https://apify.com/themineworks/reddit-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Twitter / X Scraper](https://apify.com/themineworks/twitter-x-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [YouTube Transcript](https://apify.com/themineworks/youtube-transcript-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Xiaohongshu (RED) Scraper](https://apify.com/themineworks/xiaohongshu-explore-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Telegram Channel Scraper](https://apify.com/themineworks/telegram-channel-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Telegram Channel Finder](https://apify.com/themineworks/telegram-channel-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Pinterest Profile Scraper](https://apify.com/themineworks/pinterest-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Leads and business directories**

- [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Skip Trace Lookup](https://apify.com/themineworks/skip-trace-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Maps Email Scraper](https://apify.com/themineworks/maps-leads?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [2GIS Places Scraper](https://apify.com/themineworks/2gis-places-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Marketing, SEO and reviews**

- [Facebook Ad Library Scraper](https://apify.com/themineworks/meta-ad-library-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Ads Transparency Scraper](https://apify.com/themineworks/google-ads-transparency?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Similarweb Scraper](https://apify.com/themineworks/similarweb-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google News Scraper](https://apify.com/themineworks/google-news?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**LinkedIn**

- [LinkedIn Company Scraper](https://apify.com/themineworks/linkedin-company-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Post Scraper](https://apify.com/themineworks/linkedin-post-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Employees Scraper](https://apify.com/themineworks/linkedin-employees?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Profile Scraper](https://apify.com/themineworks/linkedin-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Real estate**

- [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zillow Sold Comps Scraper](https://apify.com/themineworks/zillow-recently-sold?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Real Estate MCP](https://apify.com/themineworks/india-real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Housing.com Scraper](https://apify.com/themineworks/housing-com-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Science, health and government data**

- [Academic Research MCP](https://apify.com/themineworks/academic-research-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [CourtListener Scraper](https://apify.com/themineworks/courtlistener-court-records?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Socrata Open Data Scraper](https://apify.com/themineworks/socrata-open-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [OpenAlex Scraper](https://apify.com/themineworks/openalex-scholarly-works?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Jobs and hiring**

- [Foundit Monster India Jobs](https://apify.com/themineworks/foundit-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Hirist Jobs Scraper](https://apify.com/themineworks/hirist-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Jobs MCP](https://apify.com/themineworks/india-jobs-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Naukri Jobs Scraper](https://apify.com/themineworks/naukri-jobs?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Company and business data**

- [Company Domain Finder](https://apify.com/themineworks/company-domain-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GST Taxpayer Lookup](https://apify.com/themineworks/gst-taxpayer-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Company KYB Resolver](https://apify.com/themineworks/company-identity-resolver?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [SEC EDGAR Filings Scraper](https://apify.com/themineworks/sec-edgar-filings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**E-commerce and marketplaces**

- [Ozon.ru Scraper](https://apify.com/themineworks/ozon-product-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [⭐ Amazon Reviews Scraper](https://apify.com/themineworks/amazon-reviews?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Amazon Product Scraper](https://apify.com/themineworks/amazon-products?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Etsy Listings Scraper](https://apify.com/themineworks/etsy-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Food and local services**

- [NoBroker Scraper](https://apify.com/themineworks/nobroker-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Swiggy Restaurant Scraper](https://apify.com/themineworks/swiggy-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zomato Scraper](https://apify.com/themineworks/zomato-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Developer and AI tools**

- [Website to Markdown Crawler](https://apify.com/themineworks/rag-crawler?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Skill Finder](https://apify.com/themineworks/github-skill-discovery?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Repo Scraper](https://apify.com/themineworks/github-repo-intelligence?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Trending Scraper](https://apify.com/themineworks/github-trending-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**More tools**

- [G2 Reviews Scraper](https://apify.com/themineworks/g2-reviews-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Naver Blog Scraper](https://apify.com/themineworks/naver-blog-posts-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [WeChat Article Scraper 微信公众号文章](https://apify.com/themineworks/wechat-article-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Taobao Products Scraper 淘宝 天猫](https://apify.com/themineworks/taobao-products-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

### Support

Found an ad or a search that does not come back right, or a field you need? Open an issue in the Issues tab and include the run link. For new sources or a custom build, email dmineworks@gmail.com.

*Every ad in TikTok's EU Ad Library that matches your keywords, phrases or advertisers, with who paid for it, when it ran, how many people it reached in each country and how it was targeted, read without a login and charged only for ads you receive.*

# Actor input Schema

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

One search per line, matched the way the Ad Library's own search box matches: advertiser names and words in the ad text (nike, adidas, running shoes). Put a phrase in double quotes for an exact phrase match ("just do it"). Up to 100 searches per run; repeats are run once.

## `advertisers` (type: `array`):

Optional. Every ad of one advertiser, one per line: the advertiser name exactly as the library shows it (adidas AG, NIKE Retail B.V., Zalando SE; capital letters do not matter). The actor finds the advertiser with the library's own advertiser lookup; a name that matches several advertiser accounts runs one search for each. To pin one account, write "name | id" with the advertiser_name and advertiser_id of a row, for example adidas AG | 6885261436319171329. A name the library does not know is reported in the run summary with its closest matches and costs nothing.

## `browseWithoutSearch` (type: `boolean`):

Only used when there are no search terms and no advertisers: lists every ad shown in the chosen countries and dates, in the order set by Sort by.

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

Ads shown in these countries. The library covers the EU and EEA, Switzerland, the United Kingdom and Turkey. Leave empty or pick All for every covered country.

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

Optional. Ads shown on or after this day. Empty means 365 days before the end date.

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

Optional. Ads shown on or before this day. Empty means today.

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

How many ads to collect for each search line, 20 to 5,000. The library lists at most 5,000 ads for one search; a search with fewer matches returns what it has.

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

Open each ad's detail record: advertiser id and country, paid for by, objective, landing page, call to action, unique users by country with the age and gender split, and the targeting (countries, ages, genders, interests, audience size and more). Untick for the list fields only (faster). With details on, an ad whose details TikTok will not serve is skipped and not charged.

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

Skip ads an earlier run of this actor already delivered to you, so a daily or weekly schedule returns and charges only ads it has not sent before.

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

Order of the results when browsing without a search term. With a search term TikTok ranks the ads by how well they match, as the library page does.

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

Active ads, inactive ads, or both.

## `mediaType` (type: `string`):

Video ads, image ads, or both.

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

Only ads whose targeting includes this gender.

## `targetAges` (type: `array`):

Optional. Only ads targeting at least one of these age groups. Empty means all ages.

## `uniqueUsers` (type: `array`):

Optional. Only ads in these reach bands. Empty means any reach.

## Actor input object example

```json
{
  "searchTerms": [
    "adidas"
  ],
  "browseWithoutSearch": false,
  "countries": [
    "DE"
  ],
  "maxAdsPerSearch": 20,
  "includeDetails": true,
  "onlyNewAds": false,
  "sortBy": "last_shown_newest",
  "adStatus": "all",
  "mediaType": "all",
  "targetGender": "all"
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "adidas"
    ],
    "countries": [
        "DE"
    ],
    "maxAdsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/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": ["adidas"],
    "countries": ["DE"],
    "maxAdsPerSearch": 20,
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,themineworks/tiktok-ads-library-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/u8QEKVgwuRJcrobwP/builds/3X5ma07ufdi9MSQDj/openapi.json
