# TikTok Ads Scraper (`lexis-solutions/tiktok-ads-scraper`) Actor

Find and scrape current and past ads on TikTok. Get video URL, dates and locations, impressions, and more. Download and analyze data from the TikTok Ads Library for competitive analysis.

- **URL**: https://apify.com/lexis-solutions/tiktok-ads-scraper.md
- **Developed by:** [Lexis Solutions](https://apify.com/lexis-solutions) (community)
- **Categories:** Social media
- **Stats:** 1,216 total users, 175 monthly users, 100.0% runs succeeded, 66 bookmarks
- **User rating**: 4.92 out of 5 stars

## Pricing

from $0.49 / 1,000 ads

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/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 Scraper

![banner](https://lexis-solutions-apify.fra1.cdn.digitaloceanspaces.com/banners/tiktok-ads.jpg)

### What is the TikTok Ads Scraper?

The TikTok Ads Scraper is designed to extract data from TikTok Ad Library. It enables users to gather information about ads displayed on TikTok. The scraper can be used for competitor analysis, ad copy brainstorming, and more.

[How to Scrape TikTok Ads at Scale Using TikTok Ad Library + Apify](https://youtu.be/wa2_FN37UKs)

### What data can the TikTok Ads Scraper extract?

The TikTok Ads Scraper can extract the following data from the TikTok Ad Library:

- Ad ID
- Ad text
- Ad impressions range
- Ad shown countries
- Impressions share by country (only EU countries)
- Advertiser name
- Advertiser ID
- TikTok Video URL

and more.

### What use cases does the TikTok Ads Scraper have?

- Ad copy brainstorming and inspiration for your own ads 🧠
- Competitor analysis and benchmarking of your ads 📊
- Advertiser research and analysis 🕵️‍♀️

### How to use the TikTok Ads Scraper

1. Create a free Apify account
2. Open TikTok Ads Scraper
3. Add a query to the input field, this could be a company name, domain, or a search string that appears in the ad
4. Click Start and wait for the results
5. Download the results in JSON, XML or CSV format or connect the actor to your backend via API

### 📥 Input

To run the actor, you can input a:

- **adIds** (optional) - An array of specific ad IDs to scrape. When provided, the actor will skip the search functionality and directly fetch the detail pages for these ads. Example: `["1848459287600130", "1820197122833570"]`

- **Query** - A query to search for ads. This can be a company name, domain, or a search string that appears in the ad.

- **Advertiser Name** - An advertiser name to search for ads.

- **startDate / endDate** (optional) - Date range to filter ads (use ISO format `YYYY-MM-DD`). If `startDate` is omitted, it defaults to 1 year ago; if `endDate` is omitted, it defaults to the current time. If `startDate` is later than `endDate`, the default range (1 year ago → now) is applied. If `endDate` is in the future, the current time is used instead.

- **timezone** (optional) - Timezone string (e.g., `Europe/London`). If left empty, the server's default timezone (UTC) is used.

- **sortBy** (optional) - How to sort search results. Defaults to `last_shown_date,desc`. Allowed values:

  - `last_shown_date,desc` — Last shown date: Newest to oldest
  - `last_shown_date,asc` — Last shown date: Oldest to newest
  - `create_time,desc` — Publication date: Newest to oldest
  - `create_time,asc` — Publication date: Oldest to newest
  - `impression,desc` — Unique users seen: High to low
  - `impression,asc` — Unique users seen: Low to high

- **quickSearch** (optional) - When set to `true`, the scraper will skip the detail page requests and return data directly from the search results. This is faster but will result in missing fields (see Output section for details). Defaults to `false`.

**Note:** If `adIds` is provided, the actor will ignore all other search parameters (`query`, `advertiserName`, etc.) and directly fetch the specified ads.

You can provide either `query`, `advertiserName`, or both. When both are set, the actor prioritizes `advertiserName` (it tries to resolve the advertiser and, if it cannot, falls back to using the advertiser name as the query). If you leave `query` empty, set `country` to a specific region (anything except `all`).

### 📤 Output

The results are stored in the default dataset associated with the actor. Each item is an ad, having the following format:

> **⚠️ Note on `quickSearch` mode:**\
> When `quickSearch` is enabled, the scraper skips detail page requests for faster execution. However, the following fields will be `null` or missing:
>
> - `adLandingUrl`
> - `advertiserId`
> - `advertiserName`
> - `advertiserTtUser`
> - `advertiserCountry`
> - `adImpressions`
> - `advertiserPaidForBy`
> - `adTotalRegions`
> - `targetingByLocation`
> - `targetingByAge`
> - `targetingByGender`
>
> Use `quickSearch: false` (default) to get complete data with all fields populated.

> **💡 Note:**\
> The following enum is used for `adtype`:
>
> | Type  | Value |
> | ----- | ----- |
> | text  | "1"   |
> | video | "2"   |
> | image | "3"   |

> **🚫 Note on removed/unavailable ads:**
> Each item includes a `status` field:
>
> - `"active"` — ad is live and all detail fields are populated.
> - `"unavailable"` — TikTok has removed the ad (e.g. for a terms violation) or hidden the advertiser block. The record still appears in the dataset so no IDs are silently dropped. Depending on what TikTok still exposes, an unavailable record may carry partial data: `adType`, `adStartDate`, `adEndDate`, `adImpressions`, `adTotalRegions`, `targetingByLocation`/`Age`/`Gender`, and the audit fields below are often still populated, while `advertiser*`, `adVideoUrl`, `adVideoCover`, and `adImageUrls` are typically `null` / `[]`.
>
> Three audit fields from the TikTok API are also surfaced for both states so you can introspect why an ad was flagged:
>
> - `auditStatus` — `"1"` for active ads; other values typically indicate a moderation action.
> - `sorAuditStatus` — secondary moderation status.
> - `rejectionInfo` — populated by TikTok when a removal reason is published (often `null` since TikTok notes it can take up to 24h).

```json
{
  "adId": "1848112963098658",
  "status": "active",
  "auditStatus": "1",
  "sorAuditStatus": "1",
  "rejectionInfo": null,
  "adTitle": "上海恩榕电子商务有限公司",
  "adType": "2",
  "adLandingUrl": "https://enroutejewelry.com/products/example",
  "adSpent": "",
  "adVideoUrl": "https://library.tiktok.com/api/v1/cdn/1764070053/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS9iYTBmZWU5MWMwMDg5NDI5OWYzNTRlMzNlZGJhMjMyMS82OTI1ZTcxMS92aWRlby90b3MvYWxpc2cvdG9zLWFsaXNnLXZlLTAwNTFjMDAxLXNnL29JUUJsNkR3RkNBNkRzYVhBTmNXQUJLRGlvdVFJUWdmZ3BWSWVFLw==/c012558d-3959-4439-b57b-155dc15e3e57?a=475769&bti=PDU2NmYwMy86&ch=0&cr=0&dr=1&cd=0%7C0%7C0%7C0&cv=1&br=1256&bt=628&cs=0&ds=1&ft=.NpOcInz7ThUvGQPXq8Zmo&mime_type=video_mp4&qs=0&rc=ZTozOGg8Njo7ZWRkZDQ8aUBpM2twZnE5cmdyNzMzODYzNEA0YWEvNmNhXmMxYmAzMmMyYSMvL2RvMmRjMDNhLS1kMC1zcw%3D%3D&vvpl=1&l=20251125192732E13A9A84FCD62ECFD6FF&btag=e000b0000&cc=13",
  "adVideoCover": "https://p21-ad-sg.ibyteimg.com/origin/tos-alisg-p-0051c001-sg/oMXNy0ERi4zqAi5AFBoEtwAWYevhALB0BIcvmA",
  "adImageUrls": [],
  "adStartDate": 1762473600000,
  "adEndDate": 1762992000000,
  "advertiserId": "7345893407476285441",
  "advertiserName": "上海恩榕电子商务有限公司",
  "advertiserTtUserId": {
    "username": "enroutejewelry",
    "display_name": "en route jewelry",
    "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-avt-0068-tx2/70a6fb0dfd97f5427d020b84a6693575~tplv-tiktokx-cropcenter:168:168.jpeg?dr=9638&refresh_token=ea157d56&x-expires=1764241200&x-signature=RTLSA82JbQ1L6oyG8VBrD%2Fj3vmw%3D&t=4d5b0474&ps=13740610&shp=a5d48078&shcp=8aecc5ac&idc=useast5",
    "follower_count": "177.5K",
    "profile_web_link": "https://www.tiktok.com/share/user/6795191399140623365?source=ad_review",
    "account_type": "VERIFIED_BA"
  },
  "advertiserLocation": "China",
  "adImpressions": "100K-200K",
  "advertiserPaidForBy": "BLUEVISION INTERACTIVE LIMITED",
  "adTotalRegions": 11,
  "adEstimatedAudience": "100K-200K",
  "targetingByLocation": [
    {
      "region": "FR",
      "impressions": "12K"
    },
    {
      "region": "AT",
      "impressions": "3K"
    },
    {
      "region": "NO",
      "impressions": "4K"
    },
    {
      "region": "CH",
      "impressions": "3K"
    },
    {
      "region": "IT",
      "impressions": "15K"
    },
    {
      "region": "DE",
      "impressions": "10K"
    },
    {
      "region": "BE",
      "impressions": "13K"
    },
    {
      "region": "GB",
      "impressions": "8K"
    },
    {
      "region": "DK",
      "impressions": "3K"
    },
    {
      "region": "PL",
      "impressions": "62K"
    },
    {
      "region": "NL",
      "impressions": "11K"
    }
  ],
  "targetingByAge": [
    {
      "region": "FR",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "AT",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "NO",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "CH",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "IT",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "DE",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "BE",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "GB",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "DK",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "PL",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    },
    {
      "region": "NL",
      "13-17": false,
      "18-24": true,
      "25-34": true,
      "35-44": false,
      "45-54": false,
      "55+": false
    }
  ],
  "targetingByGender": [
    {
      "region": "FR",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "AT",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "NO",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "CH",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "IT",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "DE",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "BE",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "GB",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "DK",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "PL",
      "female": true,
      "male": true,
      "unknown": true
    },
    {
      "region": "NL",
      "female": true,
      "male": true,
      "unknown": true
    }
  ]
}
```

### How many TikTok Ads can the TikTok Ads Scraper extract?

The TikTok Ads Scraper uses pagination to extract all ads from the TikTok Ad Library. The scraper can extract 12 ads per page.

You can control the number of pages to scrape by setting the `maxPages` input parameter.

**Notes:** TikTok limits the Ad Library to 300 pages (12 ads per page). Even if more results exist, the actor cannot retrieve beyond that cap because TikTok does not expose additional pages.

### Why use the TikTok Ads Scraper?

- ⚡️ **Fast** - The scraper is fast and efficient, allowing you to scrape ads in a programmatic way.

- 🤙 **Easy to use** - The scraper is easy to use and requires no coding knowledge. All you need to do is input the query you want to scrape and the scraper will do the rest.

- ☑️ **Well-Maintained** - The scraper is maintained by the Lexis Solutions team, ensuring that it is always up-to-date and working properly.

### FAQ

- **How to find a company's ads on TikTok?**

  To find a company's ads on TikTok, you can use the TikTok Ad Library. This tool allows you to search for ads by advertiser name, domain, or country.

- **How to search for ads on TikTok?**

  TikTok Ad Library allows you to search for ads by advertiser name, domain. You can also filter ads by date range and format. If you need to obtain the data programmatically, you can use the TikTok Ads Scraper.

- **What is the TikTok Ad Library?**

  The TikTok Ad Library is a website that allows users to view ads that are displayed on TikTok's advertising network. It also provides information about the advertisers who are running these ads.

- **What is the TikTok Ads Scraper?**

  The TikTok Ads Scraper is a web scraping tool designed specifically for TikTok Ad Library. This tool offers an effective way to mine valuable data from ads displayed on TikTok's advertising network.

- **Is Scraping TikTok Ads Legal?**

  Scraping public information from TikTok Ad Library is legal as long as you are not violating any terms of service or privacy policies. However, it is important to note that scraping ads can be considered a violation of the terms of service of some websites, so it is always best to check before scraping.

- **How much does it cost?**

  The cost for using the TikTok Ads Scraper is shown on the top of this page. You can also check the Apify Store page for more information.

### Need to scrape ads from Google?

👉 Check out our [Google Ads Scraper](https://apify.com/lexis-solutions/google-ads-scraper)

### Need to scrape ads from Bing?

👉 Check out our [Bing Ads Scraper](https://apify.com/lexis-solutions/bing-ads-scraper)

### Need to scrape ads from Reddit?

👉 Check out our [Reddit Ads Scraper](https://apify.com/lexis-solutions/reddit-ads-scraper)

### Need to scrape ads from TikTok?

👉 Check out our [TikTok Ads Scraper](https://apify.com/lexis-solutions/tiktok-ads-scraper)

***

👀 p.s.

Got feedback or need an extension?

Lexis Solutions is a [certified Apify Partner](https://apify.com/partners/find). We can help you with custom solutions or data extraction projects.

Contact us over [Email](mailto:scraping@lexis.solutions) or [LinkedIn](https://www.linkedin.com/company/lexis-solutions)

### Support Our Work 💝

If you're happy with our work and scrapers, you're welcome to leave us a company review [here](https://apify.com/partners/find/lexis-solutions/review) and leave a review for the scrapers you're subscribed to. It will take you less than a minute but it will mean a lot to us!

Image Credit: https://www.socialpilot.co/tiktok-marketing/tiktok-ads

# Actor input Schema

## `query` (type: `string`):

You can search for ads containing words in a specific order or ads containing words in any order. Use quotation marks if you're searching for ads containing words in a specific order. For example, “red shoe sale” will bring up search results for all ads that contain “red shoe sale.” Don't use quotation marks if you're searching for ads containing multiple words in any order.

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

The advertiser name to search for.

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

Maximum number of pages to crawl. Set to 0 to crawl all available pages automatically.

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

Start date of the search.

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

End date of the search.

## `timezone` (type: `string`):

Timezone of the search.

## `country` (type: `string`):

Country code to filter ads.

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

How to sort search results.

## `adIds` (type: `array`):

The ad IDs to get details for.

## `quickSearch` (type: `boolean`):

If true, the actor will partial information about ads to be as fast as possible.

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

Your proxy configuration from Apify

## Actor input object example

```json
{
  "query": "pikoya",
  "maxPages": 1,
  "sortBy": "last_shown_date,desc",
  "quickSearch": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "query": "pikoya"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lexis-solutions/tiktok-ads-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 = { "query": "pikoya" }

# Run the Actor and wait for it to finish
run = client.actor("lexis-solutions/tiktok-ads-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 '{
  "query": "pikoya"
}' |
apify call lexis-solutions/tiktok-ads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lexis-solutions/tiktok-ads-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/60AtqWgevwexQsFPw/builds/MIlc8vKSgGHncN3jY/openapi.json
