Facebook Ads Library Scraper - New and Stopped Ads Monitor
Pricing
from $2.50 / 1,000 ad returneds
Facebook Ads Library Scraper - New and Stopped Ads Monitor
For marketers and agencies tracking competitors on Facebook and Instagram: Meta Ad Library ads by keyword or page, with days running, active status, text, links, images and videos. Monitor mode returns only ads that are new since your last run, plus the ones that stopped.
Pricing
from $2.50 / 1,000 ad returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Track your competitors' Facebook and Instagram ads from the Meta Ad Library, by keyword or by page. Every ad comes with how many days it has been running, whether it is still active, its text, headline, call to action, landing page, images and videos. Turn on monitor mode and each run returns only the ads that are new since your last run, plus the ads that stopped since then.
Who it is for
- Marketers and media buyers who want to know the day a competitor launches a new creative, and which ads they turned off.
- Agencies reporting on several brands: one run checks up to 30 keywords and pages.
- Creative strategists looking for winning ads: ads that have been running for many days are the ones an advertiser keeps paying for. Sort the dataset by
runDaysto see them first.
What you get for every ad
| Field | What it holds |
|---|---|
adArchiveId, adLibraryUrl | The Ad Library ID and a link that opens the ad in the Ad Library |
pageName, pageId, pageUrl, pageLikeCount, pageCategories | The advertiser |
isActive, startDate, endDate, runDays | Active or stopped, the day it started, the day it stopped (stopped ads only), and the number of days it has run (up to today for active ads) |
lastShownDate | The last day Meta reports the ad as shown |
platforms | facebook, instagram, messenger, audience_network, threads |
body, title, caption, linkDescription, ctaText, ctaType, linkUrl | The ad copy, headline, call to action and landing page |
imageUrls, videoUrls, videoPreviewImageUrls, cards | Media of single, carousel, dynamic creative and catalog ads |
collationCount, collationId | How many ads use the same creative (1 when the creative is used once) |
euReach, reachedCountries | Reach published by Meta for ads shown in the EU |
spend, impressions, currency | Ranges published by Meta for issue, election and political ads |
pageAdsInRun, pageActiveAdsInRun, pageActiveAdCount | Per-advertiser counts: ads of this page in the run, active ones, and the page's full number of active ads when the page was read to the end |
changeType | With the monitor on: new or stopped |
What the monitor returns
- First run: reads the ads of each search and page, compares and remembers them. No ad row is returned; the ads compared are charged as ad checks (see below), and one free row per search says the watch started.
- Every later run: returns only
- new ads (
changeType: "new"): ads it has not seen before whose start date is no earlier than two days before the watch began (the Ad Library lists new ads with a delay and gives the start day, not the hour), and - stopped ads (
changeType: "stopped",isActive: false): ads that were active at the last check and are not active now.
- new ads (
- A run with no change returns one free row per search (
status: "no-changes"), so a schedule never fails silently.
One memory is shared by all searches and pages of a watch and across runs, so an ad that shows up for two of your keywords is returned once, not twice. Schedule it daily (or hourly) in Apify and connect the dataset to Slack, email, Google Sheets or a webhook to get a launch-and-stop feed of your competitors' ads.
Why this one
- New and stopped ads, not the full list again. A plain scrape returns the full list every time and leaves the comparing to you; the monitor does the comparing and returns only the changes.
- Days running on every row, counted to today for active ads. Meta's own "end date" on an active ad is only the last day it was shown; this Actor keeps that in
lastShownDateand never reports an active ad as ended. - Media for dynamic creative and catalog ads. Image and video URLs come from the ad's cards as well, so dynamic creative (DCO) and catalog (DPA) ads keep their media. Template text such as
{{product.name}}is not passed off as ad copy. - Per-page counts on every row, so you can see how many active ads each advertiser runs.
- Clear answers instead of empty runs: a keyword with no ads, a page that does not exist, a country code Meta does not accept, or a page of results that could not be read each come back as a free row that says what happened.
Input
| Field | What it does |
|---|---|
searchTerms | Words to search, one per line (a brand, product or competitor). An Ad Library search link also works. |
pages | Advertisers to watch: a numeric page ID or an Ad Library link with view_all_page_id. |
country | Two-letter country code (US, GB, DE…) or ALL. |
activeStatus | Active ads only (default), stopped ads only, or both. |
adType | All ads, or one Ad Library category (issues and politics, housing, employment, credit, financial products). |
mediaType | All media, images, videos, memes, images and memes, or ads with no image or video. |
searchType | All words in any order, or the exact phrase. |
sortBy | The Ad Library's relevance order, or its recently started order. |
maxItems | How many ads to read for each search or page (1 to 5,000; 100 when empty). |
monitor | On = return only new and stopped ads since the last run. |
watchName | Optional label to keep separate memories for separate watches. |
resetMonitoringState | Forget the watch and start again (the next run is a first run: ad checks, no ad rows). |
Input example
{"searchTerms": ["nike", "running shoes"],"pages": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&view_all_page_id=15087023444"],"country": "US","activeStatus": "active","maxItems": 200,"monitor": true}
Output example
{"status": "ok","changeType": "new","adArchiveId": "1234567890123456","pageName": "Example Brand","isActive": true,"startDate": "2026-10-24","endDate": null,"runDays": 2,"platforms": ["facebook", "instagram"],"body": "Our new running shoe is here.","title": "Shop the new collection","ctaText": "Shop now","linkUrl": "https://www.example.com/","imageUrls": ["https://scontent.xx.fbcdn.net/..."],"videoUrls": [],"collationCount": 1,"adLibraryUrl": "https://www.facebook.com/ads/library/?id=1234567890123456","pageId": "100000000000000","pageActiveAdsInRun": 12,"country": "US"}
How much it costs
You pay per ad returned, plus a small fee per run that reads the Ad Library and compares or returns its ads. With the monitor on, each ad read and compared with the watch's memory is also charged as an ad check, on every monitor run including the first run and the run after a reset; new and stopped ads are charged as ad rows on top of that. Rows that explain why something was not returned are free.
| Event | When | Price |
|---|---|---|
| Ad returned | each ad row | $3.50 per 1,000 on the Free plan, lower on paid plans (down to $2.50) |
| Ad checked | monitor on: each ad compared | $0.70 per 1,000 on the Free plan, lower on paid plans (down to $0.50) |
| Run start | once per run that read a list and compared or returned its ads (not the first run of a watch) | $0.05 |
Set a maximum cost per run in Apify and the Actor stops cleanly at that limit. Ads it could not return are not remembered, so the next run returns them; with the monitor on, ads it did not get to compare are not charged and not remembered, and nothing is reported as stopped from that search in that run.
Good to know
- Stopped ads are found in two ways: an ad that reads as stopped in the list, or (with "Active ads only") a remembered active ad that is missing from the full active list. The second way needs the whole list read, so set
maxItemsabove the number of active ads of the search or page; when a run reads only part of the list, it does not report anything as stopped from it. - Pages are taken by numeric page ID or an Ad Library link with
view_all_page_id. A page-name link (facebook.com/brand) cannot be resolved without logging in, which this Actor does not do; open the page in the Ad Library and copy its link. euReachandreachedCountriesare filled for ads shown in the EU;spendandimpressionsfor issue, election and political ads. Elsewhere Meta does not publish them, and the fields arenull.- Order: "Recently started" uses the Ad Library's own newest order, which puts recent ads near the top but is not strictly by start date. With the monitor on, a new ad is found wherever it sits in the part of the list that was read, so a higher
maxItemscatches more. - The Ad Library returns about 10 ads per request and no total count, so large searches take longer. Each search is read up to
maxItems(1 to 5,000). - The Actor opens the public Ad Library in a real browser through Apify's residential proxy. It does not log in, use cookies or solve image challenges; if Meta shows a login or check page, the run stops and says so without charging.
- This is an unofficial tool, not affiliated with, endorsed by or sponsored by Meta Platforms, Inc. Facebook, Instagram and Meta are trademarks of Meta Platforms, Inc.
Thanks for using this Actor
We build these tools for people who run them every day, and we improve them from what users tell us.
- Missing a field, or need another filter? Tell us in the Issues tab. If the data is there, we add it.
- Found a bug or a wrong value? Post the run ID in the Issues tab. Wrong data is the thing we fix first.
If this Actor saved you time, a short review helps other people find it.