# TikTok Commercial Content Library Ads Scraper (`datascraperes/tiktok-ads-commercial-library`) Actor

Scrape public TikTok ads from the Commercial Content Library without login or an API key. Search by country, keyword, advertiser, dates, ad type, status, reach and audience, then extract advertiser, targeting, captions, CTAs, landing pages and media URLs.

- **URL**: https://apify.com/datascraperes/tiktok-ads-commercial-library.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Categories:** Social media, Lead generation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 tiktok ad results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/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 Scraper | Commercial Content Library

Collect public TikTok ads from the **Commercial Content Library** and receive one structured Dataset item per available ad.

Search by country, keyword, advertiser, date, ad type, status, audience reach, age or gender. Optional ad details can include the advertiser, sponsor, targeting information, caption, call to action, landing page and public media links.

No TikTok account, login or TikTok API key is required. The Actor only collects information that TikTok makes publicly available in its Commercial Content Library.

### Pricing

The Actor charges **$0.001 per successfully saved ad** — equivalent to **$1 per 1,000 saved ads**.

You are not charged for:

- A search that returns no ads.
- Duplicate ads.
- Diagnostic or error records.
- An ad that was not accepted and saved in the Dataset.

The selected `maxAds` value is a hard upper limit for billable ad results. If the run reaches your Apify spending limit, it stops before saving another billable ad.

The Apify pricing panel may also show a small **Actor Start** event of `$0.00005` per run. This is separate from the `$0.001` ad-result price and is displayed before you start a run.

### What you can use it for

- Research competitors and brands advertising on TikTok.
- Discover active or recently published ads by market.
- Compare ad creatives, captions and calls to action.
- Find advertiser landing pages and public TikTok profiles.
- Study audience reach ranges and public targeting information.
- Build datasets for marketing, SEO, lead generation and campaign research.
- Monitor public ad activity across several countries or keywords.

### How to use the Actor

1. Select one or more countries in **Countries where to search**.
2. Add keywords, brands or advertiser names if you want a targeted search. Leave the field empty to browse the latest available ads.
3. Choose the filters that match your research.
4. Set `maxAds` to the maximum number of ads you want to save.
5. Leave **Fetch ad details** enabled when you want the additional advertiser and creative information.
6. Start the Actor and open the **Dataset** tab when the run finishes.

For a first run, use one country, one keyword, one page and a small ad limit such as `3` or `10`.

### Quick start input

```json
{
  "regions": ["ES"],
  "searchTerms": ["nike"],
  "maxAds": 10,
  "maxPages": 1,
  "includeDetails": true,
  "locale": "auto"
}
```

### Input options

#### `regions`

Countries or markets in which to search. Select one or more values. The default is `ES`.

The Actor currently supports:

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

You can select up to 20 countries in one run. When several countries and search terms are selected, the Actor searches every country/term combination and removes duplicates within each market.

#### `searchTerms`

Optional list of keywords, brands, products or advertiser names. Examples:

```json
["nike", "running shoes", "summer sale"]
```

Add up to 50 terms. Each term is searched separately for every selected country. Duplicate terms are removed automatically.

If the list is empty, the Actor searches the latest available ads for each selected country.

#### `advertiserBusinessIds`

Optional advertiser business IDs exposed by the Commercial Content Library. This is an advanced exact filter and can be combined with `searchTerms`.

```json
["123456789012345"]
```

#### `queryType`

Advanced public-library search mode. Keep the default value `1` for normal keyword, brand and advertiser searches. Other values from `0` to `10` are accepted for compatibility with future changes in the public library, but are not normally needed.

#### `startDate` and `endDate`

Optional inclusive dates in `YYYY-MM-DD` format.

- `startDate`: first date on which the ad was shown.
- `endDate`: last date on which the ad was shown.
- The maximum date range is 366 days.
- If omitted, the Actor uses a recent default window for the search.

Example:

```json
{
  "startDate": "2026-08-01",
  "endDate": "2026-08-18"
}
```

#### `sortType`

Controls the order in which ads are returned:

| Value | Meaning |
| --- | --- |
| `create_time,desc` | Newest published ads first. Default. |
| `last_shown_time,desc` | Ads shown most recently first. |
| `reach,desc` | Largest public reach range first. |

#### `adType`

Public ad type filter:

| Value | Meaning |
| --- | --- |
| `0` | All types. Default. |
| `1` | Video ads. |
| `2` | Image ads. |
| `3` | Text ads. |

#### `adStatus`

Public ad status filter:

| Value | Meaning |
| --- | --- |
| `0` | All statuses. |
| `1` | Active ads. Default. |
| `2` | Inactive ads. |

#### `ageRanges`

Optional audience age ranges. The available values are:

- `all`
- `13-17`
- `18-24`
- `25-34`
- `35-44`
- `45-54`
- `55+`

Example:

```json
{
  "ageRanges": ["18-24", "25-34"]
}
```

#### `reachRanges`

Optional public audience reach bands. Available values currently include:

- `all`
- `0-1K`
- `1K-10K`
- `10K-100K`
- `100K-200K`
- `200K-300K`
- `300K-400K`
- `400K-500K`
- `500K-600K`

TikTok publishes reach as an aggregated range, not as an exact number of individual users.

#### `gender`

Optional public audience gender filter:

| Value | Meaning |
| --- | --- |
| `ALL` | All genders. Default. |
| `MALE` | Male audience. |
| `FEMALE` | Female audience. |

#### `locale`

Controls the language used for available detail labels. It does not translate the original ad creative.

- `auto` — recommended. Uses the natural language associated with each selected country.
- Manual options: `es`, `en`, `de`, `fr`, `it`, `pt`, `nl`, `pl`, `sv`, `da`, `fi`, `no`, `cs`, `el`, `ro`, `hu` and `tr`.

With `auto`, examples include Spain `es-ES`, Germany `de-DE` and the United Kingdom `en-GB`. A manual language applies to all countries in the run.

#### `maxAds`

Maximum number of ad records saved across the complete run.

- Default: `100`.
- Minimum: `1`.
- Maximum: `10,000`.

This is the most important option for controlling both result volume and ad-result charges.

#### `maxPages`

Maximum number of result pages requested for each country/search-term combination.

- Default: `10`.
- Minimum: `1`.
- Maximum: `100`.

The public library currently returns up to 12 results per page, but the number available can vary by country, search term and time.

#### `includeDetails`

Whether to request the additional public information for each ad.

- Default: `true`.
- Set to `false` when you only need the basic search results and public links.

Details are best effort. If the ad is found but its details are temporarily unavailable, the ad remains in the Dataset and `detailError` explains the issue.

#### `saveErrors`

Whether to save a compact diagnostic record when a search or detail request cannot be completed.

- Default: `true`.
- Diagnostic records are not charged as ads.

### Results

The Actor creates one Dataset item for each successfully saved ad. The Dataset also contains compact diagnostic records when `saveErrors` is enabled.

#### Successful ad record

```json
{
  "success": true,
  "recordType": "ad",
  "source": "tiktok_commercial_content_library",
  "retrievedAt": "2026-08-18T10:20:30Z",
  "adId": "1872868559944962",
  "region": "ES",
  "searchTerm": "nike",
  "searchPage": 1,
  "advertiserName": "NIKE Retail B.V.",
  "advertiserBusinessId": null,
  "paidBy": null,
  "firstShownAt": "2026-08-07T00:00:00Z",
  "lastShownAt": "2026-08-17T00:00:00Z",
  "objective": null,
  "uniqueUsersReached": "400K-500K",
  "targeting": null,
  "caption": "Vuelta a clase, vuelta al entreno.",
  "callToAction": null,
  "landingPage": null,
  "tiktokProfile": null,
  "media": {
    "imageUrl": null,
    "videoUrl": null
  },
  "searchUrl": "https://library.tiktok.com/ads?...",
  "detailUrl": "https://library.tiktok.com/ads/detail/?ad_id=1872868559944962&region=ES",
  "detailFetched": false,
  "filters": {
    "region": "ES",
    "searchTerm": "nike"
  }
}
```

Optional fields can be `null` when TikTok does not publish them for a particular ad or when details were not requested.

#### Main output fields

| Field | Description |
| --- | --- |
| `adId` | Public TikTok Commercial Content Library ad ID. |
| `region` | Country/market used for the search. |
| `searchTerm` | Keyword or advertiser term that found the ad. `null` for an unfiltered latest-ads search. |
| `searchPage` | Result page on which the ad was found. |
| `advertiserName` | Public advertiser name when available. |
| `advertiserBusinessId` | Public advertiser business ID when available. |
| `paidBy` | Public payer or sponsor information when available. |
| `firstShownAt` | First public shown date/time when available. |
| `lastShownAt` | Most recent public shown date/time when available. |
| `objective` | Advertising objective when published by TikTok. |
| `uniqueUsersReached` | Aggregated public reach range. |
| `targeting` | Public targeting information when available. |
| `caption` | Ad text or caption. |
| `callToAction` | Public call-to-action label when available. |
| `landingPage` | Public destination URL when available. |
| `tiktokProfile` | Public TikTok profile or username when available. |
| `media.imageUrl` | Public image or cover URL when provided. |
| `media.videoUrl` | Public video URL when provided. |
| `searchUrl` | Link to the corresponding public library search. |
| `detailUrl` | Link to the public ad detail page. |
| `detailFetched` | Whether the optional detail request completed. |
| `detailError` | Explanation when the ad was found but optional details failed. |
| `filters` | Country and search term associated with the result. |

The Dataset view **TikTok ads** focuses on the fields most useful for analysis. Use the full JSON item when you need every available field.

#### Diagnostic records

When a search or detail request cannot be completed, the Actor can save a record similar to:

```json
{
  "success": false,
  "recordType": "diagnostic",
  "source": "tiktok_commercial_content_library",
  "retrievedAt": "2026-08-18T10:20:30Z",
  "errorCode": "HTTP_SEARCH_ERROR",
  "errorMessage": "The public library did not complete the request.",
  "region": "ES",
  "searchTerm": "nike"
}
```

Diagnostic records help explain partial results and are not charged as ad results.

### Run summary

After each run, open the **SUMMARY** record in the Key-value store. It includes:

- Selected countries and search terms.
- Applied filters and resolved languages.
- Number of searches and pages completed.
- Ads discovered, saved and skipped as duplicates.
- Number of errors.
- The reason the run stopped.

Common stop reasons:

| Stop reason | Meaning |
| --- | --- |
| `COMPLETE` | The requested searches finished normally. |
| `MAX_ADS` | The configured `maxAds` limit was reached. |
| `CHARGE_LIMIT` | The run reached its configured spending limit before another ad could be saved. |

### Common examples

#### Find active Nike ads in Spain

```json
{
  "regions": ["ES"],
  "searchTerms": ["nike"],
  "adStatus": 1,
  "maxAds": 100,
  "maxPages": 10,
  "includeDetails": true,
  "locale": "auto"
}
```

#### Compare a brand across several countries

```json
{
  "regions": ["ES", "FR", "DE", "GB"],
  "searchTerms": ["adidas"],
  "sortType": "last_shown_time,desc",
  "maxAds": 200,
  "maxPages": 5,
  "includeDetails": true,
  "locale": "auto"
}
```

#### Collect recent ads without a keyword

```json
{
  "regions": ["ES"],
  "searchTerms": [],
  "sortType": "create_time,desc",
  "maxAds": 50,
  "maxPages": 5,
  "includeDetails": false
}
```

#### Find large-reach video ads

```json
{
  "regions": ["GB"],
  "adType": 1,
  "reachRanges": ["100K-200K", "200K-300K", "300K-400K", "400K-500K", "500K-600K"],
  "sortType": "reach,desc",
  "maxAds": 100,
  "includeDetails": true
}
```

### Limitations and expectations

- The Actor collects public Commercial Content Library data, not private Ads Manager campaigns.
- TikTok decides which ads, fields and markets are publicly available at the time of the run.
- A maximum is an upper limit; the Actor may return fewer ads when the public library has fewer matching results.
- Reach is provided as an aggregated range, not an exact individual-user count.
- Optional fields may be empty for some ads.
- Public image and video URLs may expire or change. They are links, not permanent media storage.
- The Actor returns ad metadata and public links; it does not download creative files.
- TikTok may change its public library, filters or available fields over time.
- Results can vary by country, language and the time of collection.

### Frequently asked questions

#### Do I need a TikTok account?

No. The Actor is designed for public Commercial Content Library data and does not ask for TikTok credentials.

#### Do I need an official TikTok API key?

No. There is no TikTok API key field in the input.

#### Can I search by country?

Yes. Select one or more supported countries in `regions`. The country is also included in every result so that multi-market exports remain easy to analyze.

#### Can I search several keywords at once?

Yes. Add several values to `searchTerms`. The Actor runs each term for each selected country and keeps the search context in `searchTerm`.

#### Will I always receive the number selected in `maxAds`?

No. `maxAds` is a maximum, not a guarantee. The final number depends on the public results available for the selected country, filters and search terms.

#### What happens when no ads match?

The run finishes without billable ad results. If an actual request error occurs and `saveErrors` is enabled, the Dataset contains a diagnostic record explaining it.

#### What does `includeDetails` change?

With `true`, the Actor requests additional public advertiser, targeting and creative information. With `false`, it keeps the result focused on the basic library search data. Both modes charge only for successfully saved ad records.

#### Are reach values exact?

No. TikTok exposes aggregated reach bands such as `10K-100K` or `400K-500K`. The Actor preserves those public ranges and does not convert them into invented exact counts.

#### Are videos or images downloaded?

No. When TikTok provides public media URLs, they are returned as links. The Actor does not download or permanently store creative files.

#### Can I export the results?

Yes. Open the Dataset for the run and use Apify's export options to download JSON, CSV, Excel or another available format.

#### Is this an official TikTok product?

No. This is an independent Actor that reads public information from TikTok's Commercial Content Library. It is not affiliated with or endorsed by TikTok.

### Responsible use

Use the results lawfully and respect TikTok's terms, applicable privacy and marketing rules, and the rights of advertisers and other people represented in the public data. Do not use public information for prohibited, deceptive or unlawful activity.

When reporting a problem, include the Apify run ID, selected country, search term and the relevant diagnostic record. Do not include passwords, tokens or private credentials.

# Actor input Schema

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

Select one or more countries. The actor searches ads from each selected market; the technical country codes are handled automatically.

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

Optional public search terms. The CCL search box accepts brand, product and advertiser keywords. One search is run per term and region. Leave empty to browse the latest ads for the selected region.

## `advertiserBusinessIds` (type: `array`):

Optional advertiser business IDs exposed by the CCL advertiser link. This is an advanced exact filter and can be combined with the search term.

## `queryType` (type: `integer`):

Internal public CCL query type. 1 is the current keyword/advertiser search used by the website. Other values are accepted for future CCL changes but are less validated.

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

Inclusive UTC date in YYYY-MM-DD. Defaults to 30 days before endDate.

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

Inclusive UTC date in YYYY-MM-DD. Defaults to today.

## `sortType` (type: `string`):

Public CCL ordering: newest published, most recently shown or largest audience first.

## `adType` (type: `integer`):

Public CCL ad\_type value: 0 = all types, 1 = video, 2 = image, 3 = text. The numeric field remains open for future library values.

## `adStatus` (type: `integer`):

Public CCL ad\_status value: 0 = all statuses, 1 = active, 2 = inactive. The numeric field remains open for future library values.

## `ageRanges` (type: `array`):

Optional age targeting values exposed by the library. Use all, or 13-17, 18-24, 25-34, 35-44, 45-54 and 55+. The actor converts these labels to the public values used by CCL.

## `reachRanges` (type: `array`):

Optional reach bands exposed by the library. Use all, or exact public labels such as 0-1K, 1K-10K, 10K-100K, 100K-200K, 200K-300K, 300K-400K, 400K-500K and 500K-600K. New bands are passed through unchanged.

## `gender` (type: `string`):

Audience gender filter exposed by CCL.

## `locale` (type: `string`):

Automatic selects the natural language for each country. You can override it when you want all details in one language. This does not translate the original ad creative.

## `maxAds` (type: `integer`):

Hard total limit across all selected regions and search terms.

## `maxPages` (type: `integer`):

Pagination safety limit. The public CCL currently returns up to 12 results per search request/page.

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

Enrich each result with advertiser, dates, objective, reach, targeting, caption, CTA, landing page and public TikTok profile fields.

## `saveErrors` (type: `boolean`):

Save one compact diagnostic record when a query or detail cannot be collected.

## Actor input object example

```json
{
  "regions": [
    "ES"
  ],
  "searchTerms": [
    "nike"
  ],
  "advertiserBusinessIds": [],
  "queryType": 1,
  "startDate": "2026-08-01",
  "endDate": "2026-08-19",
  "sortType": "create_time,desc",
  "adType": 0,
  "adStatus": 1,
  "ageRanges": [
    "all"
  ],
  "reachRanges": [
    "all"
  ],
  "gender": "ALL",
  "locale": "auto",
  "maxAds": 3,
  "maxPages": 1,
  "includeDetails": true,
  "saveErrors": true
}
```

# Actor output Schema

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

Dataset records emitted by this Actor.

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

Filters, transport, pagination, deduplication and error counters.

# 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": [
        "ES"
    ],
    "searchTerms": [
        "nike"
    ],
    "advertiserBusinessIds": [],
    "queryType": 1,
    "startDate": "2026-08-01",
    "endDate": "2026-08-19",
    "sortType": "create_time,desc",
    "adType": 0,
    "adStatus": 1,
    "ageRanges": [
        "all"
    ],
    "reachRanges": [
        "all"
    ],
    "gender": "ALL",
    "locale": "auto",
    "maxAds": 3,
    "maxPages": 1,
    "includeDetails": false,
    "saveErrors": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/tiktok-ads-commercial-library").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": ["ES"],
    "searchTerms": ["nike"],
    "advertiserBusinessIds": [],
    "queryType": 1,
    "startDate": "2026-08-01",
    "endDate": "2026-08-19",
    "sortType": "create_time,desc",
    "adType": 0,
    "adStatus": 1,
    "ageRanges": ["all"],
    "reachRanges": ["all"],
    "gender": "ALL",
    "locale": "auto",
    "maxAds": 3,
    "maxPages": 1,
    "includeDetails": False,
    "saveErrors": True,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/tiktok-ads-commercial-library").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 '{
  "regions": [
    "ES"
  ],
  "searchTerms": [
    "nike"
  ],
  "advertiserBusinessIds": [],
  "queryType": 1,
  "startDate": "2026-08-01",
  "endDate": "2026-08-19",
  "sortType": "create_time,desc",
  "adType": 0,
  "adStatus": 1,
  "ageRanges": [
    "all"
  ],
  "reachRanges": [
    "all"
  ],
  "gender": "ALL",
  "locale": "auto",
  "maxAds": 3,
  "maxPages": 1,
  "includeDetails": false,
  "saveErrors": true
}' |
apify call datascraperes/tiktok-ads-commercial-library --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/tiktok-ads-commercial-library"
        }
    }
}

```

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/oTC2hRX8oROueadI6/builds/PDFeThaHgiJzmB6tF/openapi.json
