TikTok Ad Library Scraper
Pricing
Pay per event
TikTok Ad Library Scraper
Search TikTok's official DSA Commercial Content Library by advertiser name or keyword and export ad-creative rows — caption, video/cover URLs, shown dates, estimated audience band, and optional landing-page/CTA enrichment. EU/EEA + UK + Switzerland + Turkey coverage only.
Pricing
Pay per event
Rating
0.0
(0)
Developer
DevilScrapes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
🎯 What this scrapes
TikTok publishes a free, keyless Commercial Content Library to
satisfy the EU's Digital Services Act ad-transparency mandate. This
Actor searches it by advertiser name or keyword and returns one
structured row per matching ad — advertiser, caption, first/last shown
dates, estimated audience band, and creative URLs. It completes the
ad-transparency class alongside our google-ads-transparency,
linkedin-ad-library-scraper, and meta-ad-library-scraper Actors.
🔥 Features
- 🛡️ We open a real browser session to earn your search a seat, then reuse that trust (Firefox-fingerprint requests) for the rest of the run — never raw Python knocking on the door.
- 🔁 We retry with exponential backoff on
429 / 503and network errors, honouringRetry-After— up to 5 attempts per call. - 🧭 We follow TikTok's cursor pagination exactly — the opaque
search_idtoken from each response is echoed verbatim into the next request, never a guessed offset. - 🌐 Apify Proxy on every request, ready to escalate to residential if TikTok ever tightens up (it hasn't yet).
- 🧱 We isolate per-row failures — one malformed ad object is skipped and logged, the run keeps going.
- 💰 You pay only for ads that land. A search that matches nothing still succeeds — you're never charged for a failed run.
💡 Use cases
- Competitive intel — track a competitor's TikTok ad creative, captions, and rotation cadence over time.
- Paid-media benchmarking — compare estimated audience bands and creative formats across advertisers in your category.
- Brand protection — check whether your brand name or trademark shows up in someone else's TikTok ads.
- Creative research — pull real, live ad captions and hooks for inspiration before building your own campaign.
- Compliance / ad-transparency reporting — export a clean, structured record of an advertiser's EU-region TikTok activity.
⚙️ How to use it
- Click Try for free at the top of the page.
- Enter one or more Queries — advertiser name(s) or keyword(s), e.g.
["nike", "zara"]. - Optionally set Region (defaults to
"all"— every EU/EEA + UK + Switzerland + Turkey region TikTok supports). - Optionally set Date from / Date to (defaults to a trailing 30-day window).
- Set Max results per query.
- Click Start. Rows stream into the run's dataset as TikTok's cursor pages are followed, one independent loop per query.
- Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.
📥 Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
queries | array<string> | yes | — | Advertiser name(s) / keyword(s). One search per entry (1-200 chars each). |
region | string | no | "all" | "all" or a live TikTok support-region code (EU/EEA + UK + Switzerland + Turkey only — no US). |
dateFrom | string | no | 30 days before dateTo | ISO YYYY-MM-DD. |
dateTo | string | no | today | ISO YYYY-MM-DD. |
maxResultsPerQuery | integer | no | 500 | Cap per query across cursor pages (1-20,000). |
proxyConfiguration | object | no | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US"} | Apify Proxy configuration. |
Example input
{"queries": ["nike", "zara"],"region": "all","maxResultsPerQuery": 25,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }}
📤 Output
Every row is one matched ad.
| Field | Type | Notes |
|---|---|---|
ad_id | string | TikTok's internal ad ID. |
query_term | string | The query that produced this row. |
region | string | The region scope that produced this row. |
advertiser_name | string | Advertiser display name — the only advertiser identifier TikTok exposes (no numeric advertiser ID). |
ad_caption | string | null | Ad caption text. |
first_shown_date / last_shown_date | string | null | ISO-8601 UTC. |
estimated_audience | string | null | Estimated audience band, e.g. "100K-200K". |
spend | string | null | Reported spend band; empty/null for most ordinary (non-DSA-flagged) ads — never fabricated. |
impressions | integer | null | Reported impression count; 0 for most ordinary ads, null only if genuinely missing. |
video_url / cover_img | string | null | Primary creative video/cover-image URL. |
image_urls | array<string> | Additional creative image URLs, if any. |
ad_url | string | Direct TikTok Ad Library URL for this ad. |
scraped_at | string | ISO-8601 UTC timestamp this row was scraped. |
Example output
{"ad_id": "1873877803725954","query_term": "nike","region": "all","advertiser_name": "NIKE Retail B.V.","ad_caption": "Une rentrée signée Nike","first_shown_date": "2026-08-16T00:00:00+00:00","last_shown_date": "2026-09-05T00:00:00+00:00","estimated_audience": "100K-200K","spend": null,"impressions": 0,"video_url": "https://library.tiktok.com/api/v1/cdn/.../video/...","cover_img": "https://p16-common-sign.tiktokcdn.com/...","image_urls": [],"ad_url": "https://library.tiktok.com/ads/detail/?ad_id=1873877803725954","scraped_at": "2026-09-12T12:00:00+00:00"}
💰 Pricing
Pay-Per-Event — you pay only when these events fire:
| Event | USD | What it is |
|---|---|---|
actor-start | $0.20 | One-off warm-up charge — fires on the first delivered row, not at boot |
ad-result | $0.003 | Per ad row written to the dataset |
Example: 1,000 matched ads ≈ $3.20 total ($0.20 start + 1000 x $0.003). No subscription, no minimum, no card to start — Apify gives every new account free credit.
A run that delivers nothing costs you nothing. 🧾 The start fee is charged on the first row that actually reaches your dataset, so if TikTok blocks the run or your search matches no ads, your bill for it is $0.00.
Keep the RESIDENTIAL proxy default (with its US country pin) — both are load-bearing. 🛡️
This Actor mints its API token by loading the Ad Library the way a browser does, once per run.
From a datacenter exit that page simply never issues the request the token rides on, so the run
stops with a clear error instead of quietly returning nothing — we verified both sides in the
cloud on 2026-09-12. The proxy exit is also pinned to the US to match the browser session's
locale — a mismatched exit country is a fingerprint red flag that can stall the token mint. You
don't need to think about any of this; just don't override the proxy defaults to save a little
cost, because the run will fail rather than degrade.
🚧 Limitations
TikTok's Commercial Content Library covers **EU/EEA + UK + Switzerland
- Turkey only** — there is no US region, and this is a hard product
limit, not something this Actor can work around.
regionis validated live against TikTok's own support-regions list at the start of every run. Thetotalcount TikTok's search response returns is a display cap (commonly5000), not an exact match count — treat it as "5,000+", not precise.spend/impressionsare genuinely empty/0for ordinary commercial ads (TikTok only populates these for DSA-flagged categories like political/social-issue ads) — this Actor ships them as-is rather than inventing numbers. There is no numeric advertiser ID in either the list or detail response — only the advertiser's display name.
❓ FAQ
Does this need a TikTok account or API key?
No. TikTok's Commercial Content Library search API is free and keyless.
Why is there no US region?
TikTok built this product to satisfy the EU's DSA transparency mandate
— it genuinely only covers EU/EEA + UK + Switzerland + Turkey. This
Actor validates your region input against TikTok's own live
support-regions list and fails loud (before any search call) if you
pick one outside it.
What happens if my query matches nothing?
That query finishes successfully with zero rows and a status message naming it — you're not charged per-result for a failed search, and other queries in the same run are unaffected.
Can I search multiple advertisers in one run?
Yes — pass multiple queries. Each runs its own independent
cursor-pagination loop, so one query hitting a snag never stops the
others from finishing.
💬 Your feedback
Spotted a bug, hit a weird edge case, or need a field we don't ship yet? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.