# TikTok Ad Library Scraper (`getdataforu/tiktok-ad-library-scraper`) Actor

Scrape ads, advertisers, creatives and audience targeting from the official TikTok Commercial Content Library.

- **URL**: https://apify.com/getdataforu/tiktok-ad-library-scraper.md
- **Developed by:** [Daya Crawler](https://apify.com/getdataforu) (community)
- **Stats:** 2 total users, 1 monthly users, 86.7% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.00001 / actor start

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 Ad Library Scraper

Export every ad a brand is running on TikTok — the creative, how long it ran, who it reached and exactly who it was targeted at — straight from TikTok's own **Commercial Content Library**.

No login, no TikTok Ads account, no browser automation. Just a search term and a country.

### What you get

| | |
|---|---|
| **The ad** | Ad ID, ad text, format, industry, link to the official ad page |
| **The creative** | Direct video URL and cover image — downloadable, watermark-free |
| **The flight** | First shown date, last shown date, number of days running |
| **The reach** | Estimated audience band, impressions, impressions per country |
| **The advertiser** | Name, business ID, registered location, paying sponsor |
| **Their TikTok account** *(with targeting on)* | Handle, display name, follower count, profile link |
| **The targeting** *(optional)* | Audience size, age groups, genders, interests, languages, devices, operating systems, cities |

### What people use it for

- **Competitor ad spy** — pull every live ad of a competitor, see which creatives they keep running (high `daysRunning` = an ad that works).
- **Creative research** — download the winning videos in your industry before you brief your own.
- **Ad targeting research** — see the exact age, gender and interest targeting behind ads that scale.
- **Market monitoring** — run it on a schedule and track new advertisers entering your category.
- **Compliance and research** — the library is TikTok's DSA transparency dataset; this actor turns it into a spreadsheet.

### Country coverage — read this first

TikTok only publishes this data for **33 countries**: the EEA, the United Kingdom, Switzerland and Turkey.

> Austria, Belgium, Bulgaria, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Iceland, Ireland, Italy, Latvia, Liechtenstein, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Switzerland, Turkey, United Kingdom

There is **no US, Asian or Vietnamese ad library data** — not in this actor, and not on TikTok's site either.

### Input

```json
{
  "searchTerms": ["nike", "adidas"],
  "countries": ["GB", "DE", "FR"],
  "lastDays": 30,
  "adFormat": "video",
  "includeTargeting": true,
  "maxItems": 500
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `searchTerms` | array | — | **Required.** Matched against advertiser names *and* ad content. Each term is searched in every country. |
| `countries` | array | `["GB"]` | Two-letter codes from the list above. |
| `lastDays` | integer | `30` | How far back to look. Ignored if you set an exact range. |
| `dateFrom` / `dateTo` | string | — | Exact range as `YYYY-MM-DD`. |
| `adFormat` | string | `all` | `all`, `video` or `image`. |
| `sortBy` | string | `newest` | `newest` or `oldest`, by last shown date. |
| `includeTargeting` | boolean | `false` | Adds the targeting breakdown. One extra request per ad. |
| `maxItems` | integer | `1000` | Hard stop across all terms and countries — your cost control. |
| `maxRequestRetries` | integer | `6` | Retries per request, each from a fresh IP. TikTok answers "system busy" often; retries are normal. |
| `proxyConfiguration` | object | Residential | TikTok blocks repeat IPs fast; keep residential proxies on. |

### Output

One record per ad:

```json
{
  "adId": "1878667481281921",
  "adUrl": "https://library.tiktok.com/ads/detail/?ad_id=1878667481281921&region=GB",
  "country": "GB",
  "searchTerm": "nike",
  "advertiserName": "THE SOLE SUPPLIER LIMITED",
  "advertiserBizId": "7412060919536336897",
  "advertiserRegistryLocation": "United Kingdom",
  "advertiserTikTokHandle": "jdofficial",
  "advertiserTikTokFollowers": "3.6M",
  "advertiserTikTokUrl": "https://www.tiktok.com/@jdofficial",
  "adTitle": "Our current Nike obsession",
  "adFormat": "video",
  "industry": "Apparel & Accessories",
  "firstShownDate": "2026-10-08",
  "lastShownDate": "2026-10-10",
  "daysRunning": 3,
  "estimatedAudience": "1K-10K",
  "creativeAvailable": true,
  "videoUrl": "https://library.tiktok.com/api/v1/cdn/...",
  "coverImageUrl": "https://p16-common-sign.tiktokcdn.com/...",
  "targeting": {
    "audienceSize": "26.9M-32.9M",
    "totalImpressions": "0-1K",
    "countriesReached": 1,
    "impressionsByCountry": [{ "country": "GB", "impressions": "0-1K" }],
    "ageGroups": ["18-24", "25-34", "35-44"],
    "genders": ["female", "male"],
    "interests": [],
    "languages": [],
    "deviceModels": [],
    "operatingSystems": []
  },
  "scrapedAt": "2026-10-12T11:46:00.000Z"
}
```

Export it as **Excel, CSV, JSON, XML** or pull it through the Apify API.

### Tips

- **Finding one brand's full ad set:** search the brand's *legal entity name* as it appears in the library (e.g. `JD SPORTS FASHION PLC`), not its TikTok handle. That returns only that advertiser's ads.
- **Finding evergreen winners:** set `sortBy` to `oldest` — ads that are still running but started long ago are the ones that pay for themselves.
- **One keyword, one advertiser everywhere?** That is TikTok's ranking, not a bug: a single advertiser running hundreds of near-identical ads fills the first pages. Search their competitor's legal name instead, or narrow the date range.
- **Finding winning creatives:** scrape with `includeTargeting: false` first, sort by `daysRunning` descending, then re-run on just the winners with targeting on.
- **Scheduling:** set a schedule and `lastDays: 1` to capture new ads daily and build your own historical archive.
- **Blank advertiser names?** The search endpoint omits the advertiser on a minority of ads. Turning on `includeTargeting` fills them in from the ad's detail page, together with the brand's TikTok handle and follower count.
- **Cost:** every ad is one result. `includeTargeting` doubles the requests but gives the data nobody else exports.

### Limitations

- **Targeting is best-effort, and the shared proxy pool limits it.** TikTok rejects the per-ad targeting lookup from IP addresses it has seen too often. Measured over several runs on Apify's shared residential proxies, **about half** the ads come back with targeting; from a clean IP the same lookups succeed every time. The other ads keep every other field and carry `targeting: null`, and the run log tells you the exact count. To improve it, raise **Retries per request** (slower, costlier) or plug your own proxies into the Proxy section.
- Reach and spend come as **bands** (`1K-10K`), not exact numbers — that is how TikTok publishes them.
- TikTok caps a single search at **5,000 ads**. Split a big job by country or by shorter date ranges to go past it.
- Only ads that TikTok classifies as commercial content in the covered countries appear.
- Video URLs are signed and expire after a few hours. Download them soon after the run.
- TikTok withholds the creative file for a minority of ads. Those records still carry the advertiser, dates, reach and targeting, and are flagged with `creativeAvailable: false`.
- Expect roughly **1 ad per second** without targeting. The endpoint answers "system busy" often; the actor simply rotates its session and retries, which is why runs are steady rather than fast.

### Legal

This actor reads a **public transparency database** that TikTok is required to publish under the EU Digital Services Act. It collects no personal data and needs no login. You are responsible for how you use the exported data.

# Actor input Schema

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

Advertiser names or keywords. Each term is matched against both advertiser names and ad content, and searched in every country you select.

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

Which ad libraries to search. TikTok publishes this data for the EEA, the UK, Switzerland and Turkey only.

## `lastDays` (type: `integer`):

How far back to look, counting from today. Ignored when you set an exact date range below.

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

Optional exact start of the range, as YYYY-MM-DD. Overrides "Last N days".

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

Optional exact end of the range, as YYYY-MM-DD. Defaults to today.

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

Keep only video ads, only image ads, or both.

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

Newest first gives you what is running right now. Oldest first surfaces long-running evergreen ads, which are usually the proven winners.

## `includeTargeting` (type: `boolean`):

Fetch the targeting breakdown of every ad: audience size, age groups, genders, interests, languages, devices and impressions per country. Slower and charged at a higher rate, because it needs one extra request per ad.

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

Stop after this many ads in total, across all terms and countries. Your main cost control.

## `maxRequestRetries` (type: `integer`):

How many times to retry a request that TikTok answers with "system busy", each time from a fresh proxy IP. Lower it to fail fast, raise it for stubborn runs.

## `sessionCount` (type: `integer`):

How many independent sessions (each on its own IP) fetch targeting data at the same time. Higher is faster; lower is gentler on TikTok and on your proxy bill.

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

TikTok rate-limits single IP addresses aggressively. Residential proxies are strongly recommended and used by default.

## Actor input object example

```json
{
  "searchTerms": [
    "nike",
    "adidas"
  ],
  "countries": [
    "GB"
  ],
  "lastDays": 30,
  "dateFrom": "2026-01-01",
  "dateTo": "2026-03-31",
  "adFormat": "all",
  "sortBy": "newest",
  "includeTargeting": false,
  "maxItems": 1000,
  "maxRequestRetries": 6,
  "sessionCount": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every scraped ad: creative URLs, first and last shown dates, days running, estimated reach, advertiser details and - when enabled - the audience targeting breakdown.

# 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": [
        "GB"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("getdataforu/tiktok-ad-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": ["GB"],
}

# Run the Actor and wait for it to finish
run = client.actor("getdataforu/tiktok-ad-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": [
    "nike"
  ],
  "countries": [
    "GB"
  ]
}' |
apify call getdataforu/tiktok-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,getdataforu/tiktok-ad-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/pRl0oo1F8oDqPEaJb/builds/ZRaG01Fb7QU9OoHF1/openapi.json
