Facebook Ads Library Scraper - Meta Ad Library API + Creatives avatar

Facebook Ads Library Scraper - Meta Ad Library API + Creatives

Pricing

from $1.20 / 1,000 ads

Go to Apify Store
Facebook Ads Library Scraper - Meta Ad Library API + Creatives

Facebook Ads Library Scraper - Meta Ad Library API + Creatives

Scrape the Facebook Ads Library (Meta Ad Library) by keyword, advertiser or pasted URL for every ad creative, including the dynamic and carousel variants others drop. Filters are enforced and reported, result caps are exact, and failed or filtered rows are free.

Pricing

from $1.20 / 1,000 ads

Rating

0.0

(0)

Developer

Blackcube Agency AB

Blackcube Agency AB

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

32 minutes ago

Last modified

Share

Facebook Ads Library Scraper — Meta Ad Library API + Creatives

More from this account: YouTube Transcript Suite · Website Contact & Email Suite · Career Site & ATS Jobs Suite · Google News Suite · Keyword Research Suite · Shopify Store Intelligence Suite · eBay Data Suite · Amazon Reviews Suite · Reddit · Vinted

You are charged for one thing: an ad that matched what you asked for and came back with something you can use. Filtered ads, ads Meta has withheld, empty results, bad inputs and failed requests are all free rows that tell you why. There is no start fee, so a run that returns nothing costs nothing.

Search the Facebook Ads Library and Meta Ad Library by keyword, by advertiser, or by pasting a URL straight from your browser. Get the ad copy, the headline, the call to action, the destination link, the advertiser, how long the ad has been running — and the actual image and video files.


Why ads come back empty from other tools

About 42% of the ads in the Ad Library are dynamic — the creative rotates across several variants instead of being one fixed image or video. Tools that read only the ad's main creative slot find nothing on those, so they hand you a row with no picture, no video, and a headline like {{product.name}}.

Measured on a single 500-ad run of this Actor, on live data:

Share of the 500 ads
Ads that returned at least one image or video100%
Same ads, counting only the main creative slot58.2%
Ads that were dynamic (multi-variant)41.8%
Ads that returned real ad copy98.8%
Ads that returned a destination link98.8%

Every variant comes back as its own entry with its own media, copy, headline and link, and the row still counts as one ad on your bill.

Meta also ships unfilled template slots — {{product.name}}, {{product.brand}} — as if they were real ad text. Those are removed rather than passed through, and the row is flagged so a pipeline can tell "the advertiser wrote no headline" apart from "Meta didn't fill this one in".


What you get for every ad

Creativead copy, headline, caption, call-to-action text and type, destination link
Mediaevery image and video, highest quality available, unwatermarked where Meta offers both, plus video poster frames
Variantseach dynamic-creative variant with its own copy, headline, link and media
Timingstart date, whether it is still running, and daysRunning as a number you can sort on
Scale signalhow many near-identical ads Meta groups with this one
Advertiserpage name, page ID, page URL, profile picture, page likes, page categories
Distributionwhich of Facebook, Instagram, Messenger, Threads, WhatsApp and Audience Network it runs on
FlagsAI-generated media, sensitive content, gating status, format

Identical field names on every row, every format, every country.

About spend, reach and impressions

Meta publishes these only for political and social-issue ads. On ordinary commercial ads they do not exist — across 500 live commercial ads, the fill rate for spend, reach and impressions was 0%.

You will see other tools advertise them anyway. Here those fields are null on commercial ads and populated on political ones, because a fabricated number silently corrupts whatever you filter or model with it. If you are researching political advertising you get them; if you are researching a supplement brand, nobody has them.


Filters are enforced, and the run tells you what they removed

Every filter is applied to every ad before it can be delivered or billed, and the run reports how many ads each one removed. A filter that cannot be honoured is never silently dropped — a date you type in a shape we cannot read comes back as a row saying so, instead of quietly widening your search.

  • startedAfter / startedBefore — ISO dates
  • minDaysRunning — the usual way to find proven winners
  • minCollationCount — only creatives the advertiser is scaling
  • mediaType — checked against the media actually extracted
  • publisherPlatforms, advertiserNameContains, textContains, onlyDynamicCreative, excludeGated

Ads removed by your filters are never charged.


Caps are exact

maxAds: 500 delivers 500 ads and stops. Not 530. The run report states how many ads it saw, how many it delivered, and how many each filter removed, so the arithmetic always closes.

Nothing is truncated silently

Every run says why it stopped:

stopReasonWhat it means
endOfResultsMeta had nothing more. This is a complete answer.
capReachedYour own maxAds stopped it — more ads exist.
pageBudgetReachedThe run's page budget stopped it — more ads exist.
sourceStoppedMeta stopped answering — some ads were not reachable.

isComplete is true only in the first case. No other tool in this category publishes this, and it is the difference between "that is all there is" and "that is all we got".


Monitoring: pay only for what is new

Set onlyNew: true and schedule the run. Ads already delivered for that input are skipped and not charged unless something about them changed — whether it is still live, when it ended, or how many siblings Meta groups with it.

Rewritten ad copy does not count as a change. Advertisers reword constantly, and billing you for that would re-charge a whole dataset for a typo fix.

Each input keeps its own memory, so a second scheduled task over an overlapping brand list still returns everything on its first run.


How to scrape the Facebook Ads Library by keyword

Put your terms in searchTerms and pick countries — the Ad Library is country-scoped, so the country decides which ads exist at all. Use exactPhrase for a phrase rather than loose keywords.

{
"searchTerms": ["protein powder", "creatine"],
"countries": ["US"],
"activeStatus": "active",
"maxAds": 500
}

How to scrape a competitor's Facebook ads

Open the advertiser in the Ad Library, copy the URL from your address bar, and paste it in. The search term, country, active status and media type in that URL are used as-is — you do not have to re-enter them.

{
"adLibraryUrls": ["https://www.facebook.com/ads/library/?active_status=all&country=US&view_all_page_id=590393174322587"],
"maxAds": 1000
}

Or give advertiserPageIds a list of numeric page IDs to track a whole competitor set in one run, with every row attributed to the advertiser it came from.

How to find winning Facebook ads

A creative still running after months is one the advertiser keeps paying for. Sort or filter on daysRunning, and use minCollationCount to keep only creatives being scaled rather than one-off tests.

{
"searchTerms": ["skincare"],
"countries": ["US"],
"activeStatus": "active",
"minDaysRunning": 60,
"minCollationCount": 3,
"maxAds": 300
}

How to scrape Instagram ads

Meta runs one library across its platforms. Filter with publisherPlatforms: ["INSTAGRAM"] to keep only ads that run on Instagram; each row also lists every platform the ad appears on.

How to download Facebook ad creatives

Each row carries direct media URLs — highest quality Meta offers, unwatermarked where there is a choice, with poster frames for video. Take the media array and fetch the URLs. Dynamic ads carry each variant's media separately, with the variant it belongs to.

How to use it as a Meta Ad Library API

Start a run and read the dataset over HTTP like any other endpoint. The official Meta Ad Library API needs identity verification and returns political and social-issue ads only; this covers commercial advertising, needs no key or approval, and returns a flat, consistent schema. Output is available as JSON, CSV or Excel.


Output

Two row types, told apart by type.

ad — the thing you asked for, and the only thing charged.

{
"type": "ad",
"adArchiveId": "3604351659703170",
"adLibraryUrl": "https://www.facebook.com/ads/library/?id=3604351659703170",
"pageName": "Paleovalley",
"pageId": "590393174322587",
"pageLikeCount": 195792,
"pageCategories": ["Food & Drink"],
"title": "BOGO Bone Broth Protein",
"body": "If you've been waiting to try Paleovalley's bone broth protein…",
"ctaText": "Shop now",
"ctaType": "SHOP_NOW",
"linkUrl": "https://paleovalley.com/offers/grass-fed-bone-broth-protein-bogo-a",
"displayFormat": "DCO",
"isDynamicCreative": true,
"hasUnresolvedPlaceholder": true,
"mediaCount": 2,
"media": [{ "kind": "video", "url": "https://…", "previewImageUrl": "https://…", "cardIndex": 0 }],
"variants": [{ "index": 0, "title": "BOGO Bone Broth Protein", "body": "2 bags for $60…", "media": [] }],
"startDate": "2026-07-09",
"endDate": null,
"isActive": true,
"daysRunning": 39,
"collationCount": 1,
"publisherPlatforms": ["FACEBOOK", "INSTAGRAM", "MESSENGER", "THREADS"],
"spend": null,
"currency": null,
"impressions": null,
"reachEstimate": null,
"searchTerm": "protein powder",
"searchCountry": "US",
"scrapedAt": "2026-08-17T13:52:00.000Z"
}

notice — free, and always says why: filteredOut, gatedByMeta, noResolvableCreative, noResults, invalidInput, notAttempted, requestFailed, blocked.

endDate is null while an ad is still running. Meta returns a far-future placeholder there, which is not a real end date, so isActive and daysRunning carry the meaning instead.

A full completeness and billing report is written to the key-value store as RUN_REPORT.


Pricing

From $1.00 per 1,000 ads, tiering down with your Apify plan. No start fee. No monthly minimum.

You are charged for delivered ads only. Filtered, gated, empty, failed and never-attempted rows are free, and with onlyNew a repeat run charges only for ads that are new or that changed.

Nothing is ever added to your search. If you supply Ad Library URLs or advertiser IDs, those are the only things searched. A run started with no input at all returns a small 10-ad sample so you can see the output shape, and says so in the log — it can never run up a bill on your behalf.

Input reference

Every field is documented in the Input tab. The proxy setting should be left at its default — it is the only configuration this Actor is tested on.

Notes

  • Please raise anything wrong or missing on the Issues tab.
  • The Ad Library is public transparency data. No login, no cookies and no account are required or accepted.
  • Unofficial. This Actor is not affiliated with, endorsed by, or connected to Meta Platforms, Inc., Facebook or Instagram. All trademarks belong to their owners. Use the data in line with Meta's terms and the law that applies to you.

Run it without configuring anythingSee which ads are running for a term, a ready-made example you can start as-is or copy.

Use cases

  • See what a competitor is spending on. Every live creative an advertiser is running, including the variants most scrapers drop.
  • Research a category before you buy media. Search by keyword to see the angles already saturating a market.
  • Track a campaign over time. A scheduled run captures creatives before they are rotated out.
  • Build a swipe file. Creative, copy, run dates and platform on every row.

Run it on a schedule

A one-off pull answers a question; a schedule answers it every day without you. Open Schedules in the Apify Console, point a cron at this Actor, and the dataset keeps filling on its own — no server, no cron box, no babysitting. Everything here is built to be re-run: you are billed per ad delivered, so a scheduled run that finds nothing new costs nothing.

FAQ

Do I need a Meta or Facebook account?

No. The Ad Library is public and this reads it directly.

Yes. Those variants are the ones most scrapers silently drop, and they are often the best-performing ones.

Can I search by advertiser instead of keyword?

Yes — keyword, advertiser or a pasted Ad Library URL.

Which countries can I filter to?

Any country the Ad Library covers, selected per run.


Something wrong, or a field you need that is missing? Open an issue on the Issues tab — it is read and it gets fixed. If this saved you time, a rating on the Store page helps the next person find it.