Find the Highest-Reach TikTok Ads in Any EU Country
Rank the TikTok ads that reached the most people in an EU country over any date range, with per-country reach, using the TikTok Ads Library Scraper.
The actor referenced in this article. Pay only for results delivered.
Which TikTok ads reached the most people in France last month, whoever ran them? Media planners ask it to size a market, creative teams ask it to see what wide-reach ads look like, and agencies ask it to find advertisers worth pitching. TikTok’s Ad Library can answer: its page lets you browse a country with no keyword and sort by unique users. What it does not do is export. You get a scrolling grid of thumbnails, and each reach figure sits behind a click.
Try it live: TikTok Ads Library Scraper: EU Ads, Targeting and Reach. Pay per result delivered. Failed and empty results are never charged.
The TikTok Ads Library Scraper runs the same browse and sort without a login and hands back the ranked list as rows, with the reach in each country when you want it.
What you get and who it is for
| Field | What it tells you |
|---|---|
unique_users_seen | Unique users reached, as the band the library shows (1M-10M) |
unique_users_min, unique_users_max | The same band as two numbers you can sort and filter |
unique_users_by_country | With details on: a rounded count per country, split by age and gender |
advertiser_name, paid_for_by | Who ran the ad and who paid for it |
ad_text, media_type, industry | What the ad was and which category TikTok filed it under |
first_shown_date, last_shown_date, days_shown | How long it ran |
ad_url | The ad’s page in the library, which does not expire |
Use it to answer “who buys reach in this market”, to build a swipe file of the ads most people actually saw, or to check whether a category leader is still running at scale. Agencies treating the ranking as a pitch list can take the advertiser names from it and pull contact details off each advertiser’s own site.
The input
{
"browseWithoutSearch": true,
"countries": ["FR"],
"dateFrom": "2026-09-01",
"dateTo": "2026-09-30",
"sortBy": "most_users",
"uniqueUsers": ["over_100k"],
"includeDetails": true,
"maxAdsPerSearch": 100
}
browseWithoutSearchis only used whensearchTermsandadvertisersare both empty. It lists every ad shown in the chosen countries and dates.sortByset tomost_usersputs the widest-reaching ads first. It only applies when browsing. With a search term, TikTok ranks by match instead, and the difference is real: in our keyword search for adidas, the ad with the biggest German reach came 16th of 20.uniqueUsersis the library’s own reach filter, with the bandsunder_10k,10k_100kandover_100k. Withmost_usersit trims the tail. Paired withsortByset tofirst_shown_newest, it finds new ads that have already passed 100K people.countriesis one filter for the whole search, so two codes mean ads shown in either country. For a ranking per country, run one country at a time.includeDetailsaddsunique_users_by_countryand the advertiser fields, at about 1.4 seconds per ad. Turn it off for a list that comes back several times faster: in the actor’s own test, the 200 widest-reaching German ads took 75 seconds with details off, led by Samsung, Subway, L’Oréal and Rossmann, each in the 1M to 10M band.dateFromanddateToset the window the ads were shown in.
What the output looks like
[
{
"ad_id": "1871321576463745",
"ad_url": "https://library.tiktok.com/ads/detail/?ad_id=1871321576463745",
"advertiser_name": "adidas AG",
"paid_for_by": "PHD INTERNATIONAL LIMITED",
"ad_text": "adidas Hyperboost Euphoria",
"media_type": "video",
"industry": "Apparel & Accessories",
"first_shown_date": "2026-07-30",
"last_shown_date": "2026-08-19",
"days_shown": 21,
"unique_users_seen": "1M-10M",
"unique_users_min": 1000000,
"unique_users_max": 10000000,
"unique_users_by_country": [
{ "country": "DE", "unique_users": "2.4M", "unique_users_approx": 2400000 }
],
"search": "adidas",
"countries_filter": "DE",
"position": 16
},
{
"ad_id": "1871323061862529",
"advertiser_name": "adidas AG",
"unique_users_seen": "1M-10M",
"unique_users_min": 1000000,
"unique_users_max": 10000000,
"unique_users_by_country": [
{ "country": "DE", "unique_users": "1.1M", "unique_users_approx": 1100000 }
],
"position": 13
}
]
These rows come from our keyword run for adidas in Germany on October 6, 2026, not from a browse run. A browse run returns the same fields, with search set to all ads. Both ads sit in the same 1M-10M band, so the band alone cannot order them. The per-country count can: 2.4M against 1.1M. Four of the 17 adidas AG ads in that run were in the top band, with German counts of 1.1M, 1.3M, 1.6M and 2.4M. Note the position values too. The biggest ad came 16th because a keyword search ranks by match, which is why this job uses browse mode.
Run it in Apify Console
- Open https://apify.com/themineworks/tiktok-ads-library-scraper and click Try for free.
- Clear the prefilled Search terms (keywords or advertiser names) field and leave Advertisers (exact names) empty.
- Tick Browse all ads (no search term).
- In Countries, replace the prefilled Germany with the one country you want.
- Set Shown from (YYYY-MM-DD) and Shown until (YYYY-MM-DD).
- Set Sort by to Most unique users first and Unique users reached to Over 100K, then set Max ads per search.
- Click Start, watch the Output tab, then click Export for CSV, JSON or Excel.
Run it from Python
pip install apify-client
import csv
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
COUNTRIES = ["DE", "FR", "ES", "IT"]
rows = []
for country in COUNTRIES:
run = client.actor("themineworks/tiktok-ads-library-scraper").call(run_input={
"browseWithoutSearch": True,
"countries": [country],
"dateFrom": "2026-09-01",
"dateTo": "2026-09-30",
"sortBy": "most_users",
"uniqueUsers": ["over_100k"],
"includeDetails": True,
"maxAdsPerSearch": 100,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item.get("_type") == "info":
continue # the run summary row, never billed
if item.get("removed"):
continue # removed ads hide the advertiser and media
here = next((c for c in item.get("unique_users_by_country") or []
if c.get("country") == country), {})
rows.append({
"country": country,
"users_in_country": here.get("unique_users_approx"),
"unique_users_seen": item.get("unique_users_seen"),
"advertiser_name": item.get("advertiser_name"),
"paid_for_by": item.get("paid_for_by"),
"ad_text": (item.get("ad_text") or "")[:80],
"first_shown_date": item.get("first_shown_date"),
"last_shown_date": item.get("last_shown_date"),
"ad_url": item.get("ad_url"),
})
# biggest per-country count first, then group by country (the sort is stable)
rows.sort(key=lambda r: r["users_in_country"] or 0, reverse=True)
rows.sort(key=lambda r: r["country"])
if not rows:
raise SystemExit("no ads matched these filters")
with open("tiktok_top_reach_by_country.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=list(rows[0].keys()))
writer.writeheader()
writer.writerows(rows)
for country in COUNTRIES:
print(country)
for r in [r for r in rows if r["country"] == country][:5]:
print(f" {r['users_in_country'] or 0:>10,} {r['advertiser_name']}")
Each country gets its own run, its own ranking and its own start fee. Sorting on the country’s own count, rather than the total band, matters for ads shown in many countries: an ad can sit in the 1M-10M band overall and still be small in the one country you care about.
Run it every month
Save the input as a task, open Schedules, and create a schedule with a cron expression such as 0 7 1 * * (07:00 on the first of each month). A task keeps fixed dates, so either update dateFrom and dateTo before each run or leave them empty for a rolling 365 days. If you want fixed calendar months without editing the task, run the Python script from your own scheduler and compute last month’s dates there.
For an alert instead of a ranking, set sortBy to first_shown_newest, keep uniqueUsers at over_100k, tick Only new ads (for schedules) and run it weekly with 0 7 * * 1. Each run then returns only big ads it has not sent you before. Send results to a Google Sheet with Apify’s Google Sheets integration, to Slack through Make, Zapier or n8n, or to your own endpoint with a webhook.
What it costs
You pay per ad delivered, the same with details on or off: $1.69 per 1,000 ads on the Bronze plan, $1.39 on Silver, and $1.09 on Gold, Platinum and Diamond, plus a flat $0.005 start fee per run.
Four countries, 100 ads each, once a month is 400 ads: about $0.68 on Bronze plus $0.02 in start fees for the four runs. Ads seen twice in a run and ads whose details TikTok will not serve are never charged, and a run that finds nothing costs only the start fee.
Limits worth knowing
- Up to 5,000 ads per search. That is the most the library lists for one search. For a deeper list, split by country or use narrower date windows.
- Reach is a band plus a rounded count. The library never gives an exact number. Per-country counts are rounded (2.4M), and small numbers are hidden.
- Removed ads can rank high. The library keeps removed ads with their reach but hides the advertiser and the media. In the actor’s own browse of Germany, a removed ad came sixth. The script above skips them; keep them if you study enforcement.
- 33 countries only. The library covers the EU and EEA, Switzerland, the United Kingdom and Turkey. Ads shown only elsewhere are not in it.
- Media links expire. Video and cover links stop working after some hours, so save creative soon after the run. Keep
ad_urlfor anything long term.
Related
Explore the scraper referenced in this article: inputs, outputs, and pricing, then run it on Apify.
Frequently asked questions
Why does Sort by have no effect on my search? +
Sort by only applies when you browse without a search term. With a keyword or an advertiser name, TikTok ranks the ads by how well they match, the same way the library page does.
How exact is the reach figure? +
The library gives a band, such as 1M-10M, which the actor also returns as unique_users_min and unique_users_max. With details on, each country gets a rounded count such as 2.4M, which is enough to order ads inside one band.
Can I rank several countries in one run? +
The Countries list is one filter for the whole search, so a run with DE and FR returns ads shown in either. For one ranking per country, run each country on its own, as the Python script in this guide does.
How far back can I look? +
About a year. Leave Shown from empty and the run covers the 365 days before the end date. The library search does not accept a start date before August 1, 2023.
See a Competitor's TikTok Ad Targeting and Reach in the EU
Pull every TikTok ad a competitor ran in the EU, with interests, age groups, audience size and reach by country, using the TikTok Ads Library Scraper.
See Every LinkedIn Ad a Competitor Is Running, With Impressions
List a competitor's LinkedIn ads with landing pages, run dates, impressions by country and targeting, using the LinkedIn Ad Library Scraper. No login.
Benchmark LinkedIn Post Engagement Across Company Pages
Compare reactions and comments per post across LinkedIn company pages, scaled by follower count, with the LinkedIn Company Posts Scraper. No login.
Export Every Image and Caption From Instagram Carousel Posts
Export every slide image link, slide type and caption from Instagram carousel posts to a CSV, by profile or by post link, with Instagram Post Scraper.