I wanted a weekly list of competitor ads for a few ecommerce brands, sorted by how long each ad has been running. An ad that a brand keeps paying for after 60 days is usually an ad that makes money. That's the whole idea behind ad spy tools.
The Problem
The official route is Meta's Ad Library API. Here's what it asks for:
- Confirm your identity with a government ID on your Facebook account. Takes one to three business days.
- Create a Meta developer app.
- Generate an access token in the Graph API Explorer, and keep it fresh.
- Pass
ad_reached_countrieson every request.
Then the catch. For normal commercial ads, the API only covers ads delivered in the EU or the UK. A US brand's US only campaign isn't in it. Spend and impressions show up only for political and issue ads.
The Ad Library website is better. It shows every active ad a page runs, in any country. But clicking through a brand's 200 ads by hand, opening "See ad details" one by one for the EU numbers, and copying start dates into a sheet is not something I'm doing every Monday. And a plain HTTP request to the library page got a 403 and a JavaScript challenge in my test.
The Solution
So I built Meta Ad Library Scraper on Apify. It reads the same public library Meta also calls the Facebook Ads Library, so Instagram and Messenger ads come back next to the Facebook ones. Search by keyword or by advertiser page. No login, no token, no ID check.
Each row is one ad:
- the advertiser page, the ad's Library ID and its link
- start date, end date, whether it's still active, and
daysRunning, computed for every ad - platforms (Facebook, Instagram, Messenger, Audience Network)
- headline, body text, call to action, landing URL and landing domain
- image and video URLs
- for ads shown in the EU: reach by country, reach by age and gender, published targeting, and who paid for the ad
That last block sits behind a second click on the website. The actor opens it for you.
There's also a monitor mode. Turn on onlyNewSinceLastRun, schedule it weekly, and every row tells you whether the ad is new since your last run, whether it just crossed 30, 60 or 90 days running, or whether it stopped.
What I measured in October 2026:
- 20 test sessions, 0 real blocks
- every ad in my test runs had a start date, so
daysRunningwas never empty - a run for Nike plus "protein powder" returned 85 ads
- the same search as a monitor run 20 minutes later skipped all 85 and returned only the 50 it hadn't sent before
One honest warning about keyword search: Meta matches keywords loosely, so a keyword run picks up ads that only mention the word somewhere. I wrote about that in an earlier post. If you know the brand, search by advertiser instead.
Quick Start (3 Minutes)
- Open Meta Ad Library Scraper on Apify and click Try for free.
- Paste this into the JSON input:
{
"advertisers": ["Nike"],
"country": "US",
"activeStatus": "active",
"maxAdsPerSearch": 50
}
- Click Start, open the results table, and sort by
daysRunning.
Code Example
Python, with the official client (pip install apify-client). This one keeps only ads running for 30 days or more and prints the ten oldest:
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("agnes.developer.queen/meta-ad-library-scraper").call(run_input={
"advertisers": ["Nike"],
"searchTerms": ["protein powder"],
"country": "US",
"activeStatus": "active",
"minDaysRunning": 30,
"maxAdsPerSearch": 50,
})
ads = client.dataset(run["defaultDatasetId"]).list_items().items
ads.sort(key=lambda ad: ad.get("daysRunning") or 0, reverse=True)
for ad in ads[:10]:
text = (ad.get("headline") or ad.get("body") or "")[:60]
print(ad["daysRunning"], "days |", ad["advertiserName"], "|", text, "|", ad["libraryUrl"])
The same run from n8n, Make or Zapier works through the Apify integration: run the actor, then pass the dataset items to your sheet or Slack.
Use Cases
- Ad research for ecommerce brands. Sort a competitor's ads by days running and study the ones they keep paying for.
- Agency reports. One scheduled monitor per client: new ads this week, ads that crossed 30, 60 or 90 days, and ads that stopped.
- Creative swipe files. Pull image and video URLs for the long runners.
- EU audience research. Reach by country, age and gender for ads shown in the EU.
Pricing
$0.005 per ad, so $5 per 1,000 ads. A run that returns 200 ads costs $1. Ads with no start date or no creative are delivered free, with a reason field that says why. Apify gives every account $5 of free platform credit each month, which covers about 1,000 ads.
FAQ
Do I need a Facebook login or an access token?
No. It reads the public Ad Library pages.
Does it show ad spend?
No. Meta publishes spend only for political and issue ads, and this actor doesn't target those.
Why do some ads have no reach numbers?
Meta publishes reach, targeting and payer only for ads shown in the EU. The other rows still have the ad itself and its dates.
Is this allowed?
It reads what Meta's public transparency library shows anyone. Check Meta's terms for your use case, and talk to a lawyer if you're building a commercial product on it.
Get Started
Run Meta Ad Library Scraper on Apify. Try one advertiser first, sort by daysRunning, and see which ads a brand has kept paying for. Questions or bugs go in the actor's Issues tab.
Top comments (0)