Facebook Ads Library Scraper - New and Stopped Ads Monitor avatar

Facebook Ads Library Scraper - New and Stopped Ads Monitor

Pricing

from $2.50 / 1,000 ad returneds

Go to Apify Store
Facebook Ads Library Scraper - New and Stopped Ads Monitor

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

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

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 runDays to see them first.

What you get for every ad

FieldWhat it holds
adArchiveId, adLibraryUrlThe Ad Library ID and a link that opens the ad in the Ad Library
pageName, pageId, pageUrl, pageLikeCount, pageCategoriesThe advertiser
isActive, startDate, endDate, runDaysActive 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)
lastShownDateThe last day Meta reports the ad as shown
platformsfacebook, instagram, messenger, audience_network, threads
body, title, caption, linkDescription, ctaText, ctaType, linkUrlThe ad copy, headline, call to action and landing page
imageUrls, videoUrls, videoPreviewImageUrls, cardsMedia of single, carousel, dynamic creative and catalog ads
collationCount, collationIdHow many ads use the same creative (1 when the creative is used once)
euReach, reachedCountriesReach published by Meta for ads shown in the EU
spend, impressions, currencyRanges published by Meta for issue, election and political ads
pageAdsInRun, pageActiveAdsInRun, pageActiveAdCountPer-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
changeTypeWith the monitor on: new or stopped

What the monitor returns

  1. 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.
  2. 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.
  3. 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 lastShownDate and 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

FieldWhat it does
searchTermsWords to search, one per line (a brand, product or competitor). An Ad Library search link also works.
pagesAdvertisers to watch: a numeric page ID or an Ad Library link with view_all_page_id.
countryTwo-letter country code (US, GB, DE…) or ALL.
activeStatusActive ads only (default), stopped ads only, or both.
adTypeAll ads, or one Ad Library category (issues and politics, housing, employment, credit, financial products).
mediaTypeAll media, images, videos, memes, images and memes, or ads with no image or video.
searchTypeAll words in any order, or the exact phrase.
sortByThe Ad Library's relevance order, or its recently started order.
maxItemsHow many ads to read for each search or page (1 to 5,000; 100 when empty).
monitorOn = return only new and stopped ads since the last run.
watchNameOptional label to keep separate memories for separate watches.
resetMonitoringStateForget 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.

EventWhenPrice
Ad returnedeach ad row$3.50 per 1,000 on the Free plan, lower on paid plans (down to $2.50)
Ad checkedmonitor on: each ad compared$0.70 per 1,000 on the Free plan, lower on paid plans (down to $0.50)
Run startonce 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 maxItems above 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.
  • euReach and reachedCountries are filled for ads shown in the EU; spend and impressions for issue, election and political ads. Elsewhere Meta does not publish them, and the fields are null.
  • 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 maxItems catches 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.