How to scrape the Meta Ad Library for competitor ad research
Key Takeaways
What is the Meta Ad Library? The Meta Ad Library (facebook.com/ads/library) is Meta's public transparency database of ads running across Facebook, Instagram, Messenger, Threads, and Audience Network. Anyone can search it by advertiser or keyword without logging in.
What can you scrape from the Meta Ad Library? Each ad's body text, headline, images, videos, carousel cards, call to action, landing page URL, start and end dates, platforms, and advertiser page. With details on, you also get EU and UK reach with age, gender, and country breakdowns, payer and beneficiary, and the advertiser's Facebook likes and Instagram followers.
Does the Meta Ad Library show how much a competitor spends?
Mostly no. Meta publishes spend and impression ranges for political and issue ads. For ordinary commercial ads the spend field is usually empty. EU reach numbers are the closest public proxy for scale.
What is the fastest way to find a competitor's winning Facebook ads? Sort by run length. Advertisers stop ads that lose money, so an ad that has been active for 60 or more days is very likely profitable.
Why the Meta Ad Library is the best free competitor ad research source
Performance marketers, DTC founders, agencies, and creative strategists use the Meta Ad Library to see exactly what competitors are running on Facebook (Meta), Instagram, Messenger, and Threads. Since Meta made the library public, it has been the largest free source of real, live ad creative anywhere.
The problem is the interface. It shows one advertiser's ads as cards, with no export, no sorting by run length, and no way to compare 10 competitors side by side. The Meta Ad Library Scraper returns the same data as structured rows.
| Research question | Field to use |
|---|---|
| What hooks and offers are competitors testing? | snapshot.body.text, snapshot.title |
| Which ads are probably profitable? | start_date_formatted, is_active |
| Image, video, or carousel? | snapshot.display_format, snapshot.cards |
| Where does the ad send traffic? | snapshot.link_url, snapshot.cta_type |
| Which placements do they buy? | publisher_platform |
| How many people in the EU saw it? | transparency_by_location.eu_transparency.eu_total_reach |
How to scrape a competitor's Facebook and Instagram ads
The scraper takes one startUrl, which can be a Facebook Page URL, an Instagram profile URL, a single ad URL, a plain keyword, or any Ad Library search URL with filters already set.
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("parsebird/facebook-ads-library-scraper").call(run_input={
"startUrl": "https://www.facebook.com/nike/",
"maxAds": 500,
"country": "US",
"activeStatus": "all",
"extractDetails": False,
})
ads = client.dataset(run["defaultDatasetId"]).list_items().items
The easiest way to apply complex filters is to set them in the Ad Library itself (country, media type, platform, language, date range, exact phrase), then paste the resulting URL as startUrl. The scraper keeps every filter in the URL.
| Input | Values | Notes |
|---|---|---|
startUrl | Page URL, Instagram URL, Ad Library URL, ad URL, or keyword | Required |
maxAds | 1 to 10,000 | Default 100 |
country | Two-letter code or ALL | Used when the URL has no country |
activeStatus | active, inactive, all | all includes stopped ads, useful for history |
extractDetails | true or false | EU/UK reach, demographics, payer, advertiser stats |
Can I scrape Instagram ads, or only Facebook ads?
Both. The Ad Library covers Facebook, Instagram, Messenger, Threads, and Audience Network, and each ad's publisher_platform field lists where it ran. You can also start from an Instagram profile URL.
Finding long-running ads as a profitability signal
Run length is the single most useful public signal in ad research. Here is a simple filter for ads that have run at least 60 days:
const DAY = 86400;
const now = Math.floor(Date.now() / 1000);
const winners = ads
.map((ad) => ({
id: ad.ad_archive_id,
page: ad.page_name,
hook: ad.snapshot?.body?.text?.slice(0, 120),
format: ad.snapshot?.display_format,
cta: ad.snapshot?.cta_text,
daysRunning: Math.round(((ad.is_active ? now : ad.end_date) - ad.start_date) / DAY),
url: ad.ad_library_url,
}))
.filter((ad) => ad.daysRunning >= 60)
.sort((a, b) => b.daysRunning - a.daysRunning);
Group the winners by format and cta and patterns show up fast: one competitor might run long-lived video ads with "Shop now" while its static image ads rarely last more than two weeks.
Why do many ads have the same text?
Advertisers often run the same copy with different images or videos, or across several pages. Group by snapshot.body.text to count variants. A hook with many creative variants is one the advertiser is investing in.
Using EU reach and demographics as a scale proxy
The EU Digital Services Act requires Meta to publish reach data for ads shown in the European Union. With extractDetails on, each EU-targeted ad includes eu_total_reach and breakdowns by country, age, and gender. That is the closest thing to impression data the Ad Library offers for commercial ads.
A trimmed, illustrative details block:
{
"aaa_info": { "targets_eu": true },
"transparency_by_location": {
"eu_transparency": {
"eu_total_reach": 173451,
"gender_audience": "All",
"age_audience": { "min": 18, "max": 65 },
"age_country_gender_reach_breakdown": [
{
"country": "AT",
"age_gender_breakdowns": [
{ "age_range": "45-54", "male": 1073, "female": 547, "unknown": 19 }
]
}
]
},
"uk_transparency": { "total_reach": 6485 }
}
}
Details are billed as a separate event, so a cost-efficient pattern is two passes: scrape all ads without details, filter to long-running ones, then re-scrape only those by their single-ad URLs with extractDetails on.
Meta Ad Library scraper pricing
At the time of writing the scraper charges about $0.59 per 1,000 ads, plus about $0.59 per 1,000 ad-details lookups when extractDetails is on, with lower prices on paid Apify plans. Check the actor page for current rates.
Pairing Meta ad data with TikTok ad data
Most brands now split paid social spend between Meta and TikTok. The TikTok Top Ads guide covers the TikTok side: Creative Center ranks top ads by CTR and engagement, which complements Meta's run-length signal. For an always-on version of this research, see how to build competitor monitoring without code.
FAQ
Is it legal to scrape the Meta Ad Library? The Ad Library is a public transparency tool and the scraper reads only what it shows to logged-out visitors. Meta also offers an official Ad Library API, which requires identity verification and mainly covers political and issue ads. Check Meta's terms before commercial use.
How far back does the Meta Ad Library go?
Active ads are always shown. Political and issue ads are kept for seven years, and ads delivered in the EU are kept for a year after they last ran under the Digital Services Act. Other inactive commercial ads may not be listed. Set activeStatus to all to include any inactive ads the library still shows.
Can I download the ad images and videos? The output includes image and video URLs from Meta's CDN. These links are signed and expire after a few days, so download the files you want to keep soon after the run.
Can I track when a competitor launches new ads?
Yes. Schedule a daily run on the competitor's page with activeStatus set to active and compare ad_archive_id values with the previous run. New IDs are new ads.
Browse the Social Media category for more ad and social data tools.