Facebook Ads Library Scraper
Pricing
Pay per event
Facebook Ads Library Scraper
Meta Ad Library ads by page, keyword or link: text, media, dates, platforms, political spend, EU/UK reach included free. Built to beat Facebook Ad Library Scraper: ads for 57 of 58 test sources vs 45, zero template text vs 25%, 5x faster on a 40-source batch (Oct 2026). From $0.50 per 1,000.
Pricing
Pay per event
Rating
0.0
(0)
Developer
TidyHarvest
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Get every ad a brand is running on Facebook, Instagram, Messenger, Threads and Audience Network from the Meta Ad Library: ad text, headline, landing page, call to action, images and video URLs, carousel cards, start and end dates, platforms, and the advertiser's page. Add EU and UK transparency data (reach, reach by country, age and gender, targeting, payer and beneficiary) with one checkbox.
Paste a Facebook page, an Ad Library URL from your browser, a single ad link, or just type search terms and countries. No login, no cookies, no Facebook account.
Compared with Facebook Ad Library Scraper
We built this to beat Facebook Ad Library Scraper
(curious_coder/facebook-ads-library-scraper), the most-used independent Ad Library actor on Apify Store. In October 2026
we ran both on the same 61 inputs in two rounds (37 brand and small-advertiser pages from over a dozen countries, 15 keyword
searches with platform, media, sort and exact-phrase filters, 8 ad share links, 1 nonexistent ad), active ads only, all
countries, up to 300 (first round) or 100 (second round) ads per source.
| This actor | Facebook Ad Library Scraper | |
|---|---|---|
| Sources that returned ads (of 58 that have ads) | 57 | 45 |
| Brand pages it reported as "private" (Revolut, Allbirds, Hims, Heineken, Jack Daniel's) | read 5 of 5 (707 ads) | 0 of 5 |
Ad share links (/ads/library/?id=...) | 7 of 7 | 0 of 7 |
Rows whose text is a template placeholder ({{product.brand}}) | 0% (0 of 6,289) | 25% (1,558 of 6,149) |
| Inactive ads returned when you asked for active only | 0 | 21 |
| Ads on sources both read | the same ads (all but 1 of our 5,565 were in theirs) | 0-30 more per source, past the per-source cap |
| EU reach on the same 150 ads (first round) | identical values | identical values |
| Error rows charged | none (status rows are free) | 7 |
| EU/UK reach details | included | included |
| Price per 1,000 ads | $0.50 ($0.35 on Gold and above), no start fee | $0.75 + $0.05 per run ($0.75 measured) |
| Time for 40 mixed pages, searches and ad links (up to 100 ads each; two runs each) | 83-95 s | 433-525 s |
Pages whose ads Facebook partly hides from logged-out visitors (alcohol and other age-restricted brands) are read as far as Facebook allows and say so: "Facebook shows 8 of about 364 ads to logged-out visitors".
Where it still does more: on a single source it is about as fast or a little faster (first round: a brand page took 70 s vs 66 s here; with EU details on, 180 ads took 33 s vs 27 s). Its developer documents a limit of roughly 3,000-6,000 ads per search URL; in our test this actor returned 10,920 ads from a single search.
The other big one, Facebook Ads Library Scraper (apify/facebook-ads-scraper),
cost $4.30-5.00 per 1,000 ads on our plan tiers in the same tests (its card runs from $5.80 down to $1.00 at the top tier),
returned nothing for all five walled pages, and had placeholder text in 28% of rows (88 of 318).
How well it works
Measured in October 2026 on Apify cloud at the default 256 MB, on 88 real inputs drawn the way users bring them: 54 brand and small-advertiser pages in 15+ countries, 20 keyword searches in 10 languages (with media, platform, date, sort, exact-phrase and political filters), 12 ad share links, and a nonexistent ad and page.
- 87 of 88 inputs answered correctly: ads for 44 pages, 19 searches and all 12 share links; an honest status row for the rest (no ads running, a nonexistent ad or page, or a handle that matches several country pages, with their ids listed). One page lookup was throttled on every IP tried and says so.
- 15,991 ads, zero duplicates. Ad text on 98.0%, landing page on 97.5%, an image or video on 98.8%, call to action on
98.2% (the rest genuinely have none, or their media is hidden from logged-out visitors, which
mediaRequiresLoginflags). - About $0.04 of platform cost per 1,000 ads on these runs, so the price leaves room to keep it maintained.
- Political ads: spend range, impressions range and "paid for by" on 299 of 299 US election ads.
- EU reach on 95% of ads shown in the EU (171 of 180), matching the values the leading actor returns on every shared ad.
- 10,920 ads from one keyword search in a single run, and a run moved by Apify to another server mid-way finished with 914 of 914 ads and no duplicates.
- Dynamic and catalog ads come back with the text the site shows, never a
{{product.name}}placeholder.
What you can do with it
- Competitor monitoring: every active ad of the brands you follow, daily. Turn on Only new ads and each run returns (and charges for) only ads you haven't seen.
- Creative research / swipe files: search ad text by keyword and country, filter by video or image, platform, language and date, sort by impressions.
- Lead qualification: Count only tells you whether a company is advertising on Meta and roughly how many ads it runs, for $1 per 1,000 companies.
- EU/UK transparency and political ads: reach and audience breakdowns for ads shown in the EU or UK; spend and impression ranges for issue, election and political ads.
- One ad by its link: paste
facebook.com/ads/library/?id=...and get that ad.
Input
| Field | What it does |
|---|---|
urls | Any mix of Ad Library URLs, Facebook page URLs (facebook.com/nike, profile.php?id=, /people/...), page handles, numeric page ids and single-ad links. |
searchTerms | Keywords to search ad text for. No URL needed. |
countries | Two-letter codes (US, GB, DE...). Empty = all countries (or the country in your URL). Several = one search per country. |
maxAdsPerSource | Stop each source after this many ads (default 1,000; 0 = all). |
maxItems | Hard cap on ads for the whole run, which also caps your cost. |
activeStatus, adType, mediaType, platforms, startDate, endDate, languages, sortBy, exactPhrase | Filters. They apply to every source, including Ad Library URLs you paste. |
includeAdDetails | EU/UK reach, audience breakdowns, payer/beneficiary, verified legal entity and advertiser profile per ad (free). |
countOnly | One row per source with the ad count and whether it is advertising (no ads returned). |
onlyNewAds + stateKey | Scheduled monitoring: skip ads returned on earlier runs, so you pay only for new ones. |
onePerAdvertiser | Keep the first ad of each page (lead lists from keyword searches). |
runTag | Copied into every row. |
Field names other Ad Library actors use also work (startUrls, resultsLimit, limitPerSource, count,
scrapeAdDetails, onlyTotal...), so you can switch without rewriting your integration.
Examples:
{ "urls": ["https://www.facebook.com/nike", "https://www.facebook.com/gymshark"], "countries": ["US"], "maxAdsPerSource": 0 }
{ "searchTerms": ["protein powder"], "countries": ["US", "GB"], "mediaType": "video", "sortBy": "impressions", "maxAdsPerSource": 200 }
{ "urls": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=DE&q=versicherung&search_type=keyword_unordered"], "includeAdDetails": true }
Output
One row per ad (type: "ad"), with stable camelCase field names and ISO dates:
{"type": "ad","adArchiveId": "1870984290951787","adLibraryUrl": "https://www.facebook.com/ads/library/?id=1870984290951787","pageId": "15087023444","pageName": "Nike","pageUrl": "https://www.facebook.com/nike/","pageLikeCount": 39502064,"pageCategories": ["Sportswear"],"isActive": true,"startDate": "2026-09-02T07:00:00Z","endDate": null,"activeDays": 45,"platforms": ["facebook", "instagram"],"displayFormat": "VIDEO","body": "Ad text as shown...","title": "Headline","linkUrl": "https://www.nike.com/...","linkDomain": "nike.com","ctaText": "Shop now","ctaType": "SHOP_NOW","imageUrls": [],"videos": [{"hdUrl": "https://video...", "sdUrl": "https://video...", "previewImageUrl": "https://scontent..."}],"cards": [],"isDynamicCatalogAd": false,"collationCount": 3,"collationId": "...","categories": [],"paidForBy": null,"spend": null,"impressions": null,"position": 1,"sourceTotalEstimate": 2722,"source": {"input": "https://www.facebook.com/nike", "type": "page", "url": "https://www.facebook.com/ads/library/?...", "pageId": "15087023444"},"scrapedAt": "2026-10-17T04:00:00Z"}
collationCount: the Ad Library groups near-identical ads ("3 ads use this creative and text"). This is that number.- Dynamic and catalog ads (
isDynamicCatalogAd): the ad's top-level text is a template ({{product.name}}). We return the first real variation's text instead, as the site shows it, never the placeholder. All variations are incards. spend,impressions,paidForBy: Meta publishes these only for issue, election and political ads.- With
includeAdDetails, adetailsobject addseuTotalReach,euAudience(targeted ages, gender, locations, reach by country/age/gender), the same for the UK,payer,beneficiary,verifiedPayer/verifiedBeneficiary(legal name, country, website) andadvertiser(Instagram handle and followers, category, verification, description). - Status rows (free): a source that finds nothing or can't be read gets one row with
type: "status"(no-ads,limited-by-facebook,page-not-found,ad-not-found,invalid-input,failed) so every input has a row. Filter ontype = "ad"to drop them, or turn offincludeStatusRows. SUMMARYin the run's key-value store lists every search: ads returned, the site's estimate, pages read.
Pricing
- $0.50 per 1,000 ads (
ad-scraped) on the Free plan; $0.45 Bronze, $0.40 Silver, $0.35 Gold and above. - EU/UK details are included: no extra charge when you turn them on. No start fee.
- Count only: $1 per 1,000 sources (
source-counted). - Status rows, duplicates and ads skipped by Only new ads or your caps are never charged. One ad found by two of your sources is returned and charged once.
Reliability
- Runs resume after Apify moves them to another server. The run continues from where it stopped and never returns or charges an ad twice. (In our test, a run without this saved 2,896 duplicate rows out of 7,703 after one move.)
- Empty results are double-checked. When Facebook throttles an IP it answers with an empty result instead of an error. Before reporting "no ads", the actor checks a query that always has results; if that is empty too, it moves to a fresh IP and continues from the same page.
- Filters are honoured on every input type. Ads that don't match a filter you set are not returned or charged.
Limits and notes
- Estimates vs. results: the Ad Library's "~N results" is Meta's estimate. Scrolling to the end usually shows fewer,
and that's what any scraper can return. Our
sourceTotalEstimateis Meta's number;SUMMARYshows how many were read. - Login-only ads (some age-restricted or regulated categories) are not shown to logged-out visitors and can't be returned.
- Media URLs are Facebook CDN links that expire after a few days or weeks: download what you need to keep.
- Speed: each source pages through results in order (about 5-9 ads per second, as fast as Facebook answers), and up to 16 sources run in parallel at the default 512 MB (8 at 256 MB, 24 at 768 MB+). EU/UK details are fetched alongside, 32 at a time.
Is it legal?
The Meta Ad Library is a public transparency database that Meta publishes so anyone can see the ads running on its platforms. This actor reads it the way a logged-out visitor does: no login, no account, no private data. The ads and pages are businesses' public advertising. Some fields name people (a page run by an individual, a political ad's "paid for by" disclaimer, payer/beneficiary names): if you store or use those, data-protection law (GDPR, CCPA and similar) applies to you. Ad creatives are copyrighted by their advertisers; research and analysis are generally fine, republishing them is not. Meta's terms restrict automated collection; if in doubt, ask a lawyer about your use.