TikTok Ads Library Scraper — TikTok Creative Center Top Ads avatar

TikTok Ads Library Scraper — TikTok Creative Center Top Ads

Pricing

from $0.40 / 1,000 ads

Go to Apify Store
TikTok Ads Library Scraper — TikTok Creative Center Top Ads

TikTok Ads Library Scraper — TikTok Creative Center Top Ads

Scrape the TikTok Ad Library, TikTok's ads transparency archive: every ad an advertiser runs, with targeting, reach per country, landing page, payer and TikTok account. Plus TikTok Creative Center Top Ads with CTR curves. A TikTok ads scraper and ad spy for competitor ads. No login.

Pricing

from $0.40 / 1,000 ads

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Every ad an advertiser runs in TikTok's Ad Library, with its full record — the targeting (ages, genders, interests, audience size, languages, devices), reach per country and the age × gender breakdown, the landing page with its UTMs, the category, the objective, the CTA, who paid, and the advertiser's TikTok account. Pin an advertiser by name and get its own ads, not everyone who mentions it. Search keywords, a creator's branded posts, or paste any library URL, with every filter the library has. Plus the Creative Center's Top Ads — TikTok's best-performing ads worldwide, with the landing page, likes, comments, shares, the per-second CTR and retention curves and the Spotlight picks, in the same row shape. Follow a competitor on a schedule and get only its new ads. Same column names as our Google Ads Transparency Scraper, Meta Ad Library Scraper and LinkedIn Ad Library Scraper. No login, no cookies, proxies handled for you.

Why this scraper, not the other TikTok ad actors

  • It reads the library the way TikTok serves it. Of the TikTok ad actors we ran on one advertiser (2026-09-29), several came back with "0 rows, SUCCEEDED": the library refuses a search without its per-connection entry ticket (HTTP 421 "system busy"), refuses page 2 without the previous page's search id (HTTP 425), accepts each detail ticket once, and stops a connection after about 100 detail records. This Actor follows those rules, moves to a fresh connection before the limit, and a run that could not read the source ends PARTIAL or FAILED and says why — never green and empty.
  • The advertiser, not everyone who mentions it. A keyword finds every ad that uses the word; advertisers pins the advertiser itself. Give its name as TikTok registers it and the run takes every business id TikTok lists under exactly that name; give Name | id to pin one. Each row carries advertiser_id and advertiser_name, so the next run can use the pair.
  • Walked to the end, and said so. TikTok serves about 5,000 ads per query, then repeats its last page; a keyword's total stops at 5,000. The run splits the date window until each part is under the cap, walks each part in both directions (ties on the date reshuffle between pages), and the run summary says, per search, TikTok's own total, how many it listed and whether the walk is complete. On one UK advertiser (2025-10-01 to 2026-09-30) it returned 220 of TikTok's 221 ads, each with its detail record.
  • The whole record, not the list card. Each library row carries what the detail record publishes: targeting per country (age groups, genders), interests, video and creator interactions, custom audiences, languages, cities, devices, operating systems, the targeted audience size as numbers, reach per country and the age × gender breakdown where TikTok publishes it, landing page with its UTMs, category, objective, CTA, payer, the registered country, the advertiser's TikTok account with its followers, and — for ads TikTok removed — the removal reason.
  • Top Ads in the same rows. The Creative Center's Top Ads for any of its 28 countries and three periods, sorted by TikTok's seven orders, filtered by industry, objective, language, format and likes. Logged out TikTok serves 20 per list; topAdsSweep reads the list under every sort, objective, likes tier, format, industry and language and deduplicates (more than 100 of TikTok's ~130 for one country and period). The detail adds landing page, countries, comments and shares; topAdsMetrics adds the per-second CTR, conversion, click and retention curves and five percentiles. The CTR is TikTok's rank bucket (ctr_top_percent: 6 = "Top 6%"), not read backwards.
  • Monitoring with a change feed. onlyNewAds skips every ad an earlier run delivered — not returned, not charged — and brings back an ad whose last shown day, reach band, status or likes moved, marked change_type: changed. Every row carries first_seen_at, last_seen_at and times_seen; Top Ads carry their rank and previous_rank; includeEndedAds adds a free row for each ad a complete walk no longer lists.
  • What the ad is doing, as columns. tagAds returns typed tags — angle, CTA intent, tone, offer type, funnel stage, sentiment — each with its confidence, the same tags our LinkedIn and Meta actors return. analyzeAds writes the hook, offer, audience and strategy; ocrImageAds reads the words in image ads; transcribeVideos returns what the video says and its first three seconds. No API key of yours needed.
  • Counts, lookups and reports. resultType: counts returns TikTok's total per search from one call (a search with no ads is free; ready-made: Check which advertisers run TikTok ads). resultType: advertisers lists every business id TikTok has for a name, with its number of ads. includeAdvertiserReport adds TikTok's own advertiser report: where its ads ran, country by country, and how many it published each month.
  • Core columns shared with our Google, Meta and LinkedIn ads scrapers. creative_id, ad_url, advertiser_name, advertiser_id, body_text, destination_url, first_shown, last_shown (YYYY-MM-DD), days_shown, image_url and ad_format mean the same thing in all four, so a competitor's ads on four platforms stack in one sheet on those columns. The rest differ by platform (reach vs impressions, targeting names, TikTok's own status).

Who it's for

  • Performance marketers and media buyers — a competitor's live TikTok ads with the targeting they chose, where they run, how many people they reach, and the landing pages with their UTMs.
  • Agencies and creative strategists — the Top Ads in a client's industry with TikTok's own curves and percentiles, the long runners in the library, and typed tags for angle and offer — a creative brief from data.
  • Brands and brand-safety teams — every ad paid for in your name, which agency paid, which ads TikTok removed and why, and the creators posting branded content about you.
  • Researchers and compliance teams — the EU transparency record TikTok publishes per ad — payer, reach per country, targeting, removals — in columns, over time.

Quick start

Every ad one advertiser runs, with its detail

{
"advertisers": [
"Samsung Electronics GmbH"
],
"maxAds": 100
}

One advertiser pinned by name and id, in Germany and France, last 90 days

{
"advertisers": [
"Notion | 7377365644930662401"
],
"countries": [
"DE",
"FR"
],
"dateRange": "last-90-days",
"maxAds": 50
}

A keyword across every advertiser, list fields only (cheap)

{
"keywords": [
"skincare"
],
"includeDetails": false,
"maxAds": 200
}

Top Ads in the US for the last 30 days, with curves

{
"topAdsCountries": [
"US"
],
"topAdsPeriod": "30",
"topAdsSortBy": "ctr",
"topAdsMetrics": true,
"maxAds": 20
}

Which of these advertisers run ads, and how many

{
"advertisers": [
"Samsung Electronics GmbH",
"Notion"
],
"resultType": "counts"
}

Monitoring — only what appeared or changed since the last run

{
"advertisers": [
"Samsung Electronics GmbH"
],
"onlyNewAds": true
}

Output

One record per ad:

fieldmeaning
row_typead for an ad; commercial_content for a creator's branded post (creators); count for a resultType: counts row; advertiser_match for a resultType: advertisers row; advertiser for an advertiser report (includeAdvertiserReport); advertiser_profile, landing_page and hashtag for the free summaryRows; ended for an ad a complete walk no longer lists (includeEndedAds); not_found for an id TikTok no longer has.
surfacelibrary — TikTok's Ad Library (ads shown in the EU, EEA, Switzerland and the UK, with the transparency record); top_ads — the Creative Center's Top Ads (TikTok's best-performing ads, worldwide).
creative_idTikTok's ad id: the library ad id (16 digits) or the Top Ads id (19 digits). Unique per ad; the key for onlyNewAds.
ad_urlThe ad's page: the library's detail page or the Creative Center's Top Ads page.
ad_formatvideo or image (an image ad can hold several images).
creative_availableWhether TikTok shows the creative. An active ad can have its video and images withheld; removed ads have none.
advertiser_nameThe advertiser as TikTok registers it (library), or the brand name on a Top Ad (often empty there).
advertiser_idTikTok's business id of the advertiser (library ads). With advertiser_name it pins the advertiser in advertisers (`Name
advertiser_locationThe country the advertiser is registered in, as the library states it.
payerWho paid for the ad (the library's "Paid for by"), often an agency.
advertiser_tiktok_usernameThe advertiser's TikTok account, when the ad is linked to one.
advertiser_tiktok_nameThat account's display name.
advertiser_tiktok_urlThat account's profile.
advertiser_tiktok_followersThat account's followers, as a number (the library shows "276.7K").
advertiser_tiktok_avatar_urlThat account's avatar.
advertiser_tiktok_account_typeThe account type TikTok reports (BLUEV_BA = a verified business account).
creator_usernamecreators rows: the creator who posted the branded content.
creator_urlcreators rows: the creator's profile.
content_labelcreators rows: TikTok's commercial-content label code (1 or 2), as the library gives it.
body_textThe ad's caption (library: the ad text; Top Ads: the title).
hook_textThe caption's first sentence or line — what the viewer reads first.
hashtagsThe caption's hashtags, lower-cased, without #.
mentionsThe accounts the caption mentions, without @.
ctaThe call-to-action button as the ad words it ("Shop now"). Library detail only.
cta_typeThe CTA as one value across languages: shop, buy, learn_more, download, install, sign_up, book, contact, … other.
objectiveThe campaign objective: the library's advertising objective ("Reach") or the Top Ad's objective ("Conversions").
objectivesTop Ads: every objective TikTok lists for the ad.
categoryThe library's ad category ("Tech & Electronics", "News & Entertainment").
industryTop Ads: the industry, by TikTok's own name.
industry_idTop Ads: TikTok's industry id (topAdsIndustries takes it).
destination_urlWhere the ad sends the click, with the advertiser's UTM parameters kept.
landing_domainThe destination's domain.
image_urlAn image ad's first image, or a video ad's cover.
image_urlsAn image ad's images (signed links that expire at media_expires_at).
cover_urlA video ad's cover frame.
video_urlThe video (library: TikTok's link, which redirects to the CDN; Top Ads: the best rendition).
video_urlsTop Ads: every rendition, best first: quality ("1080p"), height, url.
video_idTop Ads: TikTok's id of the video file.
video_duration_sThe video's length in seconds.
video_widthTop Ads: the video's width in pixels.
video_heightTop Ads: the video's height in pixels.
media_expires_atWhen the signed media links stop working (UTC). downloadMedia stores copies that do not expire.
first_shownThe ad's first day shown (library). Null where TikTok gives an ad that never ran a placeholder (the moment of the query as both dates).
last_shownThe ad's last day shown so far (library).
days_shownDays from the first to the last day shown, both counted.
is_activeStill running, by TikTok's own status (tiktok_status) when the run knows it; otherwise last shown today or yesterday and not removed.
tiktok_statusTikTok's own status of a library ad: active or inactive, as its Ad Library filter lists it (TikTok serves the status as a filter, not a field; an ad last shown yesterday can be inactive). Null where the run could not tell.
launched_last_7_daysFirst shown less than 7 days ago.
launched_last_30_daysFirst shown less than 30 days ago.
long_runningShown for 30 days or more.
posted_atcreators rows: when the creator posted it (UTC).
audit_statusThe library's audit state: approved or removed.
is_removedTikTok removed the ad. The reason is in removal_reasons (detail).
removal_reasonsWhy TikTok removed the ad, in its words (library detail).
display_modeThe library's display mode of the ad (standard, enhanced).
reach_bucketUnique users reached, as the library's band ("10K-100K").
reach_minThe reach band's lower bound, as a number.
reach_maxThe reach band's upper bound, as a number (null for an open band such as "100K+").
impressions_by_countryReach per country, most first: country (ISO-2), impressions as TikTok writes it ("313K" or a band "1K-10K"), impressions_estimate as a number, impressions_min / impressions_max the band's bounds.
top_countryThe country with the most reach (library) or the Top Ads list's country.
countries_countHow many countries the ad was shown in.
regionsISO-2 codes of the countries the ad was shown in — the shape our Google, Meta and LinkedIn ads actors use.
audience_breakdownReach per country × age × gender where TikTok publishes it: country, age, gender, impressions (null where TikTok shows "-").
target_audience_sizeThe targeted audience's size, as the library's band ("21.8M-26.6M").
audience_size_minThe audience-size band's lower bound, as a number.
audience_size_maxThe audience-size band's upper bound, as a number.
targeting_agesAge groups targeted in any country (13-17 … 55+).
targeting_gendersGenders targeted in any country (female, male, unknown).
targeting_by_countryPer country: country, ages and genders targeted there.
targeting_interestsInterest categories targeted.
targeting_video_interactionsVideo-interaction categories targeted.
targeting_creator_interactionsCreator-interaction categories targeted.
targeting_custom_audienceWhether a custom audience was targeted.
targeting_custom_audience_excludedWhether a custom audience was excluded.
targeting_countriesCountries in the targeting settings.
targeting_citiesCities targeted.
targeting_provincesProvinces or regions targeted.
targeting_languagesLanguages targeted.
targeting_devicesDevice models targeted.
targeting_osOperating systems targeted.
targeting_spending_powerThe high-spending-power setting, when used.
video_views_bucketcreators rows: the post's views, as the library's band.
video_views_mincreators rows: the views band's lower bound.
video_views_maxcreators rows: the views band's upper bound.
rankTop Ads: the position in the list, in topAdsSortBy order (1 = first). Spotlight: the page's order.
top_ads_countryTop Ads: the country of the list the ad came from.
top_ads_periodTop Ads: the period of that list, in days (7, 30 or 180).
ctr_top_percentTop Ads: TikTok's CTR rank bucket, as a percentage — 6 means "CTR Top 6%". Lower is better; it is not a click-through rate.
likesTop Ads: likes.
commentsTop Ads: comments (detail).
sharesTop Ads: shares (detail).
cost_levelTop Ads: TikTok's budget tier for the ad (1 = low … 3 = high).
is_search_adTop Ads: shown in TikTok search.
sourceTop Ads: TikTok's source label for the ad (detail).
keyword_listTop Ads: keywords TikTok attaches to the ad (detail).
pattern_labelsTop Ads: TikTok's creative-pattern label ids (detail).
voice_overTop Ads: the video has a voice-over (detail).
highlight_textTop Ads: TikTok's own note on the ad — on Spotlight ads, why its creative team picked it.
keyframesTop Ads (topAdsMetrics): per-second curves ctr, cvr, clicks, conversions, retention, each a list of second, value (TikTok's relative values).
keyframe_highlightsTop Ads (topAdsMetrics): the seconds TikTok marks on each curve (ctr, cvr, …), a list of seconds per curve.
percentilesTop Ads (topAdsMetrics): the ad's percentile against other ads for ctr, cvr, clicks, conversions, impressions (0–1).
copy_lengthThe caption's length in characters.
text_languageThe caption's language by a word vote (ISO 639-1); null when too short to tell.
sentiment_scoreThe caption's sentiment, −1 to 1, from the AFINN word list — English captions only.
analysis_angletagAds: the persuasion angle (problem_solution, social_proof, scarcity, discount, feature, lifestyle, curiosity, education, comparison, brand, other).
analysis_cta_intenttagAds: what the ad asks for (purchase, signup, download, learn_more, contact, visit, watch, apply, book, other).
analysis_tonetagAds: the tone (playful, urgent, professional, friendly, luxurious, informative, emotional, bold, other).
analysis_sentimenttagAds: the caption's sentiment, −1 to 1.
analysis_offer_typetagAds: what is offered (discount, giveaway, app_or_game, entertainment, physical_product, free_tool_or_trial, event_or_webinar, product_announcement, … other).
analysis_funnel_stagetagAds: awareness, consideration or conversion.
analysis_confidencetagAds: the confidence (0–1) of each tag, by tag name.
analysis_hookanalyzeAds: the line meant to stop the scroll.
analysis_offeranalyzeAds: the concrete offer, or null.
analysis_audienceanalyzeAds: who the ad is written for.
analysis_strategyanalyzeAds: what the advertiser is doing with this ad, in one sentence.
ad_ocr_textocrImageAds: the words in an image ad's artwork.
transcripttranscribeVideos: what the video says.
transcript_languagetranscribeVideos: the spoken language (ISO 639-1).
hook_3stranscribeVideos: the words spoken in the first three seconds of speech.
speech_secondstranscribeVideos: seconds of speech in the video.
transcript_segmentstranscribeVideos: the transcript in timed segments (start, end, text).
media_filesdownloadMedia: the stored files — kind, key, url (does not expire), bytes, content_type, source_url, reused.
image_file_urldownloadMedia: the stored first image or cover.
video_file_urldownloadMedia: the stored video.
detail_statusok (the detail record is on the row), skipped (details off), not_found, or failed: … (not billed for details).
matched_queryThe search that found the row (the advertiser, keyword, creator, URL or Top Ads list).
claimed_countTikTok's own total for that search (library), or the Top Ads list's total.
claimed_count_is_cappedThe total is TikTok's 5,000 ceiling for a keyword: the real number is at least that.
scraped_atWhen the row was read (UTC).
first_seen_atMonitoring: the day a run of this search first saw the ad.
last_seen_atMonitoring: the last day a run saw it.
ended_atended rows: the day a complete walk no longer listed the ad.
times_seenMonitoring: on how many days a run of this search saw the ad.
previous_rankMonitoring, Top Ads: the ad's rank the last time it was delivered.
change_typeMonitoring: new, changed (delivered before, a watched field moved) or unchanged.
changed_fieldsMonitoring: which fields moved (last_shown, reach_bucket, audit_status, likes, ctr_top_percent).
run_tagYour runTag, on every row.
search_querycount and advertiser_match rows: the library page of that search.
has_adscount and advertiser_match rows: whether the search finds any ad.
exact_name_matchadvertiser_match rows: TikTok's name is exactly the name you gave.
report_country_shareadvertiser rows: TikTok's report of where the advertiser's ads ran — country, share (0–1).
report_ads_published_by_monthadvertiser rows: ads published per month — month, ads.
report_ads_publishedadvertiser rows: ads published in the window.
report_first_publishedadvertiser rows: the first day with a new ad in the window.
report_last_publishedadvertiser rows: the last day with a new ad in the window.
summary_ad_countSummary rows: ads counted.
summary_active_countadvertiser_profile: of those, still running.
summary_removed_countadvertiser_profile: of those, removed by TikTok.
summary_longest_daysadvertiser_profile: the longest run in days.
summary_formatsadvertiser_profile: ads per format.
summary_landing_domainsSummary rows: the landing domains.
summary_countriesadvertiser_profile: ads per country.
summary_distinct_copiesadvertiser_profile: distinct captions.
summary_ad_idsSummary rows: the ad ids counted.
summary_advertisershashtag rows: the advertisers using the hashtag.

Example record:

{
"row_type": "ad",
"surface": "library",
"creative_id": "1844346308991089",
"ad_url": "https://library.tiktok.com/ads/detail/?ad_id=1844346308991089",
"ad_format": "video",
"creative_available": true,
"advertiser_name": "Notion",
"advertiser_id": "7377365644930662401",
"advertiser_location": "United Kingdom",
"payer": "Notion",
"advertiser_tiktok_username": null,
"advertiser_tiktok_name": null,
"advertiser_tiktok_url": null,
"advertiser_tiktok_followers": null,
"advertiser_tiktok_avatar_url": null,
"advertiser_tiktok_account_type": null,
"creator_username": null,
"creator_url": null,
"content_label": null,
"body_text": "@Defender’s Boutique Camp was more than a retreat - it was a world of its own.",
"hook_text": "@Defender’s Boutique Camp was more than a retreat - it was a world of its own.",
"hashtags": null,
"mentions": [
"defender"
],
"cta": null,
"cta_type": null,
"objective": null,
"objectives": null,
"category": "News & Entertainment",
"industry": null,
"industry_id": null,
"destination_url": "https://www.tiktok.com/@notion/video/7551792476881751318?is_from_webapp=1&sender_device=pc&web_id=7554424558355465750&utm_source=tiktok&utm_medium=paid&utm_id=__CAMPAIGN_ID__&utm_campaign=__CAMPAIGN_NAME__",
"landing_domain": "tiktok.com",
"image_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/okPWCkwIiLBAaoCi2hACX0yRxpAAmBA0E8KufQ~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=3fa73c35&x-expires=1790784000&x-signature=KofWPhpCoCr2Lm6PG9MCxXwaob8%3D&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1",
"image_urls": [
"https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/okPWCkwIiLBAaoCi2hACX0yRxpAAmBA0E8KufQ~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=3fa73c35&x-expires=1790784000&x-signature=KofWPhpCoCr2Lm6PG9MCxXwaob8%3D&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1"
],
"cover_url": "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/okPWCkwIiLBAaoCi2hACX0yRxpAAmBA0E8KufQ~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=3fa73c35&x-expires=1790784000&x-signature=KofWPhpCoCr2Lm6PG9MCxXwaob8%3D&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1",
"video_url": "https://library.tiktok.com/api/v1/cdn/1790764331/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS8wZTQ3ODMwY2JkYWRmOWIyYjNjYjFjY2RiZDgwMTgzYi82YWJkMzk5YS92aWRlby90b3Mvbm8xYS90b3Mtbm8xYS12ZS01MWM3MTAtbm8vb29aUkN0ZUZJdlVMQ09rQWNBQWdySUFmYkVLUkdEQUVHZTdSNGcv/b3b2ff51-3545-4a5d-ae78-e2328d56ab8b?a=475769&bt=814&btag=e000b8000&bti=PDU2NmYwMy86&ft=.NpOcInz7Th23B4GXq8Zmo&l=2026093018321101F0A5CA4E082F289691&mime_type=video_mp4&rc=NzloZ2g6ZDk5NTRmODQ2N0BpM2lwZnE5cmVmNjMzODYzNEAwMTU1LzM1XzIxNi8vNDVhYSMvYGtvMmQ0Zl9hLS1kMC1zcw%3D%3D&signature=lKcTGI0By%2FyCgmuDqrJulCX7LOtLAj5XBo1Nxh81QJM%3D&vvpl=1",
"video_urls": [
{
"quality": null,
"url": "https://library.tiktok.com/api/v1/cdn/1790764331/video/aHR0cHM6Ly92NzcudGlrdG9rY2RuLmNvbS8wZTQ3ODMwY2JkYWRmOWIyYjNjYjFjY2RiZDgwMTgzYi82YWJkMzk5YS92aWRlby90b3Mvbm8xYS90b3Mtbm8xYS12ZS01MWM3MTAtbm8vb29aUkN0ZUZJdlVMQ09rQWNBQWdySUFmYkVLUkdEQUVHZTdSNGcv/b3b2ff51-3545-4a5d-ae78-e2328d56ab8b?a=475769&bt=814&btag=e000b8000&bti=PDU2NmYwMy86&ft=.NpOcInz7Th23B4GXq8Zmo&l=2026093018321101F0A5CA4E082F289691&mime_type=video_mp4&rc=NzloZ2g6ZDk5NTRmODQ2N0BpM2lwZnE5cmVmNjMzODYzNEAwMTU1LzM1XzIxNi8vNDVhYSMvYGtvMmQ0Zl9hLS1kMC1zcw%3D%3D&signature=lKcTGI0By%2FyCgmuDqrJulCX7LOtLAj5XBo1Nxh81QJM%3D&vvpl=1"
}
],
"video_id": null,
"video_duration_s": null,
"video_width": null,
"video_height": null,
"media_expires_at": "2026-09-30T16:00:00Z",
"first_shown": "2025-09-26",
"last_shown": "2025-10-03",
"days_shown": 8,
"is_active": false,
"tiktok_status": "inactive",
"launched_last_7_days": false,
"launched_last_30_days": false,
"long_running": false,
"posted_at": null,
"audit_status": "approved",
"is_removed": false,
"removal_reasons": null,
"display_mode": "standard",
"reach_bucket": "10K-100K",
"reach_min": 10000,
"reach_max": 100000,
"impressions_by_country": [
{
"country": "GB",
"impressions": "78K",
"impressions_estimate": 78000
}
],
"top_country": "GB",
"countries_count": 1,
"regions": [
"GB"
],
"audience_breakdown": null,
"target_audience_size": "10.6M-12.9M",
"audience_size_min": 10600000,
"audience_size_max": 12900000,
"targeting_ages": [
"18-24",
"25-34",
"35-44",
"45-54"
],
"targeting_genders": [
"female",
"male",
"unknown"
],
"targeting_by_country": [
{
"country": "GB",
"ages": [
"18-24",
"25-34",
"35-44",
"45-54"
],
"genders": [
"female",
"male",
"unknown"
]
}
],
"targeting_interests": [
"Music"
],
"targeting_video_interactions": null,
"targeting_creator_interactions": [
"Fashion & Beauty"
],
"targeting_custom_audience": false,
"targeting_custom_audience_excluded": null,
"targeting_countries": null,
"targeting_cities": null,
"targeting_provinces": null,
"targeting_languages": null,
"targeting_devices": null,
"targeting_os": null,
"targeting_spending_power": null,
"video_views_bucket": null,
"video_views_min": null,
"video_views_max": null,
"rank": null,
"top_ads_country": null,
"top_ads_period": null,
"ctr_top_percent": null,
"likes": null,
"comments": null,
"shares": null,
"cost_level": null,
"is_search_ad": null,
"source": null,
"keyword_list": null,
"pattern_labels": null,
"voice_over": null,
"highlight_text": null,
"keyframes": null,
"keyframe_highlights": null,
"percentiles": null,
"copy_length": 78,
"text_language": null,
"sentiment_score": null,
"analysis_angle": null,
"analysis_cta_intent": null,
"analysis_tone": null,
"analysis_sentiment": null,
"analysis_offer_type": null,
"analysis_funnel_stage": null,
"analysis_confidence": null,
"analysis_hook": null,
"analysis_offer": null,
"analysis_audience": null,
"analysis_strategy": null,
"ad_ocr_text": null,
"transcript": null,
"transcript_language": null,
"hook_3s": null,
"speech_seconds": null,
"transcript_segments": null,
"media_files": null,
"image_file_url": null,
"video_file_url": null,
"detail_status": "ok",
"matched_query": "Notion",
"claimed_count": 221,
"claimed_count_is_capped": false,
"scraped_at": "2026-09-30T10:32:09Z",
"first_seen_at": null,
"last_seen_at": null,
"ended_at": null,
"times_seen": null,
"previous_rank": null,
"change_type": null,
"changed_fields": null,
"run_tag": null,
"search_query": null,
"has_ads": null,
"exact_name_match": null,
"report_country_share": null,
"report_ads_published_by_month": null,
"report_ads_published": null,
"report_first_published": null,
"report_last_published": null,
"summary_ad_count": null,
"summary_active_count": null,
"summary_removed_count": null,
"summary_longest_days": null,
"summary_formats": null,
"summary_landing_domains": null,
"summary_countries": null,
"summary_distinct_copies": null,
"summary_ad_ids": null,
"summary_advertisers": null
}

Pricing

Pay only for what a run actually returns, with no start fee and no platform usage billed to you. Prices are per 1,000 and fall with your Apify plan:

per 1,000FreeStarterScaleBusiness
Ad (ad)$0.80$0.68$0.56$0.40
Ad detail record on that ad (ad_details)+$1.20+$1.02+$0.84+$0.60
Top Ads curves and percentiles (ad_metrics)+$2.00+$1.70+$1.70+$1.70
Count row (resultType counts or advertisers) (count)$10.00$8.50$7.00$5.00
Advertiser report (advertiser)$4.00$3.40$2.80$2.00
Typed tags on that ad (ad_tags)+$1.00+$0.85+$0.70+$0.50
Written analysis of that ad (ad_analysis)+$6.00+$5.10+$4.20+$3.00
Video transcript on that ad (ad_transcript)+$20.00+$17.00+$15.00+$12.50
Image text read on that ad (ad_ocr)+$2.00+$1.70+$1.40+$1.00
Stored image or cover (media_file)$4.00$3.40$2.80$2.00
Stored video (media_video)$20.00$17.00$15.00$14.00

An ad with its detail record is $2.00 per 1,000 on the Free plan and $1.00 on Business. Each fee is charged per row that actually carries the thing: a detail record that could not be read is delivered marked (detail_status) and not billed for details; a silent video is not billed a transcript; a file an earlier run stored is linked, not billed again; a search with no ads is a free zero. maxAds is exact and never overshot. Nothing is billed for a run that failed. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

Usage patterns

  • Follow a competitor weekly — Put its name (or Name | id) in advertisers, tick onlyNewAds, save it as a task and schedule it. The first run delivers the current set; every later run only what appeared or changed since. For the change feed, open the task's Integrations tab and add a webhook on "Run succeeded" (or the Slack or email integration): it receives the run's dataset, which holds only the new and changed ads. Ready-made: Monitor a competitor's new TikTok ads weekly.
  • Find the ads worth copying — minDaysRunning: 30 keeps the ads an advertiser has run for a month or more; topAdsCountries with topAdsSortBy: ctr gives TikTok's own best performers in a market. Add tagAds to see which angle and offer they use, transcribeVideos for the script. Ready-made: TikTok's top-performing US ads, transcribed and tagged.
  • Map a market — A keyword with countries, ages and reach, or Top Ads with topAdsIndustries and topAdsSweep. summaryRows adds one profile per advertiser, one row per landing page and one per hashtag. Ready-made: TikTok ads that reached 100K+ users in Germany and France.
  • Know who advertises under a name — resultType: advertisers with a name returns every business id TikTok lists for it, whether the name matches exactly, and how many ads each runs — then pin the one you want with Name | id.
  • Use a search you already set up — Set the filters on library.tiktok.com/ads or on the Creative Center's Top Ads page, copy the URL into startUrls. Every filter in it is kept: an advertiser, a keyword search, the "other commercial content" tab of a creator, a Top Ads list or one ad. A published Google Sheet or a text file with one URL per line works as well.
  • Compare against their Google, Meta and LinkedIn ads — Run the same competitor through our Google Ads Transparency, Meta Ad Library and LinkedIn Ad Library scrapers. The four outputs share their core columns (creative_id, ad_url, advertiser_name, advertiser_id, body_text, destination_url, first_shown, last_shown, days_shown, image_url, ad_format), so the rows stack in one sheet on those; the other columns are each platform's own.

Input configuration

fieldtypedefaultwhat it does
advertisersarray[]Each entry is one advertiser in TikTok's Ad Library: its name as TikTok lists it (Samsung Electronics GmbH), or the name with its business id (`Notion
keywordsarray[]Words searched across every advertiser's ads, as the library's search box does. Put a phrase in double quotes ("running shoes") for the exact phrase. TikTok's total for a keyword stops at 5,000; the run walks past it by splitting the date window.
creatorsarray[]TikTok usernames (vikaglam, @vikaglam or the profile URL): their posts in the library's "other commercial content" tab — branded posts with the commercial-content label. Read per country (countries, or all 32 when empty).
startUrlsarray[]URLs copied from the browser: a library search on library.tiktok.com/ads (an advertiser or a keyword search; every filter in it is kept), a library ad (/ads/detail/?ad_id=…), a creator on the "other commercial content" tab, a Creative Center Top Ads list or ad page, or the Top Ads Spotlight page. A text file, CSV or published Google Sheet with one URL per line works too (Link remote text file).
adIdsarray[]Ads to fetch again by id: library ad ids (16 digits, 1844346308991089) or Creative Center Top Ads ids (19 digits starting with 7), or their URLs. Each comes with its full record; an id TikTok no longer has comes back as a free not_found row.
searchesarray[]Several searches in one run, each with its own filters and cap. Each entry names one of advertiser, keyword, url or creator, plus any of countries, dateRange, startDate, endDate, timezone, adStatus, mediaType, ages, gender, reach, sortBy, maxAds. Example: `[{"advertiser": "Notion
resultTypeads / counts / advertisers"ads"counts answers "does this advertiser run ads, and how many" from one call per search; a search with no ads is free. advertisers looks names up: each business id TikTok lists for the name, whether it is an exact match, and its number of ads.
countriesarray[]Ads shown in these countries: the library covers the EU, EEA, Switzerland and the UK. Empty = all 32 in one search. Several are one search each, deduplicated (an ad shown in two is delivered once).
dateRangelast-7-days / last-30-days / last-90-days / last-year / custom"last-year"When the ad was shown, as the library's own date filter, in timezone. startDate / endDate win over this preset when you set them.
startDatestringYYYY-MM-DD. With an end date or alone (then the 12 months before the end date). Set dates win over dateRange.
endDatestringYYYY-MM-DD. A date after today is today.
timezonestring"UTC"The IANA time zone the date window is read in (Europe/Berlin, America/New_York): a day runs midnight to midnight there.
adStatusall / active / inactive"all"The library's own status filter. The library page shows active ads by default; this Actor returns all by default.
mediaTypeall / video / image"all"The library's ad-type filter.
agesarray[]Ads targeted at these age groups (the library's audience filter). Empty = any.
genderall / female / male"all"The library's audience gender filter.
reacharray[]Ads whose reach falls in these bands (the library's reach filter). Empty = any.
sortBynewest / oldest / created_newest / created_oldest / impressions_high / impressions_low"newest"The order ads come in when a cap cuts the list. A walk that reaches the end of the list delivers every ad whatever the order.
includeRemovedAdsbooleantrueRemoved ads stay in the library with their removal reason (is_removed, removal_reasons, on the detail). Off: dropped before any detail is read, and not billed.
minDaysRunninginteger0Keep ads shown for at least this many days (first to last shown day) — the long runners. 0 = all. Filtered on the list, before any detail.
onlyActivebooleanfalseKeep only the ads TikTok itself lists as active (its status filter; an ad last shown yesterday can be inactive) and not removed.
topAdsCountriesarray[]The Creative Center's Top Ads (TikTok's best-performing ads, worldwide) for these countries: one list per country, deduplicated. Setting one runs Top Ads; leave empty for the Ad Library only.
topAdsPeriod7 / 30 / 180"30"The Top Ads period.
topAdsSortByfor_you / ctr / like / impression / play_2s_rate / play_6s_rate / cvr"ctr"TikTok's own order of the list. for_you changes between sessions; ctr is stable. rank on each row is the position in this order.
topAdsIndustriesarray[]Creative Center industries by name (Apparel & Accessories, Games) or id. The 258 names are TikTok's own.
topAdsObjectivesarray[]Campaign objectives to keep.
topAdsLanguagesarray[]Ad languages to keep.
topAdsFormatall / video / image"all"TikTok's own format filter.
topAdsLikesall / top_20 / top_40 / top_60 / top_80 / top_100"all"TikTok's likes tier filter.
topAdsKeywordstringKeep Top Ads whose title or brand contains these words. TikTok answers keyword searches only to logged-in users, so the run reads the lists (with the sweep on) and matches the words itself.
topAdsSweepbooleanfalseLogged out, the Creative Center serves 20 ads per list. On: the run also reads the list under every sort, both directions, each objective, likes tier, format, industry and language, and deduplicates — more than 100 of TikTok's ~130 for one country and period. Each extra list is one call (about 64 per country).
topAdsSpotlightbooleanfalseAlso return the Spotlight: the ads TikTok's creative team hand-picked, with their note on why each works.
topAdsDetailsbooleantrueOn: each Top Ad carries its landing page, countries, comments, shares, objectives and source. Off: the list fields only.
topAdsMetricsbooleanfalseEach Top Ad also carries TikTok's per-second curves (CTR, conversion rate, clicks, conversions, retention) and its five percentiles. Ten calls per ad.
includeDetailsbooleantrueOn: the targeting (age, gender, interests, audience size, languages, devices…), reach per country and the age × gender breakdown, the landing page with its UTMs, category, objective, CTA, payer and the advertiser's TikTok account. Off: the list fields only (dates, reach band, caption, media) — cheaper and faster.
includeAdvertiserReportbooleanfalseOne advertiser row per business id the run met: TikTok's own report of where its ads ran (share per country) and how many it published each month.
downloadMedianone / images / all"none"TikTok's media links expire (media_expires_at). Store the files in the run's key-value store and get links that do not; a file an earlier run stored is linked, not fetched or billed again.
tagAdsbooleanfalseTyped tags from the caption and CTA: angle, CTA intent, tone, offer type, funnel stage and sentiment, each with its confidence (analysis_*). Same tags as our LinkedIn and Meta ads actors.
analyzeAdsbooleanfalseThe hook, the offer, who it is for and the advertiser's strategy, written by a model from the ad's words.
ocrImageAdsbooleanfalseThe words set in the artwork of image ads (ad_ocr_text), read by a vision model.
transcribeVideosbooleanfalseWhat the video says (transcript, its language, the first 3 seconds as hook_3s). A silent video is not billed.
openaiApiKeystringYour own key for analyzeAds, ocrImageAds and transcribeVideos, if you want the model usage on your account. Not needed: the Actor has its own.
summaryRowsbooleanfalseFree rows after the ads: one profile per advertiser (ads, still running, longest run, formats, domains, countries), one per landing page and one per caption hashtag.
outputFormatfull / compact"full"compact is for sheets and AI agents; billing is the same.
maxAdsinteger0Ads delivered in the whole run, exactly (0 = no limit). Never exceeded, and you are never billed for more.
maxAdsPerSearchinteger0Ads per advertiser, keyword, creator, URL or Top Ads list (0 = no limit).
onlyNewAdsbooleanfalseMonitoring: skip every ad an earlier run with the same searches delivered — not returned, not charged. An ad whose last shown day, reach band, status or likes changed comes back with change_type: changed.
includeEndedAdsbooleanfalseMonitoring: a free ended row for each ad an earlier run saw that a complete walk of the same search no longer lists.
stateStoreNamestringName of the memory onlyNewAds and includeEndedAds keep between runs. Empty = derived from the searches, so the same task always meets its own memory.
runTagstringYour own label, copied onto every row (run_tag).
resumeFromRunIdstringThe id of a run of this Actor with the same input that stopped early (timeout, abort): this run continues where it stopped, without delivering or billing its ads again.

FAQ

Why does advertisers not take a business id alone?

TikTok's library pins an advertiser by its registered name and its business id together: with the id and no name it answers every advertiser, with the id and another name it answers none (measured 2026-09-30). Give the name as TikTok registers it — the run finds its ids — or Name | id from a row's advertiser_name and advertiser_id, or paste the library URL of the advertiser's page.

Which countries does the library cover, and what about the US?

TikTok's Ad Library covers ads shown in the EU, EEA, Switzerland and the UK — 32 countries. Ads shown only elsewhere are not in it. The Creative Center's Top Ads cover 28 countries including the US, but only TikTok's top-performing ads, 20 per list logged out (more with topAdsSweep).

Why are some library rows without a video or images?

TikTok withholds the creative of some ads, active ones included, and removes the media of ads it took down. creative_available says which; is_removed and removal_reasons say when TikTok removed the ad.

How complete is an advertiser's list?

The walk runs to the end of TikTok's list, past its 5,000-row ceiling by splitting the date window, and reads the list in both directions because ads with the same date reshuffle between pages. The run summary compares what was listed with TikTok's own total per search and says complete true or false; claimed_count on every row is that total.

What is ctr_top_percent?

TikTok's CTR rank bucket from the Creative Center, as a percentage: 6 means the ad is in the top 6% by click-through rate. Lower is better. It is not a click-through rate, and some tools read it backwards.

What does a row cost me, and what if a detail fails?

Per ad, and per detail record read. A detail that could not be read is delivered marked (detail_status) and not billed for details. maxAds is exact. Nothing is billed for a run that failed.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/tiktok-ad-library-scraper').call({"advertisers": ["Samsung Electronics GmbH"], "maxAds": 100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/tiktok-ad-library-scraper').call(run_input={'advertisers': ['Samsung Electronics GmbH'], 'maxAds': 100})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/tiktok-ad-library-scraper --input '{"advertisers": ["Samsung Electronics GmbH"], "maxAds": 100}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~tiktok-ad-library-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"advertisers": ["Samsung Electronics GmbH"], "maxAds": 100}'

Support

apify@hyperbach.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.