Meta Ad Library avatar

Meta Ad Library

Pricing

$1.49 / 1,000 ads

Go to Apify Store
Meta Ad Library

Meta Ad Library

Pricing

$1.49 / 1,000 ads

Rating

0.0

(0)

Developer

Lantern Lab

Lantern Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Meta Ad Library Scraper (Facebook & Instagram Ads)

Search the public Meta Ad Library by keyword or by advertiser Page and get every ad back as a row: the Library ID and link, the advertiser Page, whether it is still running, start and end date, the platforms it ran on (Facebook, Instagram, Messenger, Audience Network, Threads), the ad text, headline, link, button text, and the image and video URLs. For political and issue ads you also get the spend range, impressions range, currency and the "Paid for by" line. No Facebook login, no login cookies, no account of your own. $1.49 per 1,000 ads, no start fee. See Pricing.

Input:

{
"searchTerms": ["running shoes", "election"],
"pageUrls": ["https://www.facebook.com/nike"],
"country": "US",
"adType": "all",
"activeStatus": "active",
"mediaType": "all",
"maxItems": 200
}

Output - one row per ad (recordType: "ad"); per-target status rows and the run summary are free. Sample from a real run (video URL shortened):

{
"recordType": "ad",
"adArchiveId": "1134693002421653",
"url": "https://www.facebook.com/ads/library/?id=1134693002421653",
"pageId": "108107432370909",
"pageName": "Kalshi - Trade the Headlines",
"pageUrl": "https://www.facebook.com/KalshiTradeTheHeadlines/",
"paidForBy": "KALSHI INC.",
"isActive": true,
"startDate": "2026-10-11",
"endDate": null,
"platforms": ["FACEBOOK", "INSTAGRAM"],
"countries": [],
"searchCountry": "US",
"displayFormat": "VIDEO",
"bodyText": "Who will win the House? Trade it on Kalshi.",
"title": "Trade what's next",
"linkUrl": "http://itunes.apple.com/app/id1632713844",
"ctaText": "Install now",
"imageUrls": [],
"videoUrls": ["https://video.xx.fbcdn.net/o1/v/t2/f2/m366/AQP9wr8P….mp4?…"],
"collationCount": 2,
"impressionsRange": ">1M",
"spendRange": "$700K - $800K",
"currency": "USD",
"searchTerm": "election",
"rank": 3,
"partial": false,
"partialReason": null,
"collectedAt": "2026-10-24T09:55:03.118Z"
}

Limits:

  • Public data only. What the Ad Library shows a logged-out visitor: no targeting breakdowns (age, gender, region), no EU reach report, no ad-level demographic data. Spend, impressions and currency exist only for political and issue ads; for every other ad they are null.
  • Image and video URLs are Meta's signed CDN links and expire after a few days. Download what you need soon after the run.
  • Every search term and Page gets a status row saying what happened. A search that found nothing is an empty result; one cut short by a limit, a refusal or an error is partial with the reason - the two are never confused.
  • Your limits stop collection and appear in the row: maxItems, the maxUpstreamRequests request ceiling and the maximum charge per run (see Pricing).

What it does

  • Searches each keyword and each Page separately and labels every row with the target that produced it (searchTerm or searchPageId), so one run can cover many brands or topics.
  • Accepts Pages as a Facebook Page URL, a numeric Page ID, or an Ad Library link with view_all_page_id. For a Page URL the numeric Page ID is read from the Page's public page first.
  • Filters the way the Ad Library does: country (or all countries), ad category (all ads, or issues, elections and politics), active / inactive / both, media type, and exact-phrase matching.
  • Deduplicates across the whole run: an ad found by several of your search terms or Pages is written once and charged once.
  • Keeps the Ad Library's own identifier (adArchiveId), its start date as the calendar day the Ad Library page shows (startDate, plus publishedAt as an exact instant) and our collection time (collectedAt) as separate fields. endDate is null while an ad is still running.
  • Says what happened per target. A search the Ad Library answered with nothing is recorded as an empty result; one that was cut short is marked partial: true with the reason.
  • Caps itself: maxUpstreamRequests is a hard ceiling on requests to the Ad Library for the whole run, derived from your input when you leave it empty, so a run is never unbounded.
  • Charges only ad rows. Empty results, per-target status rows and the run summary are free.

What it does not do

  • No login, no account and no session cookies of your own: it reads only what the public Ad Library shows any visitor.
  • No targeting or audience data, no EU transparency report, no advertiser contact details.
  • It does not download images or videos; it returns their URLs.
  • No scheduling or monitoring: one run, one snapshot. Schedule the Actor on Apify if you need a recurring snapshot.

Input

FieldDefaultWhat it does
searchTerms–Keywords or phrases, searched like the Ad Library search box.
pageUrls–Facebook Page URLs, numeric Page IDs, or Ad Library links with view_all_page_id. Give search terms, Pages, or both.
countryALLALL, or a two-letter country code such as US, GB, DE, BR, JP.
adTypeallall, or political_and_issue_ads (the only category with spend, impressions and "Paid for by").
activeStatusactiveactive, inactive or all.
mediaTypeallall, image, video, meme, image_and_meme, none.
exactPhrasefalseMatch search terms as an exact phrase.
maxItems100Most ads one search term or Page may produce (up to 5,000).
maxUpstreamRequestsderivedHard ceiling on requests to the Ad Library for the whole run.
proxyConfigurationApify residentialThe Ad Library refuses to page results for datacenter IPs, so residential is the default and what the Actor is measured on.

Output

Three kinds of row, told apart by recordType:

  • ad - one per ad, the only charged row. Fields as in the sample above, plus pageCategories, pageLikeCount, categories, linkDescription, caption, ctaType, videoPreviewUrls, cardCount (carousel cards), collationId and reachEstimate.
  • target_status - one per search term or Page: adsReturned, adsCharged, duplicatesSkipped, upstreamRequests, partial, partialReason and a plain-language statusText.
  • RUN_SUMMARY - the last row, also saved as RUN_SUMMARY in the run's key-value store: totals, empty and partial targets by reason, requests sent and why collection stopped.

Partial is not empty

partial: true means a target's results are incomplete, never that it has no ads. partialReason says why:

ReasonMeaning
upstream_request_capThe run reached its maxUpstreamRequests ceiling while on this target.
charge_limit_reachedThe maximum charge you set for the run was reached.
blockedThe Ad Library refused our requests (rate limit or bot check) even after switching to a new proxy IP.
upstream_errorA request failed in a way retrying inside the run would not fix.
page_not_resolvedA Page URL whose numeric Page ID could not be read; pass the numeric ID instead.
not_collectedThe run stopped earlier for one of the reasons above and never reached this target.

A run that collected nothing because every target was refused ends as failed, not as an empty success.

Limits and boundaries

  • countries lists the countries the Ad Library publishes for an ad, which it does for only some ads (mostly EU-delivered and political ones); otherwise it is empty and searchCountry tells you which country filter found the ad.
  • The Ad Library returns ads 10 at a time in its own relevance order; rank is the position in that order for the target.
  • Ads that share one creative are grouped by the Ad Library (collationCount); each ad in a group is its own row.
  • Dynamic-creative ads store template text such as {{product.name}}; bodyText, title and linkDescription then carry the first card's text, which is what the Ad Library page shows. Catalog ads whose cards hold template text too keep the template, as the Ad Library itself does (about 2% of rows in our test runs). Tracking placeholders inside linkUrl are kept as the Ad Library lists them.
  • A browser is started once per run and reused for every target, so the first target of a run takes a few seconds longer.

Pricing

Pay per event, no start fee:

EventPriceCharged for
result$0.00149 ($1.49 per 1,000)Each ad row written. Per-target status rows, empty results and the run summary are free.

Set a maximum charge for the run and the Actor stops before going over it.