TikTok Ads Scraper - Ad Library by Keyword and Country avatar

TikTok Ads Scraper - Ad Library by Keyword and Country

Pricing

from $0.44 / 1,000 ads

Go to Apify Store
TikTok Ads Scraper - Ad Library by Keyword and Country

TikTok Ads Scraper - Ad Library by Keyword and Country

Scrape TikTok ads from TikTok's public ad library by keyword, advertiser, country or date. Each ad has the advertiser, caption, first and last shown dates, countries, a reach band, video, thumbnail, call to action and landing page. EEA and UK ads only, no US. $0.45 per 1,000 ads.

Pricing

from $0.44 / 1,000 ads

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

11

Total users

6

Monthly active users

4 days ago

Last modified

Categories

Share

Scrape TikTok ads from TikTok's public ad library, the Commercial Content Library: search by keyword, advertiser, country and date, and get one flat row per ad with who ran it, the caption, the first and last dates it was shown, the countries it ran in, the audience band TikTok publishes, the video and thumbnail, the button text and the landing page.

Read the coverage line before you plan anything around this. The archive exists because of EU and UK transparency rules, so it holds the EEA plus GB, CH, NO, IS and LI, and nothing before 2022-10-01. There is no United States edition of this library, and no spend or performance figures in it.

InputSearch terms, advertiser names, or links from library.tiktok.com/ads
OutputOne row per ad: advertiser, caption, first and last shown dates, countries, audience bands, video and thumbnail links, call to action and landing page
Ceiling20,000 ads per run, and 20 terms, 20 advertisers and 20 links
Account neededNone
Price$0.45 per 1,000 ads on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 11,000

🔍 What TikTok Ads Scraper does

Four ways to say what you want, and they combine in one run.

A keyword matches advertiser names and ad copy, so running shoes returns ads whose text mentions running shoes.

An advertiser name is looked up in the library's own register first, then that advertiser's ads are pulled. Typing a brand word like Nike picks up registered entities whose name starts with it, and the row keeps your wording in searchTerm.

A library link pasted straight from the site: the country, dates, advertiser, order and format already in the address are read back out and used as they are.

Countries on their own, with no search term, means the ads running in those countries.

📋 What data you get from each TikTok ad

What you getField
The library's own id, and the link back to the ad's pageadId, adDetailUrl
Who ran it, and who paid when a sponsor is namedadvertiserName, advertiserId, paidBy, advertiserRegistryCountry
The ad copycaption
First and last day it was shownfirstShownDate, lastShownDate
Where it ran, and which countries your search coveredcountriesTargeted, searchedRegions
Reach, audience size and impressions per country, as bandsuniqueUsersSeen, targetAudienceSize, impressionsByCountry
The creative: video, thumbnail and image linksvideoUrl, thumbnailUrl, imageUrls
Landing page, button text and campaign objectivelandingUrl, callToAction, advertisingObjective
Format and statusadFormat, adStatus
Age and gender targeting, where publishedtargetedAgeGroups, targetedGenders
Which of your terms, advertisers or links produced the rowsearchTerm

▶️ How to scrape TikTok ads

  1. Open TikTok Ads Scraper and click Try for free.
  2. Put your keywords into Search terms, or names into Advertiser names, or paste library links into Ad Library URLs.
  3. Set Ad target countries to the codes you care about, and a Shown from and Shown until date if the last 30 days is not the window you want.
  4. Set Maximum rows low, around 20, for the first run, then click Start.
  5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

Start it with the input empty and you get one labelled sample row and nothing else.

💰 How much does it cost to scrape TikTok ads?

$0.45 per 1,000 ads on the Free plan. Paid plans pay a little less: $0.445 on Starter, $0.44 on Scale and $0.435 on Business. On the free plan, the $5 Apify gives you each month covers about 11,000 ads.

You are charged per ad row delivered. Ads already seen earlier in the same run are dropped before that, so a creative matching two of your terms costs once. The sample row, every diagnostic row and a country code or date the library does not support are not charged.

📥 What you give it

{
"searchTerms": ["running shoes", "protein powder"],
"countries": ["DE", "FR", "IT"],
"dateFrom": "2026-07-01",
"dateTo": "2026-08-15",
"maxItems": 100,
"includeAdDetails": true
}
FieldDefaultWhat it is
searchTermsnone (the box holds running shoes)Keywords. Up to 20, and the row budget is split evenly between every target.
advertiserNamesnoneRegistered names like NIKE Retail B.V., or a brand word.
adLibraryUrlsnoneAddresses copied from the library site. Any other link gets an uncharged BAD_INPUT row.
countriesnone (the box holds DE)Two-letter codes, or all. Only these exist in the library: 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. Empty searches all of them.
dateFrom, dateTothe last 30 daysYYYY-MM-DD. Anything earlier than 2022-10-01 is moved forward to it.
maxItemsnone (the box holds 20)Total ads across every target, up to 20,000.
includeAdDetailsonFetches the per-ad transparency record. It is the only source of landingUrl, callToAction, advertisingObjective, advertiserRegistryCountry, countriesTargeted, targetAudienceSize and impressionsByCountry. Off is faster and leaves those null.
adFormatnone (the form starts at all)all, video, image or text.
adStatusnone (the form starts at all)all, active for still running, inactive for stopped.
sortBynone (the form starts at create_time,desc)Published date newest first is the order the library repeats and skips least. Last-shown and impression orders are there too.
proxyUrlsnoneOptional. Your own servers, as http://user:pass@host:port, used exactly as given.
sessionCookiesnoneNot needed, so leave it empty. The library is public and runs read it signed out. A session put here is only tried if the library refuses its public access, and it opens nothing a signed-out visitor cannot see. Anyone holding a session can act as that account, and you are responsible for using yours within the site's terms. The field is stored encrypted.

📤 What you get back

One flat row per ad, with the fields above. These are the ones that need reading:

FieldHow to read it
firstShownDate, lastShownDateDay granularity, ISO format.
uniqueUsersSeen, targetAudienceSize, impressionsByCountryBands, not numbers. TikTok publishes ranges.
videoUrl, thumbnailUrl, imageUrlsLinks only, signed and expiring. Download what you want to keep.
adStatusactive, inactive or rejected.
paidByFilled only when the library names a sponsor separately.
targetedAgeGroups, targetedGendersOnly what the archive publishes, which is not every ad.
searchedRegionsThe countries your search actually covered. Check it before you read a country breakdown.
detailsCompletetrue when the ad's own transparency record was read. false when it was asked for and did not come back, because the run reached its time limit while reading it or that one lookup failed, so the fields only that record holds are null on this row. null when includeAdDetails is off.

🧾 Reading the output

Three kinds of row can land in your dataset.

RowHow to spot itBilled
An adok: true and recordType: "ad"yes
The sample row_sample: true, written only when the input was emptyno
A diagnosticok: false, _diagnostic: true and an errorCodeno

Filter on recordType == "ad" and you have your data. charged: true marks a real ad row and false marks a sample or diagnostic one. Read it as the row type: it is stamped as the row is built, so it is not a receipt. Your run's own event count in Apify is the billing record.

CodeWhat it means
BAD_INPUTA country code that does not exist in this library, a date outside it, or a link the actor cannot read.
NO_RESULTSNothing matched. On an advertiser name it usually means no registered match, so try it as a keyword.
RATE_LIMITEDThe library kept answering "system busy" for that search. Worth a re-run with a narrower window.
NETWORKThe library was unreachable or answered badly.
TIME_BUDGETThe run ran out of time before reaching that target. The run ends as failed only when the time limit stopped it before any ad came back.
PROXY_INPUT_ADJUSTEDSomething you put in proxyUrls was unusable, so the run carried on without it.
CHARGE_ERRORA charge could not be recorded. A couple in a row stops the run.

💡 What people use it for

  • Watching what a rival brand is running right now in a given market, by advertiser name.
  • Pulling a category's creatives by keyword and reading the captions and calls to action together.
  • Tracking how long an ad stays up, using firstShownDate and lastShownDate across repeated runs.
  • Collecting landing pages for a set of advertisers to see where the traffic is being sent.

From one brand's ads to what people say about it, in two runs:

  1. Run this with the brand in Advertiser names and your markets in Ad target countries.
  2. Sort on firstShownDate and open the adDetailUrl of the newest ads to see the creative.
  3. Put the brand name into the Search queries box of TikTok Scraper to see the organic videos about it.

🚧 What it does not do

  • No United States ads. The archive covers the EEA plus GB, CH, NO, IS and LI, and nothing before 2022-10-01. This is the library's own scope.
  • No spend and no performance data. Reach and impressions come back as bands, because bands are what TikTok publishes.
  • A detail lookup that does not come back leaves fields null. landingUrl, countriesTargeted, advertiserRegistryCountry, targetAudienceSize, impressionsByCountry, targetedAgeGroups and targetedGenders can be null either because the archive has no value or because that one lookup did not come back, for instance when the run hit its time limit. Such an ad is still delivered and charged, marked detailsComplete: false.
  • An unsupported country next to a search term widens the search. Ask for a country the library does not have and the run searches every country it does have, with one uncharged BAD_INPUT row to tell you. Check searchedRegions on the rows before you read a country breakdown.
  • Media is linked, not downloaded. Those links are signed and expire.
  • 12 rows a page. A large maxItems is many round trips, so give a big run room.
  • Ordering by last shown repeats and skips ads, which is why published-date order is the starting point.
  • It is not an official TikTok tool. Dami's Studio is independent and is not affiliated with or endorsed by TikTok, or by any other company named on this page.

🧭 Which TikTok scraper do you need?

If you wantUse
Ads from TikTok's public ad libraryThis one
Facebook and Instagram ads from Meta's ad libraryMeta Ad Library Scraper
The ads a brand runs on Google, by domain or advertiserGoogle Ads Transparency Scraper
Products, prices and units sold on TikTok ShopTikTok Shop Scraper
The hashtags ranking in a country right nowTikTok Trending Hashtags
Videos posted under a hashtagTikTok Hashtag Scraper
A profile plus its newest videos, or a keyword searchTikTok Scraper
Comments under a videoTikTok Comments Scraper

❓ Questions people ask

Do I need a TikTok account or an ad account?

No. The library is a public transparency archive and the run reads it the way a signed-out visitor does.

Can I get US TikTok ads?

No. There is no US edition of this library, so nothing can pull US ads from it.

Why are some fields null on a row?

Either the archive has no value, or the per-ad record did not come back that time. detailsComplete tells them apart: false means it did not come back, so re-run that ad if a null matters.

How far back does the TikTok ad library go?

2022-10-01. Earlier dates are moved forward to it and you get an uncharged row telling you.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/tiktok-ads-scraper. Either way the run happens on your Apify account at the same price.

It is a public archive TikTok publishes to meet transparency rules, and a normal run reads it the way a signed-out visitor does: no account, nothing private. If the ads you collect name or show a person, that is personal data under GDPR and similar laws, so keep only what you need. TikTok's own terms still apply to what you do with it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the search, advertiser or link that misbehaved and the run ID. The errorCode on the diagnostic row usually names the problem on its own.