Ad Library Monitor: Facebook, Google & TikTok Ads
Pricing
from $0.80 / 1,000 watch item checkeds
Ad Library Monitor: Facebook, Google & TikTok Ads
Ad library monitor for competitors' ads on Facebook, Instagram, Google and TikTok: new and stopped ads with first and last shown dates, text, links to creatives and landing pages, read from each platform's public ad library. Only your Apify account needed.
Pricing
from $0.80 / 1,000 watch item checkeds
Rating
0.0
(0)
Developer
CleanPull
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Features
Share
This ad library monitor watches competitor ads in the platforms' public ad libraries: the Google Ads Transparency Center (search, YouTube and display ads, any country), the Meta Ad Library (Facebook and Instagram, any country) and TikTok's ads library (ads shown in the EU, the UK and Switzerland). Give it competitors' brand names or domains and get the ads they run. Nothing to set up beyond your Apify account: no tokens, no developer apps. Every ad comes with its first and last shown dates, whether it is active, its library page and, where the library gives them, its text, title, call to action, landing page and a link to the creative. Schedule it and every run says which ads are new and which stopped since the last one. An ad counts as stopped only after two runs in a row find it inactive or gone. Run it once, on a schedule or through the API.
How to monitor competitor ads
- Open Ad Library Monitor on Apify and go to its input form.
- Enter competitors' brand names or domains in Advertisers, one per line (or words in ad text in Keywords).
- Pick the Platforms (Google, Meta, TikTok) and, if you like, up to 5 Countries. Leave Active ads only on for the ads running now.
- Start the run. Open the Ads view to read each ad's Platform, Advertiser, Status, First shown, Last shown, Text and Landing page, with In the library to open it.
- To watch competitors, give it a Watchlist name, turn on Changes only, save it as a task and schedule it daily. The New and stopped ads view then lists each new ad, and each stop once two runs agree.
What the ad library monitor gives you
- "Tell me when a competitor launches new ads." Put their brands in a watchlist, turn on Changes only and schedule it daily: you get each new ad with its first shown date, and a change row for it.
- "Which of their ads stopped?" A stop is confirmed on the second run that reads the advertiser in full without the ad active, so one missed sighting never reads as a stop.
- "What creatives are they running right now?" All active ads per advertiser, newest shown first, with the format (text, image, video), a link to each creative and the library page to open it.
- "Which small advertisers keep paying for ads on this product?" A keyword with Days running (at least) 35 and One row per advertiser lists the advertisers whose ads have run five weeks or more, on Meta (with the store each links to) and on TikTok in Europe (with how many ads TikTok's library lists for each account, a rough size, and the widest reach of their ads).
- "Who advertises on a topic in Europe?" Keywords search Meta's and TikTok's libraries for ads that use them, from any advertiser.
- "Feed a digest or an AI agent." Compact JSON with the same fields on every platform, a field picker, and a dataset view per job.
Ad library sources
| Platform | How it is read | Which ads | Watch by |
|---|---|---|---|
| Google Ads Transparency Center | Directly | Every verified advertiser's search, YouTube, display and Shopping ads, in any country | Brand name (its advertiser accounts), domain (ads that point to it), advertiser id |
| Meta Ad Library | Through our ad library service (a third-party API, ScrapeCreators) | Facebook, Instagram, Messenger and Audience Network ads, in any country | Brand name (the brand's pages), domain or keyword (ads that mention it), page id |
| TikTok ads library | Through the same service | Ads shown in the EU, the UK and Switzerland (TikTok's public library) | Brand name (its business accounts), domain or keyword |
The Meta and TikTok data is provided by a third-party API that reads the platforms' public ad libraries; CleanPull holds the account and its key (never in your input, logs or results). Each page it returns (30 Meta ads, 12 TikTok ads) is a library request on your bill.
How each platform is read
- Google: a brand name is matched to its advertiser accounts (Gymshark → Gymshark Ltd, Gymshark USA Inc and two more), then their ads are read newest shown first, 40 a page. Google gives the last day each ad was shown, so an ad shown in the last 3 days is active. Requests are spaced 1.5 s apart, from the run's own address. When Google declines a run (a captcha), that run's Google items are read through the ad library service instead, so the run still completes.
- Meta: the brand's ads from the Meta Ad Library, in each country chosen (or all), active ones by default, 30 a page, with Meta's own active flag, start date and last date shown. A brand name keeps the pages named for it (others that carry the name are left out and counted); a domain or keyword finds every page's ads that mention it; a page id reads that page exactly.
- TikTok: the brand's business accounts in TikTok's ads library (Gymshark → GYMSHARK LTD), 12 ads a page, each asked for by its id so every page stays on it. The account TikTok lists ads of is read first, then the brand's other accounts until Ads per watch item is reached; an account that lists no ads is passed over (the notes name it). Only an account named for the brand (the name alone, or followed by a legal form or market such as Ltd or USA Inc) is read; accounts whose names only start with it ("BOMBAS GENS" for Bombas, people's handles) are left out and counted in the run notes. TikTok's name suggestions sometimes come back empty, or with only an account that lists no ads: the accounts the watchlist read ads from before are tried, then the suggestions are asked once more; if still nothing, the notes say which accounts were read and the next run asks again. Each ad comes with its caption, first and last shown dates and reach. An ad shown in the last 7 days counts as active, so a TikTok stop is reported only after an ad has gone a week unshown and two runs agree (TikTok's library dates are not yet proven to update daily). The library covers the EU, the UK and Switzerland as a whole, so countries do not narrow it.
In tests from Apify's servers, Google returned ads for every brand and domain tried (Allbirds, Gymshark in the US, UK, Germany and France, gymshark.com with 532 active ads, bombas.com), Meta and TikTok returned Gymshark's ads with text, media links and dates, and watchlists read twice showed no false changes.
Ad library data accuracy
- Stopped means stopped. An ad remembered as active that a run finds inactive, or misses on a read that covered every active ad, is counted once in the run summary; it is reported as stopped when the next run agrees. A read cut short by Ads per watch item never counts an unread ad as stopped, and a read that finds no ads at all, or loses more than half of the active ads at once, counts no stops (it looks like a failed read; the run notes it). An ad not found counts only when the read used the same filters as the run that remembered it: a read with Days running (at least) never counts a missing ad (it reads only the older ones), and a watchlist run with Days running (at least) or with Active ads only off keeps its own memory, apart from the same watchlist's default runs. A TikTok read counts a missing ad only when TikTok listed every ad of the account (it stops paging short of large advertisers' totals).
- New means new. After the first run, an ad is new when the watchlist has not seen it and its platform start date is after the last run (a day of grace: TikTok dates by day, and libraries list some ads a little late). An old ad that only now came into view is added to memory quietly, not reported as new.
- A block is never an empty result. A refusal, a rate limit or a service outage is named in the run summary with the reason, and the platform's other watch items are not tried in that run. Captchas are never solved. Nothing that failed is charged.
- Only links, never files. Creatives are linked where the library gives a link (Google's image previews, Meta's images and videos, TikTok's videos; these addresses expire after a while); nothing is downloaded or stored. The
adUrlof every ad opens it in the platform's own library. - Businesses only. Advertisers are pages and business accounts; no personal data of individuals is read.
- Billed once. Each watch item read is billed its check and its library requests, and each delivered ad or advertiser row once; rows already delivered are never charged twice, even after a restart.
Ad library monitor input
| Field | Key | What it does |
|---|---|---|
| Advertisers | advertisers | Brand names or domains, one per line; each is checked on every platform chosen |
| Keywords | keywords | Optional. Words in ad text (Meta and TikTok) |
| Google advertiser ids | googleAdvertiserIds | Optional. Exact advertisers: AR… ids or Transparency Center addresses |
| Meta page ids | metaPageIds | Optional. Exact pages: page ids or Ad Library addresses with view_all_page_id=… |
| Platforms | platforms | google, meta, tiktok (default all) |
| Countries | countries | Optional. Up to 5 two-letter codes, each read separately on Google and Meta; empty is anywhere |
| Active ads only | activeOnly | Only ads running now (default on). Off: stopped ads too (Meta lists stopped non-political ads only for the EU) |
| Ads per watch item | maxAdsPerTarget | Ads read per watch item and platform each run (default 100, up to 1,000) |
| Days running (at least) | minDaysRunning | Optional. Only ads running at least this many days (35: proven ads). Meta and TikTok; younger ads are free |
| One row per advertiser | oneRowPerAdvertiser | One row per advertiser and watch item instead of per ad (default off) |
| TikTok account size | tiktokAccountSize | Optional, with One row per advertiser. TikTok advertiser names get the account's ad count free without it; keyword and domain items get none, as TikTok's keyword answers carry no account id |
| Changes only | changesOnly | After the first run, only new ads and confirmed stops (plus the ad rows of the new ads) |
| Watchlist name | monitorName | Runs with the same name share their memory of seen ads (default default) |
| Max cost per run (USD) | maxRunCostUsd | Optional. The run stops before charging past this amount, for scheduled runs without a spending limit of their own; what was not read is read in full on the next run |
| Fields | fields | Optional. Only these fields in each row (recordType always stays) |
| Watch items at a time | maxConcurrency | Watch items read at once (1 or 2, default 2) |
| History store | stateStoreName | The key-value store that keeps each watchlist (default: its own store, cleanpull-ad-library-monitor); pick one when you run with a scoped API token |
A watch item is one line on one platform: "Allbirds" with Google and Meta chosen is two watch items. A run checks up to 200 watch items.
Example inputs
A competitor watchlist on Google, checked daily for changes:
{"advertisers": ["Allbirds", "Gymshark", "bombas.com"],"platforms": ["google"],"countries": ["US"],"changesOnly": true,"monitorName": "competitors"}
The same brands on Meta (US) and TikTok, newest 30 ads each:
{"advertisers": ["Allbirds", "Gymshark"],"platforms": ["meta", "tiktok"],"countries": ["US"],"maxAdsPerTarget": 30,"changesOnly": true,"monitorName": "competitors-social"}
Everything an advertiser runs on Google, active or not:
{"googleAdvertiserIds": ["AR01371945870127267841"],"activeOnly": false,"maxAdsPerTarget": 1000}
Ad library monitor output
Rows are told apart by recordType: ad rows, free change rows, and with One row per advertiser, advertiser rows. Dataset views: Ads, New and stopped ads, Advertisers and Overview.
Example rows
An ad row (Meta, from a run on 2026-10-15):
{"recordType": "ad","platform": "meta","advertiser": "Gymshark","advertiserId": "129669023798560","adId": "1082781854356123","adKey": "c8ee6a86fae0ad6b67051abc4f2bbc0632d65a936bb525b74e62caad4283f4db","status": "active","active": true,"firstShown": "2026-10-01T07:00:00.000Z","lastShown": "2026-10-14T07:00:00.000Z","firstSeen": "2026-10-15T18:32:33.313Z","text": "The pieces everyone’s talking about. Shop our best sellers now 👀","title": "Shop Best Sellers","mediaType": "image","mediaUrl": "https://scontent-phl2-1.xx.fbcdn.net/v/t39.35426-6/829004198_3661677960646258_6377294838161671042_n.jpg?…","cta": "Shop now","landingUrl": "https://www.gymshark.com/collections/must-have","countries": ["US"],"publisherPlatforms": ["facebook", "instagram", "audience_network", "messenger", "threads"],"reach": null,"adUrl": "https://www.facebook.com/ads/library?id=1082781854356123","watch": "Gymshark","watchType": "advertiser","firstRun": true,"checkedAt": "2026-10-15T18:32:33.313Z"}
A Google ad row, from a run on 2026-10-15:
{"recordType": "ad","platform": "google","advertiser": "Allbirds Inc","advertiserId": "AR01371945870127267841","adId": "CR06031181514438344705","adKey": "0476abec7da5a0db288873742d7aa5dfe6a217cf23070cd5ebfadb45a0e30157","status": "active","active": true,"firstShown": "2026-02-12T18:33:36.000Z","lastShown": "2026-10-15T00:18:38.000Z","firstSeen": "2026-10-15T02:07:47.759Z","text": null,"title": null,"mediaType": "text","mediaUrl": "https://tpc.googlesyndication.com/archive/simgad/7226910236503050294","cta": null,"landingUrl": null,"countries": [],"publisherPlatforms": null,"reach": null,"adUrl": "https://adstransparency.google.com/advertiser/AR01371945870127267841/creative/CR06031181514438344705?region=anywhere","watch": "Allbirds","watchType": "advertiser","checkedAt": "2026-10-15T02:10:49.852Z"}
status is new (first seen since the last run and started since then), active, or inactive (with Active ads only off). firstShown and lastShown are the library's dates; firstSeen is when this watchlist first saw the ad.
What each platform fills
| Field | Meta | TikTok | |
|---|---|---|---|
text, title | not given (the text is inside the image) | the ad's body and title | the ad's caption, in both (when it has one) |
mediaType, mediaUrl | text, image or video; the preview image where Google gives one as an image (see below) | image or video, and its address | video or image, and its address |
cta, landingUrl | not given | the call to action and the landing page | not given (TikTok's library search has neither) |
countries | the countries searched | the countries searched | not given (the EU, the UK and Switzerland) |
publisherPlatforms | not given | facebook, instagram, messenger, audience_network, threads | tiktok |
reach | not given | Meta's reach estimate, when it gives one | estimated audience ("10K-100K") |
Google gives a preview image only for part of its ads: Shopping, video, and many image and text ads come as a preview Google draws with a script in its page (in the recorded Allbirds US page, 12 of 15 image ads, 4 of 15 text ads and all 10 video ads), so their mediaUrl is null; adUrl opens them. TikTok's library search gives no landing page, call to action or countries for an ad (only its detail page does, one request per ad).
Change rows
A change row (free), from the second run on. This one is from 2026-10-15, 3 minutes after the first run, before the start-date check came in (0.2.x): today an ad first shown more than a day before the last run, like this one, is added to memory quietly instead of being reported as new.
{"recordType": "change","change": "new","platform": "google","advertiser": "Allbirds Inc","adId": "CR10446175794693668865","adKey": "0e1be3de6440249add466215fa05a991ba99bf009ed9ae2115b43f2e23596561","firstShown": "2026-10-12T22:14:37.000Z","lastShown": "2026-10-15T01:40:25.000Z","text": null,"adUrl": "https://adstransparency.google.com/advertiser/AR01371945870127267841/creative/CR10446175794693668865?region=anywhere","watch": "Allbirds","watchType": "advertiser","since": "2026-10-15T02:07:47.759Z","checkedAt": "2026-10-15T02:10:49.852Z"}
Proven advertisers
Days running (at least) (minDaysRunning) keeps only ads that started at least that many days ago: every ad's start date is checked before any row, on Meta and TikTok. Meta's library is asked for those ads directly (by date), so they take no more pages than any read. TikTok's library has no date filter or sort: younger ads are skipped as they come (about 3 in 4 of a large advertiser's ads), so a TikTok watch item then reads at most 3 times the pages it would otherwise take. TikTok's keyword search lists the most recently shown and newest ads first, so a broad keyword can come back with no ad old enough within those pages (skincare with Days running (at least) 35, on 2026-11-04: every ad on its first page had started in the last three weeks); a brand name, read by its account, reaches its long-running ads more often. Younger ads, and ads without a start date, are left out and never charged, and they do not count toward Ads per watch item (the run notes say how many pages were read and how many ads were younger). The library requests are charged as usual. A read with Days running (at least) never reports an ad as stopped for not being found. Google is read as before (its Transparency Center has no keyword search). With One row per advertiser (oneRowPerAdvertiser), each watch item gives one row per advertiser instead of per ad, charged as one ad, ready for a store lookup (Meta keyword gymshark, Days running (at least) 35, from the recorded answer used in the tests):
{"recordType": "advertiser","platform": "meta","advertiser": "Gymshark","advertiserId": "129669023798560","landingDomain": "gymshark.com","landingUrl": "https://www.gymshark.com/collections/must-have","adsKept": 2,"earliestFirstShown": "2026-07-02T07:00:00.000Z","daysRunning": 104,"sampleAdUrl": "https://www.facebook.com/ads/library?id=1082781854356123","watch": "gymshark","watchType": "keyword","checkedAt": "2026-10-15T02:00:00.000Z"}
TikTok proven advertisers
TikTok's library search gives no landing page, so a TikTok advertiser row has no store to look up (landingDomain is null). Its closest size signal is the account itself: accountAdsInLibrary is how many ads TikTok's library lists for the advertiser's account (the last year of ads shown in the EU, the UK and Switzerland). A shop with a handful of ads reads very differently from a brand with tens of thousands (in the recorded answers: BOMBAS GENS 2, GYMSHARK LTD 23,378; TikTok's own count for a large account varies between reads, so take it as an order of magnitude). Advertiser names (advertisers) get it free with One row per advertiser, with or without TikTok account size: the read of the brand's account answers with that count, so no extra request is made. It is taken only from an answer that is that account's alone (asked by its id, or TikTok's answer for the name when TikTok resolved the name to that account and every ad in it is that account's), and set only on that account's row; a row whose account gave no such answer has accountAdsInLibrary: null. Keyword and domain items get no size: TikTok's keyword answers carry no account id (none for skincare on 2026-11-04), so TikTok account size (tiktokAccountSize) has nothing to ask, makes no request and charges nothing; the size is null with a run note. To size a brand, watch it as an advertiser name. Should a keyword answer carry account ids, TikTok account size asks each advertiser once by its id: one library request each ($0.0035 on Bronze, $0.007 on the Free plan; at most 30 per watch item, about $0.105 on Bronze and $0.21 on Free), only for advertisers that get a row (with Changes only, those with a new ad), the longest-running first; the rest, and any lookup that fails, have accountAdsInLibrary: null and a run note. If the ad library service asks us to slow down, the lookups end there: the remaining sizes are left empty with a run note and the ads are delivered. A refused key or no credits still stop TikTok for the run. Every advertiser row, on every platform, also carries maxReach: the widest reach figure among its kept ads, as the library gave it (TikTok's estimated audience band, Meta's reach estimate where Meta gives one). TikTok keyword leggings with account ids, Days running (at least) 35, from the recorded answer shapes used in the tests:
{"recordType": "advertiser","platform": "tiktok","advertiser": "BOMBAS GENS","advertiserId": "7670905082032160769","landingDomain": null,"landingUrl": null,"adsKept": 2,"maxReach": "100K-1M","accountAdsInLibrary": 2,"earliestFirstShown": "2026-06-01T00:00:00.000Z","daysRunning": 135,"sampleAdUrl": "https://library.tiktok.com/ads/detail/?ad_id=9002","watch": "leggings","watchType": "keyword","checkedAt": "2026-10-14T14:00:00.000Z"}
landingDomain is the site most of the advertiser's ads link to. Change rows are left out in this mode; an advertiser found by two watch items has a row for each.
Change types and run summary
change is new (its ad row comes with it) or stopped (with the last sighting). RUN_SUMMARY in the key-value store gives the outcome (COMPLETE, PARTIAL, NO_CHANGES, EMPTY, FAILED), per watch item the advertisers matched, ads read, active, new, stopped, missing once, requests and whether every active ad was read, the charges, and every watch item that could not be read, with the reason.
Pricing
| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Watch item checked (one platform, per 100 ads read: 1 up to 100, 2 up to 200) | $1.00 | $1.00 | $0.90 | $0.80 |
| Ad (a delivered ad row) | $1.50 | $1.50 | $1.35 | $1.20 |
| Library request (a page of 30 Meta or 12 TikTok ads, or of Google ads when Google declines the run, or one TikTok account sized) | $7.00 | $3.50 | $3.25 | $3.00 |
Per 1,000. Each run also has a $0.00005 start fee. Change rows are free. A watchlist of 10 competitors on Google checked daily with Changes only is about 300 checks a month ($0.30 on the Free and Bronze plans), plus the new ads ($1.50 per 1,000). The same 10 on Meta and TikTok at 30 ads each add 1 Meta and 3 TikTok library requests per competitor a day: about 1,200 requests a month ($4.20 on Bronze, $8.40 on the Free plan), and 600 more checks ($0.60). With Changes only, a day with nothing new still bills each watch item's check and its library requests. The first run delivers every active ad as the baseline (up to Ads per watch item each).
Limits
- Meta and TikTok come through a third-party API (ScrapeCreators) that reads the public libraries; if it is down or slow, those items are named in the run summary and read on the next run.
- TikTok: the EU, the UK and Switzerland only (TikTok publishes its ads library for those markets). There is no ad text beyond a caption, no call to action or landing page, no likes, comments, shares or spend (the library's search gives a reach band, not engagement), and countries do not narrow the search. Stops are reported only after a week unshown.
- Meta's stopped ads (Active ads only off) are listed for ads that reached the EU; outside the EU, Meta's library keeps only political and social-issue ads once they stop. Running ads are listed in every country.
- Google gives no ad text for image and video ads (it is in the creative) and no landing page; its library lists verified advertisers only. Google may occasionally decline a run (it answers with a captcha, mostly when runs follow each other within minutes); that run's Google items are then read through the ad library service (charged as library requests) and the run completes.
- Large advertisers: with more active ads than Ads per watch item, the first ads the library returns are read, and stops are not reported for that item (a stop needs a full read). Raise Ads per watch item to cover them; each Meta or TikTok page is a library request.
- A brand name on Meta keeps the pages whose name is the brand's; give a page id to watch a page with another name. Nothing needs or uses a sign-in to a personal account.
- Nothing found: when no watch item could be read, and each was missing (an advertiser name with no match) or left at the time limit, the run still succeeds, with one free
recordType: "unreadable"row per item giving thereason; nothing is charged. When other watch items were read, the missing ones are listed inRUN_SUMMARYwith the reason instead. A run near its time limit stops starting watch items, delivers what it read and lists the rest with the reason. A run that read nothing because a platform blocked every item endsPARTIAL(the next run tries again). A run that read nothing because of a service failure fails, and so does one whose items mix blocked and missing ones (no free rows then), unless items were left at the time limit, which ends itPARTIAL.
FAQ
How much does competitor ad monitoring cost per competitor per day?
On the Free and Bronze plans, one competitor on Google costs $0.001 a day for its check (up to 100 ads read; $0.002 up to 200), plus $0.0015 for each ad row delivered. Meta and TikTok add a library request per page: 30 Meta ads are one request ($0.0035 on Bronze, $0.007 on Free), and 30 TikTok ads are 3 requests of 12 ($0.0105 on Bronze, $0.021 on Free). The first run delivers every active ad as the baseline: 100 Google ads cost $0.151. With Changes only, a day with nothing new costs only the checks and library requests ($0.001 per competitor on Google; on a day Google declines the run, its items are read through the ad library service and each page is a library request too, $0.0035 on Bronze and $0.007 on Free); each new ad adds $0.0015, and change rows are free. With Days running (at least), younger ads are free, but every page read is still a library request. A watch item that fails or is blocked is never charged, and higher Apify plans pay less (see Pricing above).
How often should I check competitor ads?
Daily suits most watchlists; weekly is enough for slow advertisers. New ads appear from the second run (the first is the baseline). A stop needs the platform to show the ad inactive first (Google: not shown for 3 days; Meta: its active flag; TikTok: not shown for 7 days), then two runs in a row to agree. Keep one set of filters per Watchlist name: runs with Days running (at least) or with Active ads only off keep a memory of their own.
What is the difference between first shown, last shown and first seen?
firstShown and lastShown are the library's own dates: when the platform says the ad started and was last shown. firstSeen is when this watchlist first saw the ad. status is new only for an ad the watchlist had not seen that also started since the last run; an older ad that only now came into view is active.
Why is an ad's text, creative or landing page missing?
- Google:
text,title,ctaandlandingUrlare null; Google gives no ad text (it is in the creative) and no landing page. - Google previews:
mediaUrlis null for ads Google draws with a script (Shopping, video and many image and text ads);adUrlopens them. - TikTok:
cta,landingUrlandcountriesare null, and an advertiser row'slandingDomainis null; TikTok's library search gives neither. - Reach:
reachis filled only where Meta gives an estimate or TikTok an audience band. - Account size:
accountAdsInLibraryis null for TikTok keyword and domain items, and for an account without an answer of its own. - Media links: creative addresses expire after a while;
adUrlalways opens the ad in the library. - No stops reported: a read cut short by Ads per watch item, or a read with Days running (at least), never reports a stop.
Which platforms and countries does it support?
The Google Ads Transparency Center and the Meta Ad Library in any country, and TikTok's ads library for ads shown in the EU, the UK and Switzerland. Countries takes up to 5 two-letter codes, each read separately on Google and Meta; empty is anywhere. Meta lists stopped non-political ads only for the EU.
Can I use the ad library monitor through the API?
Yes. Start runs through the Apify API or an API client, and read the dataset through its Ads, New and stopped ads, Advertisers and Overview views, or the RUN_SUMMARY record with the outcome, the counts per watch item, the charges and every watch item that could not be read. Fields (fields) trims each row to the keys you need.
Does it work with Google Sheets, Make, Zapier or Claude?
Yes. Apify's integrations send each run's results to Google Sheets, Make, Zapier, webhooks and other tools, and a schedule keeps them updated. From Claude, the MarketMage plugin shows the ads a competitor runs, watches them for new and stopped ads, or finds small advertisers whose ads have run for weeks, in a chat.
Is it allowed to monitor competitor ads?
The actor reads the platforms' public ad libraries as a signed-out visitor sees them (Meta and TikTok through a third-party API that reads the same public libraries): no login, no account and no personal data of individuals. Advertisers are pages and business accounts. How you use the data, and following the laws and terms that apply to you, is your responsibility. This is not legal advice.
Related actors
Other CleanPull actors for ads and market research:
- Competitor Promotions & New Products Monitor: competitor sales, discount codes and new products.
- Google Trends Scraper & API: Google Trends interest over time, regions and related queries.
- Tech Stack Detector: the technologies any website runs, with versions and evidence.
- TikTok Shop Scraper & Sales Tracker: TikTok Shop units sold per day, revenue and rising products.
Use it from Claude
The MarketMage plugin runs these actors from a Claude chat.
Found it useful? A rating on the Store helps others find it.
Changelog
-
0.2.x, TikTok account size from the read (2026-11-04): a TikTok advertiser name with One row per advertiser now carries
accountAdsInLibraryfrom its own read, at no extra request, whether or not TikTok account size is on (it was null). TikTok account size and the docs now say keyword and domain items get no size, as TikTok's keyword answers carry no account id. Prices and events unchanged. -
0.2.x, TikTok proven advertisers (2026-11-04): TikTok account size (
tiktokAccountSize, with One row per advertiser): each TikTok advertiser kept by a keyword or domain item getsaccountAdsInLibrary, the number of ads TikTok's library lists for its account (one library request each, up to 30, longest-running first). Advertiser rows on every platform carrymaxReach, the widest reach among their kept ads. Prices and events unchanged. -
0.2.x, TikTok accounts (2026-11-02): a TikTok brand read no longer stops at an account named for the brand that lists no ads (Gymshark → an empty "Gymshark" account gave 0 ads): the account TikTok lists ads of is read first, then the brand's other accounts up to Ads per watch item, then the accounts the watchlist read before, then the suggestions once more. A read ending with no ads says which accounts listed none. Prices and events unchanged.
-
0.2.x, stops and proven ads (2026-11-02): a missing ad counts toward a stop only on a full read with the same filters (Days running (at least) never counts one, and runs with Days running (at least) or Active ads only off keep their own memory), fixing stops reported for TikTok ads still running; Days running (at least) asks Meta for older ads by date (1 page where 6 found none); TikTok reads only the brand's own account, by its id on every page (steady results; other accounts are left out and counted, empty name suggestions asked once more); TikTok rows carry the caption as
text; the run notes count Meta ads read and left out instead of saying none were found. Prices and events unchanged. -
0.2.x, proven advertisers (2026-10-24): Days running (at least) (
minDaysRunning) keeps only ads running at least that many days on Meta and TikTok (start dates checked on each ad); younger ads are not delivered or charged. One row per advertiser (oneRowPerAdvertiser): page, landing domain, ads kept, earliest start, days running and a sample ad, each charged as one ad. Prices and events unchanged. -
0.2.x, reliability (2026-10-24): runs that find nothing (advertisers with no match, input naming nothing readable) end SUCCEEDED with a free
unreadablerow per item saying why, instead of FAILED; a run stops starting watch items before its time limit and ends with what it read, never TIMED-OUT. Google advertiser ids, Meta page ids and platforms are checked in the input form. Prices and events unchanged. -
0.2 (2026-10-15): Meta and TikTok through CleanPull's ad library service: no tokens or developer apps needed, Meta ads in every country with text, media links and calls to action; TikTok's library for the EU, the UK and Switzerland with captions and video links. Google falls back to the service when it declines a run. New event: library request.
-
0.1.x (2026-10-15): RUN_SUMMARY
perWatchItemsays whether each watch item was delivered in full (complete); a watch item whose check could not be paid for no longer counts inwatchItemsRead. -
0.1 (October 2026): Google Ads Transparency Center by brand, domain or advertiser id; Meta Ad Library API and TikTok Commercial Content API with your own credentials as secret inputs; new and stopped ads with first and last shown dates, stops confirmed on a second run; watchlists with Changes only; Max cost per run.