Meta Ad Library API: Facebook Ads Library
Pricing
from $0.54 / 1,000 ads
Meta Ad Library API: Facebook Ads Library
Facebook Ad Library scraper and Meta Ad Library API: search the Facebook Ads Library by keyword, advertiser or Ad Library URL in any country. Ad text, images, videos, landing pages, CTA, dates and Meta's ad count, plus advertiser details and EU reach. Monitor competitors' new ads. No login.
Pricing
from $0.54 / 1,000 ads
Rating
0.0
(0)
Developer
DeepMine
Maintained by CommunityActor stats
0
Bookmarked
16
Total users
11
Monthly active users
a day ago
Last modified
Categories
Share
Meta Ad Library
Meta Ad Library API and Facebook Ads Library scraper: type a keyword, an advertiser or an Ad Library link and get one clean row per ad from the Meta Ad Library (Facebook, Instagram, Messenger, Threads), with the creative, ad text, headline, button, landing page, format, platforms, dates and Meta's count of matching ads, no login.
| Advertiser | Ad text | Headline | Button | Format | Started | Days active |
|---|---|---|---|---|---|---|
| ProDough Shop | ProDough Protein lets you make the best high prote… | Best Protein For Protein Yogurt | Shop now | Video | 2026-05-18 | 147 |
| Paleovalley | If you’ve been waiting to try Paleovalley’s 100% G… | BOGO Bone Broth Protein | Shop now | Dynamic creative | 2026-07-09 | 95 |
| Huel | Huel was never meant to replace real food. It’s fo… | For Your Inconvenient Meals. | Shop now | Video | 2026-08-04 | 69 |
$0.74 per 1,000 ads on Starter ($0.84 Free, $0.64 Scale, $0.54 Business); with ad details $1.39 per 1,000 ($1.49 Free, $1.29 Scale, $1.19 Business). The prefilled run (30 ads) costs about $0.02.
Add ad details for the advertiser's verification and Instagram account and, for ads shown in the EU or UK, reach by country, targeted ages and gender, payer and beneficiary. Turn on Only new ads and schedule it to monitor competitors' ads. No Facebook account, no cookies.
Switching from apify/facebook-ads-scraper? Every row also carries that Actor's fields under the same names (adArchiveID, snapshot, publisherPlatform, ...), after the clean fields, so your pipeline keeps working with no setting to change (details below). Coming from curious_coder's Facebook Ad Library Scraper? The same Meta record is here with camelCase keys (adArchiveId for ad_archive_id), plus totalCount (its total), adsCount (its ads_count) and rank (the ad's place in Meta's list, like its position).
What you can do with it
- Ad research / ad spy: see every active ad for "protein powder", "running shoes" or any product, most impressions first.
- Competitor monitoring: add your competitors' Facebook pages, schedule a daily run with Only new ads, and get just the ads they started since the last run, however many ads they already run.
- Creative inspiration: collect video and image URLs, hooks, headlines and CTAs by niche and country. Long-running ads (Days active) are usually the ones that work.
- Market and lead research: find the brands advertising in a niche, their Facebook pages and likes, and (with ad details) their Instagram accounts and followers.
- EU reach data: for ads shown in the EU or UK, get Meta's reach per country plus the targeted age range and gender (Meta's
ad_detailsobject in the row also has reach by age and gender).
Input
| Field | What it does |
|---|---|
| Search terms | Keywords, as in the Ad Library search box. One search per line. |
| Advertisers | A Facebook page link (facebook.com/nike), a page id (15087023444), an advertiser's Ad Library link, or the page name exactly as it appears on its ads. |
| Country | Two-letter code where the ads ran (US, GB, DE, ...) or ALL (US in the form, ALL if left out). |
| Max ads per search | Stop each search after this many ads (30 in the form: Meta's first page, one request; 200 if left out, up to 10,000). You pay per ad. Searches read about 1,000 ads in 3 minutes. |
| Include ad details | Adds the advertiser's profile and EU/UK reach data to each ad, at the with-details price (one more request per ad, so slower). |
| Only new ads (monitor) | Return only ads started since the last run that this Actor hasn't returned before for the same search. Max ads per search then limits the new ads per run. You pay only for the new ads. |
Under Filters and Ad Library URLs:
| Field | What it does |
|---|---|
| Ad Library URLs | Searches copied from facebook.com/ads/library. The link's own filters are used. |
| Ad status | Active (default), inactive, or both. |
| Media type | All, images, videos, memes, images and memes, or no media. |
| Ad category | All ads, or only ads about social issues, elections or politics (these carry spend, impressions and reach). |
| Exact phrase | Match the search terms as an exact phrase. |
| Shown on or after / before | The Ad Library's date filter: ads that were shown in that period, whatever day they started. |
Give at least one search term, advertiser or Ad Library URL; a run with none fails with a message. Example:
{"searchQueries": ["protein powder"],"advertisers": ["https://www.facebook.com/sephora/", "15087023444"],"country": "US","maxAdsPerQuery": 100,"includeAdDetails": false}
Output
One row per ad, in Meta's order (most impressions first; with Only new ads, most recent first). An ad found by several searches appears once, under the first search that found it.
Each row has two parts:
- The clean fields first (below): flat, readable values for spreadsheets and the Console tables. Every row has them in the same order; a value Meta doesn't give is
null. - Then the apify/facebook-ads-scraper fields, under that Actor's names: Meta's full ad record (below). They're what makes a row about 15 KB; skip them if you only need the clean part.
The Console tables show only the clean fields. A real row from the prefilled protein powder search in the US (2026-10-12), clean part (media links cut):
{"image": "https://scontent-dfw6-1.xx.fbcdn.net/v/t39.35426-6/765995747...","pageName": "Huel","adText": "Huel was never meant to replace real food.\n\nIt’s for the meals that happen away from the kitchen ...","adTextSnippet": "Huel was never meant to replace real food. It’s fo…","headline": "For Your Inconvenient Meals.","adLibraryUrl": "https://www.facebook.com/ads/library/?id=2784442271913133","landingUrl": "https://huel.com/products/huel-black-edition","ctaText": "Shop now","format": "Video","platforms": ["Facebook", "Instagram", "Audience Network", "Messenger", "Threads"],"isActive": true,"pageLikes": 332275,"collationCount": 3,"adsCount": 1,"daysActive": 69,"startedAt": "2026-08-04","lastShownAt": "2026-10-12","rank": 13,"totalCount": 19400,"videoUrl": "https://video-dfw6-1.xx.fbcdn.net/o1/v/t2/f2/m412/AQMPL5NRuPTUGTar...","pageUrl": "https://www.facebook.com/huelusa/","adArchiveId": "2784442271913133","pageId": "2281559212068421","searchInput": "protein powder","scrapedAt": "2026-10-12T17:07:38Z"}
Clean fields, in row order:
image: the creative's picture: its first image, the video's preview frame, or the first card's image.pageName: the advertiser (its Facebook page).adText,adTextSnippet: the ad's primary text in full, and its first 50 characters on one line.headline: the headline under the creative.adLibraryUrl: the ad in the Meta Ad Library.landingUrl: where the ad's button leads.ctaText: the button text, e.g. Shop now.format: Image, Video, Carousel, Dynamic creative, Catalog, ...platforms: Facebook, Instagram, Messenger, Threads, Audience Network, WhatsApp.isActive: still running when the run read it.pageLikes: likes of the advertiser's Facebook page.collationCount: how many ads use this creative and text. Meta says it on one ad of each group, so it's oftennull.adsCount: how many ads Meta lists together with this one in the results (one result group).daysActive: days fromstartedAttolastShownAt.startedAt: the day the ad started (YYYY-MM-DD).lastShownAt: the last day it ran: the day it stopped, or the run's day for active ads.rank: the ad's place in its search (1 = most impressions).totalCount: Meta's count of ads matching the search, as the Ad Library shows it (50001means 50,000+); the same on every row of a search.videoUrl: the ad's video file (standard definition), for video ads.pageUrl: the advertiser's Facebook page.adArchiveId,pageId: the ad's Library ID and the advertiser's page id.searchInput: the search term, advertiser or Ad Library URL that found the ad.scrapedAt: when the run started (UTC).
Dynamic and catalog ads keep placeholders like {{product.name}} in their top text; the clean fields take the text, headline and picture of the ad's first card instead, as the Ad Library shows it.
Images and videos expire. image, videoUrl and the media links in snapshot are Meta's signed CDN links (fbcdn.net). They stop working about 5 days after the run, so download what you want to keep.
When a search is for Issues, elections or politics (Ad category, or ad_type=political_and_issue_ads in an Ad Library URL), the clean part also has these fields after isActive. Meta publishes them for those ads only:
spend: Meta's spend range as shown, e.g.$45K - $50K.spendMin,spendMax: the same range as numbers incurrency(spendMaxisnullfor an open range like>$1M).currency: e.g.USD.impressions,reachEstimate: Meta's impressions range (e.g.>1M) and estimated audience size (e.g.100K - 500K).paidFor: the Paid for by disclaimer.
With Include ad details, these fields come in after pageUrl (details are fetched per ad; a row whose details are missing is charged as a plain ad):
detailsStatus: OK, Not available (Meta has none for this ad) or Failed.isPageVerified: the advertiser's page has Meta's verified badge.instagramUrl,instagramFollowers: the advertiser's Instagram account and its followers.euReach,ukReach: people reached in the EU and in the UK (ads shown there only).targetAges,targetGender: the targeted age range (e.g.18-65+) and gender.reachByCountry: people reached per country, most first (e.g.DE: 14,914).payer,beneficiary: who paid for the ad and who it benefits.
In the Console, the dataset has these tables: 📊 Overview (creative, advertiser, text, headline, links, button, format, platforms, active, started, days active, search), 📈 Stats (rank, search total, days active, page likes, same-creative and group counts, dates), 🎨 Creatives (picture, text, headline, button, video, landing page), 🏛️ Political (spend, impressions and reach; fills on political searches) and 📋 Details (fills with Include ad details). All fields shows the whole row, the facebook-ads-scraper part included.
facebook-ads-scraper fields
After scrapedAt, every row has the same fields as apify/facebook-ads-scraper, under the same names: Meta's raw ad record with camelCase keys, plus inputUrl, pageID / adArchiveID and startDateFormatted / endDateFormatted. Pipelines built on that Actor keep working when you switch. This part is nested (snapshot holds the creative), uses Meta's constants (FACEBOOK, VIDEO), and has every image and video variant (HD and SD). With Include ad details, Meta's ad_details object comes as Meta sends it, including reach by age and gender; as in apify/facebook-ads-scraper, its aaa_info also carries the EU reach fields (eu_total_reach, age_audience, gender_audience, location_audience, age_country_gender_reach_breakdown) that Meta now sends under transparency_by_location.
A field that is in both parts appears once, in the clean part, with the same value: pageName, isActive, pageId, adArchiveId, collationCount and, on political searches, spend, currency and reachEstimate. Meta's own adId (usually null) is a different id from adArchiveId. The same row as above, facebook-ads-scraper part (shortened, media links cut):
{"inputUrl": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&...&q=protein%20powder&...","pageID": "2281559212068421","adArchiveID": "2784442271913133","startDateFormatted": "2026-08-04T07:00:00.000Z","endDateFormatted": "2026-10-12T07:00:00.000Z","collationId": "906556651873182","pageIsDeleted": false,"snapshot": {"pageName": "Huel","pageProfileUri": "https://www.facebook.com/huelusa/","pageProfilePictureUrl": "https://scontent-dfw5-1.xx.fbcdn.net/v/t39.35426-6/...","caption": "huel.com","ctaText": "Shop now","ctaType": "SHOP_NOW","displayFormat": "VIDEO","linkDescription": "4,000,000 happy customers","linkUrl": "https://huel.com/products/huel-black-edition","pageCategories": ["Food & beverage company"],"pageLikeCount": 332275,"title": "For Your Inconvenient Meals.","cards": [],"images": [],"videos": [{ "videoHdUrl": "https://video-dfw5-1.xx.fbcdn.net/...","videoSdUrl": "https://video-dfw6-1.xx.fbcdn.net/...","videoPreviewImageUrl": "https://scontent-dfw6-1.xx.fbcdn.net/..." }]},"impressionsWithIndex": { "impressionsText": null, "impressionsIndex": -1 },"gatedType": "ELIGIBLE","categories": ["UNKNOWN"],"isAaaEligible": false,"reachEstimate": null,"currency": "","spend": null,"endDate": 1791788400,"publisherPlatform": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER", "THREADS"],"startDate": 1785826800,"adId": null,"targetedOrReachedCountries": []}
Main fields of this part:
adArchiveID,pageID: the ad's Library ID and the advertiser's page id (the same asadArchiveIdandpageId).snapshot: the creative. It holdsbody.text,title,caption,ctaText,linkUrl,displayFormat(IMAGE, VIDEO, CAROUSEL, DCO, DPA),images,videos,cards(carousel and dynamic-ad variants, each with its own text and media), and the page's likes, categories and picture.startDateFormatted/endDateFormatted(alsostartDate/endDatein unix seconds),publisherPlatform.ad_details(with Include ad details): the advertiser profile and, whenisAaaEligibleis true (the ad was shown in the EU/UK), reach and audience data.detailsStatusin the clean part says whether they came.spend,impressionsWithIndex,reachEstimate,currency: Meta fills these only for political and issue ads (choose Issues, elections or politics under Ad category). They're empty for commercial ads in every Ad Library tool, because Meta doesn't publish them.
Run summary
The run's OUTPUT record lists every search with Meta's result count (metaCount), the ads read, the ads delivered and why it stopped: complete, maxAds, chargeLimit, caughtUp (a monitor read every ad started since its last run; window shows Meta's count of them and how many were read), readCap (a monitor couldn't read back to its last run; see warning), duplicate (the same search was given twice), or a failure: blocked, error, incomplete.
Monitoring advertisers
- Put the competitors' pages in Advertisers (or keywords in Search terms).
- Turn on Only new ads.
- Save it as a task and schedule it daily.
How it works:
- Monitoring reads the Ad Library's Most recent order. The first run returns the newest ads, up to Max ads per search.
- Later runs go back to about two days before the previous run, so ads that appear in the Library a little late aren't missed. They return every ad started since then that wasn't returned before, even if the advertiser runs thousands of ads (up to the read limit below).
- Meta counts the ads started on each day, so a run reads only until it has seen every ad started since the last run, and then stops. The newest ads of each day come over datacenter IPs, and a day whose ads didn't change since the last run (Meta's count of all its ads, running or stopped, didn't move) isn't read again, so a run with a few new ads is usually done in a few seconds, whatever the advertiser's size. Meta doesn't order ads exactly by day (a new ad sometimes sits among older ones); the run still finds it, because it reads on until the count is met, but never further back than the start of the month before. You pay only for the new ads.
- If more new ads started than Max ads per search, the run returns that many and the next run continues where it stopped.
- A run reads at most 1,000 ads past Max ads per search. If a search has more ads this month than that, the run can't read back to the previous run: it returns the new ads it found, and its status message and OUTPUT
warningsay that new ads further down Meta's list were skipped. The next run starts from this one, so the monitor keeps working, but running more often doesn't help: the month's ads are still in the way. To check deeper, raise Max ads per search or narrow the search (country, media type). - The history is kept per search in your account, in the
meta-ad-library-monitorkey-value store. A search is the same search when its words or advertiser and all its filters are the same.
Reliability
- Uses Apify residential proxies by default. Meta refuses most datacenter IPs after the first page of results, so datacenter proxies aren't recommended.
- A refused or failed request is retried on a new IP.
- If Meta still refuses a search, the ads already collected are kept and the run fails with the reason. It doesn't report success on an incomplete search.
- Each search is checked against the result count Meta reports. A search whose results end well short of that count (under 80% of the count, or of Max ads per search if that's lower) fails the run.
- With Include ad details, failed details get a second try on new IPs. If details are still missing for more than half the ads, the run fails with the reason (the ads are kept, and charged as plain ads).
- Each ad appears once per run, even when several searches find it.
Pricing
Pay per ad, by your Apify plan. No start fee, no monthly fee.
| Per 1,000 ads | Free | Starter | Scale | Business |
|---|---|---|---|---|
| Ad | $0.84 | $0.74 | $0.64 | $0.54 |
| Ad with details | $1.49 | $1.39 | $1.29 | $1.19 |
- The with-details price is the ad price plus a flat $0.65 per 1,000 for the details, the same on every plan.
- An ad is charged the with-details price only when its details came; an ad whose details failed is charged as a plain ad.
- With Only new ads you pay only for the new ads, not for the ads the run reads to find them.
- Set a maximum cost per run in the run options: the run stops before it would go past it and keeps what it collected (
OUTPUT.chargeLimitReachedis thentrue).
Limitations
- Advertiser names are matched against the names on their ads. If a name isn't found, use the page link or page id; the run's OUTPUT lists names it couldn't find.
- Links to a single ad (
?id=...) aren't supported as input yet. Search its advertiser instead. - Spend and impressions exist only for political and issue ads (Meta's rule, see above).
- Page transparency (the confirmed page owner, address, name history) isn't included yet.
FAQ
Do I need a Facebook account? No. Everything comes from the public Ad Library, without logging in.
Which countries work? Every country in the Ad Library, or ALL.
How many ads can I get? Set Max ads per search up to 10,000. A search reads about 1,000 ads in 3 minutes, so 10,000 take about half an hour; several searches run in parallel. Very large searches (tens of thousands of ads) are easier to split by country, media type or date.
Related Actors
- Watching competitors? Facebook Ads Monitor runs this Actor's monitor as its own listing: add their pages, schedule it daily, get only their new ads.
- Only video ads? Facebook Video Ads returns HD and SD MP4 links of Facebook and Instagram video ads by keyword or advertiser.
- Meta ad research reports: Meta Ad Spy (winning products and long-running ads), Meta Ad Intelligence (who advertises in a niche, share of voice), Meta Ad Saturation Tracker (ad volume and new entrants over time), Meta Brand Mention Monitor (ads that mention your brand) and Meta Ad Monitor (launches and stopped ads per advertiser between runs).
- LinkedIn ads too? LinkedIn Ad Library API returns any company's LinkedIn ads with text, media, landing page, payer and EU targeting.
- Also need Threads data? Threads Scraper returns a brand's organic Threads posts, replies and profile, or the posts that mention it, with likes and view counts and no login.
Feedback
Found a bug or missing a field? Open an issue on the Issues tab and we'll look at it within 48 hours. Happy with the data? A short review on the Store helps others find this Actor.