Facebook Ad Library Scraper — Meta Ads, Winners & Monitor avatar

Facebook Ad Library Scraper — Meta Ads, Winners & Monitor

Pricing

from $0.60 / 1,000 ad scrapeds

Go to Apify Store
Facebook Ad Library Scraper — Meta Ads, Winners & Monitor

Facebook Ad Library Scraper — Meta Ads, Winners & Monitor

Scrape the Meta (Facebook & Instagram) Ad Library by keyword, advertiser name, page or URL: copy, creatives, landing pages, days running, winning score, EU/UK reach & targeting included. $0.60/1,000 ads.

Pricing

from $0.60 / 1,000 ad scrapeds

Rating

0.0

(0)

Developer

Mr Zack

Mr Zack

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

8 days ago

Last modified

Share

Scrape the Meta Ad Library (Facebook, Instagram, Messenger, Threads, Audience Network) by keyword, by advertiser name (just type "gymshark" or paste facebook.com/gymshark — no page-ID hunting), by page ID, by single ad ID, or by pasting any Ad Library URL. Every ad comes back as one flat row: ad copy, headline, CTA, landing page, images, videos, carousel cards, start date, days running, versions, rank in Meta's impressions order and a transparent winning score.

Every ad also comes with what Meta publishes under "See ad details" — included in the price: reach (EU/UK) broken down by country, age and gender, targeting (age, gender, locations), payer & beneficiary, and the advertiser's Instagram handle, followers and verification.

$0.60 per 1,000 ads, details included. Duplicates, filtered-out ads and ads you already received in monitor mode are never charged. No login, no cookies, no API key, no browser. Deep paging runs through Apify residential proxy automatically (≈ $0.035 of proxy traffic per 1,000 ads on your Apify bill — measured: 450 ads with details in 88 s for $0.016 total platform usage).

Why this one

This Actor
Find an advertiser by name / @handle / page URL✅ resolved to the page ID automatically (exact match first, then verified / most-liked, alternatives in RUN_SUMMARY)
Winning-ad signals✅ daysActive, versionsCount, rankInQuery (Meta's impressions order) and a 0–100 winningScore on every row
Sort✅ impressions (Meta's default) or newest first for monitoring
EU/UK audience data✅ includeAdDetails (on by default, no extra charge): reach by country/age/gender, targeting, payer/beneficiary
Flat output✅ one clean row per ad, same columns every time — opens straight in Sheets/Excel, no nested snapshot to unpack
Deep paging✅ automatic: page 1 direct, deeper pages via residential proxy with IP rotation; parallel queries
Monitor mode✅ onlyNewAds — pay only for ads you haven't seen
Dynamic/catalog ads✅ {{product.name}} placeholders replaced by the real card copy
Honest empties✅ an empty result page is re-checked with a fresh session before we report "0 ads"
Price$0.60 / 1,000 ads, details included

Who this is for

  • Media buyers & performance marketers — find the ads that are actually working: an ad that has been running for 60+ days and has several versions is being paid for because it converts. Filter with minDaysActive.
  • E-commerce & dropshipping teams — see which products competitors push, with the exact landing pages (landingDomain, linkUrl) and creatives.
  • Agencies — pull a prospect's full ad footprint by page ID for a pitch deck, or schedule weekly competitor reports.
  • Creative strategists & copywriters — build swipe files of hooks, headlines and CTAs by niche keyword.
  • AI agents (MCP) — "what ads is brand X running on Instagram right now, and which have run the longest?" is one tool call with a predictable price.

What you get per ad

FieldExampleNotes
adArchiveId, libraryUrl925321173274919Open the ad in Meta's library
pageName, pageId, pageUrl, pageLikes, pageCategoriesNike, 15087023444The advertiser
isActive, startDate, endDate, lastSeenDatetrue, 2026-08-03Run window
daysActive53Days the ad has been running (to today, or to its end date)
isNewfalseStarted within newWithinDays (default 7)
versionsCount4How many near-identical versions Meta grouped together — a scaling signal
platformsfacebook, instagram, threadsWhere it is shown
displayFormatvideo / image / carousel / dpa / dcoCreative type (dpa/dco = catalog/dynamic ads)
bodyText, title, linkDescription, captionAd copy (dynamic {{product.name}} placeholders are replaced by the real card copy)
ctaText, ctaTypeShop Now, SHOP_NOWCall to action
linkUrl, landingDomainhttps://www.footlocker.com/…, footlocker.comDestination (Meta's l.facebook.com redirect is unwrapped)
primaryImageUrl, primaryVideoUrl, imageUrls, videosCreative media (HD + SD video, preview image)
cards, cardCountCarousel / catalog cards: title, body, link, image, video
spend, impressions, currency, disclaimerFilled for political & issue ads (Meta publishes these only there). spend = {lower, upper, text}, e.g. {40000, 45000, "£40K-£45K"}
reachEstimatePolitical & issue ads: Meta's reach bucket, e.g. >1M
containsAiGeneratedMediafalseMeta's AI-media label
rankInQuery3Position in Meta's result order (impressions high → low by default)
winningScore780–100: long run (≤40) + versions (≤20) + top impressions rank (≤25) + multi-placement (≤10) + still active (5)
reachTotal, reachRegion, reachByCountry, reachByAgeGender14565, EU, {"DE":14235}With includeAdDetails, for ads shown in the EU/UK
targetingAge, targetingGender, targetingLocations18-65, All, GermanyWith includeAdDetails
payer, beneficiaryALLBIRDS, INC.With includeAdDetails (EU DSA disclosure)
advertiserIgUsername, advertiserIgFollowers, advertiserVerification, advertiserAboutallbirds, 511773, BLUE_VERIFIEDFree for advertisers inputs; for every ad with includeAdDetails
searchQuery, searchCountry, scrapedAtWhich of your inputs produced the row

Every field is always present — null when Meta does not publish it, never a made-up value.

A free RUN_SUMMARY record (key-value store) adds per query: Meta's reported total, ads delivered, pages fetched, why a query stopped; and per advertiser: ads, active ads, new ads, format mix, platforms, top landing domains, oldest start date and longest-running ad.

Input

FieldDefaultWhat it does
searchTerms["nike"]Keywords / brands searched in all ad copy. Ad Library URLs pasted here work too
advertisers[]Every ad of an advertiser by name, @handle, facebook.com/… or instagram.com/… URL
pageIds[]Same, by numeric page ID (view_all_page_id=…) — pins the exact page
adIds[]Specific ads by Ad Library ID or ?id= link
adLibraryUrls[]Paste a search URL from facebook.com/ads/library — all its filters are applied
countryALLISO-2 country (US, GB, DE, BR, ID…) or ALL
activeStatusactiveactive, inactive or all
adTypeallor political_and_issue_ads, housing_ads, employment_ads, financial_products_and_services_ads
mediaTypeallimage, video, meme, image_and_meme, none
platformsallany of facebook, instagram, messenger, audience_network, threads, whatsapp
languagesallad language codes, e.g. ["en","es"]
exactPhrasefalsematch the search term as an exact phrase
sortByimpressionsimpressions (high → low, Meta's default) or newest
includeAdDetailstrueEU/UK reach by country/age/gender, targeting, payer/beneficiary, advertiser Instagram (included in the price)
useResidentialForPagingtruePage past the first 30 ads per query through Apify residential proxy (≈ $0.035 / 1,000 ads proxy traffic)
activeFrom / activeTo—Meta's date filter: ads shown in this window (they may have started earlier)
startedAfter—only ads launched on/after this date (new campaigns) — filtered ads are free
maxAdsPerQuery100cap per search / page / URL
minDaysActive0only ads running at least N days (winning ads) — filtered ads are free
newWithinDays7window for the isNew flag
onlyNewAdsfalsemonitor mode — see below
proxyConfigurationApify Proxysee "Depth & proxies"

Example — winning ads in a niche

{ "searchTerms": ["protein powder"], "country": "US", "minDaysActive": 30, "maxAdsPerQuery": 200 }

Example — everything two competitors run, with EU audience data

{ "advertisers": ["gymshark", "https://www.instagram.com/allbirds/"], "country": "DE", "includeAdDetails": true }

Example — newest ads in a niche (daily monitor)

{ "searchTerms": ["ai note taker"], "country": "US", "sortBy": "newest", "onlyNewAds": true }

Schedule it: competitor monitor

Turn on onlyNewAds and schedule the Actor daily or weekly (Console → Schedules). The Actor remembers every ad ID it has seen per query (in a named key-value store in your account) and delivers — and charges — only ads that are new since the last run. Connect the dataset to Slack, email, Google Sheets or a webhook and you have a free-running "competitor launched a new ad" alert.

With sortBy: "newest" (recommended for monitoring) the Actor stops each query as soon as it reaches the ads it already delivered last time — so a quiet day costs almost nothing, and older ads that the previous run simply did not reach are never sold to you as "new".

Tip: with the default impressions sort, set maxAdsPerQuery at least as high as the number of ads you want to watch (e.g. an advertiser's full active count), so every run covers the whole set.

For AI agents & MCP

  • Minimal input: {"advertisers": ["<brand name>"]} or {"searchTerms": ["<keyword>"]}. Everything else has a sensible default.
  • Output: one row per ad, flat JSON, stable field names (table above). daysActive + versionsCount answer "which ads work"; landingDomain answers "where does the traffic go".
  • Price is predictable: $0.0006 per ad delivered, details included. Cap spend with maxAdsPerQuery or the run's max charge.
  • Empty is not an error: a keyword with no ads ends SUCCEEDED with 0 rows and a clear status message. Short hiccups are retried inside the run (fresh sessions after 20 s and 45 s); only a Meta outage that survives every retry ends FAILED so your pipeline can alert. Short run timeouts end SUCCEEDED with whatever was collected.

Depth & proxies (honest limits)

Meta serves the first page of every search (up to 30 ads) to anyone, but rate-limits deeper paging from datacenter IPs. The Actor handles this for you: page 1 and ad details go direct (free), deeper pages go through Apify residential proxy with automatic IP rotation when an exit IP gets limited. That traffic is small (≈ 0.4 MB per 100 ads) and appears on your Apify bill as residential proxy usage (≈ $0.035 per 1,000 ads). If your plan has no residential proxy, you still get the first page of every query and the status message says so. You can also plug in your own proxy in Proxy configuration.

Other limits: Meta shows spend/impressions only for political & issue ads, and reach/targeting data only for ads delivered in the EU or UK. Deleted ads and ads Meta hides from the library cannot be returned.

FAQ

Is this legal? The Actor reads only the public Ad Library that Meta publishes for transparency, without logging in. You are responsible for how you use the data (e.g. GDPR if you process personal data of EU persons).

Why is bodyText empty on a few ads? Some image-only or dynamic ads have no copy text. Their cards (cards) usually still carry title and link.

Why do I get fewer ads than Meta's reported total? maxAdsPerQuery, filters (minDaysActive, startedAfter) and datacenter paging limits all reduce the count; RUN_SUMMARY.queries[].limitedBy tells you which one applied.

  • Brand Ads Spy — Google + LinkedIn (tactful_anvil/brand-ads-cross-network-spy) — the same brand across Google and LinkedIn ad libraries.
  • Ad Budget Signals (tactful_anvil/ad-budget-signals) — does a list of domains run ads at all? One row per domain.
  • Google Ads Transparency Scraper (tactful_anvil/google-ads-transparency-scraper).

Changelog

  • 0.2.1 (2026-09-28) — hardening from a 24-case cloud test matrix: runs with short timeouts now deliver (reserves scale with the run), 256 MB runs no longer run out of memory, one ad-details session per route (much less proxy traffic), one ad without details no longer switches details off for the rest of the run, monitor mode stops at last run's ads (newest sort), political spend and reachEstimate filled again (Meta switched them to text), dead targetedCountries column removed, patient retries before any failure, watchdog finishes the run before a platform timeout.

  • 0.2.0 (2026-09-25) — advertiser name/URL lookup, single ads by ID, sortBy newest, rankInQuery + winningScore, ad details included (EU/UK reach, targeting, payer/beneficiary, advertiser Instagram), automatic residential paging with IP rotation, 3 queries in parallel, empty-page re-checks.

  • 0.1.0 (2026-09-25) — first release: keyword / page / URL search, SSR + GraphQL paging with automatic route fallback, dynamic-ad placeholder fix, winning-ad filter, startedAfter, monitor mode, per-advertiser summary.