Facebook Ads Library Scraper avatar

Facebook Ads Library Scraper

Pricing

from $0.60 / 1,000 ad records

Go to Apify Store
Facebook Ads Library Scraper

Facebook Ads Library Scraper

Scrape Meta Ad Library ads (Facebook, Instagram, Messenger, Threads) by keyword, advertiser page or Ad Library URL: ad text, headline, CTA, landing page, images, videos, carousel cards, run dates and platforms.

Pricing

from $0.60 / 1,000 ad records

Rating

0.0

(0)

Developer

Roman

Roman

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 hours ago

Last modified

Categories

Share

Scrape ads from the Meta Ad Library (Facebook, Instagram, Messenger, Threads, Audience Network) by keyword, advertiser page or any Ad Library URL, and get clean, structured data: ad text, headline, CTA, landing page, images, videos, carousel cards, run dates and platforms.

No login, no cookies, no browser. It uses the same API the Ad Library website uses, so it is fast and cheap: about 1,000 ads in under 2 minutes. Pair it with the Google Ads Transparency Scraper to see a competitor's ads on Google and Meta side by side.

What you get for every ad:

  • ✍️ Ad copy: primary text, headline, link description, caption, call-to-action text and type.
  • 🔗 Landing page URL: where the ad sends people.
  • 🖼️ Media: preview image, all image URLs, HD video URLs and video thumbnails.
  • 🎠 Carousel and dynamic ads: every card with its own title, text, link and media. Catalog templates like {{product.name}} are replaced with real product names.
  • 📅 Run dates: start date, end date, days active, active or not. Ads that run for months are usually the winners.
  • 📱 Platforms: Facebook, Instagram, Messenger, Threads, Audience Network.
  • 🏢 Advertiser: page name, ID, URL, categories, likes and profile picture.
  • 🗳️ Political and issue ads: spend range, impressions range, currency and "Paid for by" line.
  • 🤖 AI label: whether Meta marks the media as digitally created or altered.
  • 🇪🇺 EU reach, demographics and targeting (optional): people reached in the EU, UK and Brazil, a breakdown by country, age and gender, the targeted locations, gender and ages, payer and beneficiary, plus the advertiser's Instagram account and followers.
  • 🔔 Monitoring: give a search a name and schedule it. Each run returns only ads you have not seen yet, so you pay only for new ones.

Use cases

  • Competitor research: see every ad a competitor runs right now and which creatives have run the longest.
  • Ad copy swipe files: export hundreds of hooks, headlines and CTAs from a niche into a spreadsheet.
  • Creative inspiration: collect the video and image URLs of the top ads in your market.
  • Agency pitches and audits: show a prospect what their competitors run, by country and platform.
  • Dropshipping and e-commerce: find products that brands keep advertising for weeks.
  • Political ad monitoring: track spend and impressions of issue and election ads.

Input

FieldDescription
queriesOne per line: a keyword (running shoes), a page URL (https://www.facebook.com/nike), a page ID (15087023444) or an Ad Library URL copied from your browser
countryTwo-letter country code where the ads were shown (US, DE…) or ALL
activeStatusActive ads, inactive ads, or both
adTypeAll ads, or issues, elections and politics (adds spend and impressions)
mediaTypeImages, videos, memes, no media, or all
platformsFacebook, Instagram, Messenger, Audience Network, Threads (empty = all)
exactPhraseMatch the keyword as an exact phrase
languagesAd language codes (en, es…)
dateFrom / dateToOnly ads shown in this date range
includeAdDetailsAdd EU/UK/Brazil reach, demographics, targeting, payer and beneficiary, and the linked Instagram account (one extra request per ad)
monitorNameName a search to get only new ads on each run (see Monitoring new ads)
maxAdsPerQueryLimit per input line (0 = everything)
maxConcurrencyHow many queries run in parallel
{
"queries": ["running shoes", "https://www.facebook.com/nike"],
"country": "US",
"activeStatus": "active",
"platforms": ["instagram"],
"maxAdsPerQuery": 200
}

When you paste an Ad Library URL, its filters (country, status, media type, platforms, languages, dates, search type) are used, so you can set up a search on the website and copy the address bar.

Output example

{
"query": "protein powder",
"adArchiveId": "28415581214739236",
"adLibraryUrl": "https://www.facebook.com/ads/library/?id=28415581214739236",
"pageId": "139311472851666",
"pageName": "Bigbasket",
"pageUrl": "https://facebook.com/Bigbasketcom",
"pageCategories": ["Shopping"],
"pageLikeCount": 825682,
"isActive": true,
"startDate": "2026-09-01",
"endDate": "2026-10-16",
"daysActive": 46,
"publisherPlatforms": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER", "THREADS"],
"displayFormat": "DPA",
"body": "Shop from over 30,000+ products & get groceries delivered at your doorstep. Install the bigbasket app & Shop now!",
"title": "Epigamia Greek Yogurt - Vanilla Bean 85 g Cup",
"caption": "play.google.com",
"linkUrl": "http://play.google.com/store/apps/details?id=com.bigbasket.mobileapp",
"ctaText": "Install now",
"ctaType": "INSTALL_MOBILE_APP",
"previewImageUrl": "https://scontent.xx.fbcdn.net/v/t39.35426-6/581959359_..._n.jpg",
"imageUrls": ["https://scontent.xx.fbcdn.net/v/t39.35426-6/581959359_..._n.jpg"],
"videoUrls": [],
"cards": [
{"title": "Epigamia Greek Yogurt - Vanilla Bean 85 g Cup", "body": "Shop from over 30,000+ products...",
"linkUrl": "http://play.google.com/store/apps/details?id=com.bigbasket.mobileapp", "imageUrl": "https://scontent.xx.fbcdn.net/..."}
],
"collationCount": 1,
"containsAiGeneratedMedia": false
}

Political and issue ads also include byline, currency, spend (for example "100-199") and impressions.

With includeAdDetails

Meta publishes reach and demographics for every ad shown in the EU (Digital Services Act), the UK and Brazil, not only for political ads. With includeAdDetails on, each such ad also gets:

{
"euTotalReach": 9014345,
"ukTotalReach": 2493788,
"targetsEu": true,
"audienceLocations": [{"name": "Italy", "type": "countries", "excluded": false}, {"name": "Netherlands", "type": "countries", "excluded": false}, {"name": "Spain", "type": "countries", "excluded": false}, {"name": "Poland", "type": "countries", "excluded": false}, {"name": "France", "type": "countries", "excluded": false}, {"name": "Germany", "type": "countries", "excluded": false}],
"audienceGender": "All",
"audienceAgeMin": 18,
"audienceAgeMax": 65,
"reachByCountry": {"GB": 2492528, "FR": 2210082, "DE": 1647371},
"reachByGender": {"male": 6313826, "female": 5228999, "unknown": 136635},
"reachByAge": {"18-24": 1208148, "25-34": 4004398, "35-44": 3684762},
"reachBreakdown": [{"region": "EU", "country": "DE", "ageRange": "18-24", "male": 111268, "female": 69215, "unknown": 2817}],
"payer": "NIKE, Inc.",
"beneficiary": "NIKE, Inc.",
"pageInstagramUsername": "nike",
"pageInstagramFollowers": 290970338
}

Ads that were never shown in the EU, UK or Brazil have no such data. They still get the Instagram fields, and you are not charged the detail fee for them.

Monitoring new ads

Track competitors without paying twice for the same ads:

  1. Fill in queries and filters as usual and set monitorName, for example competitors-de.
  2. Save the input as a Task and add an Apify Schedule (daily or weekly).
  3. The first run returns every matching ad. Each later run with the same monitorName returns only ads that earlier runs have not returned. Old ads are skipped and not charged.

Connect a webhook or the Slack / email integration to the Task to get new ads delivered. The list of seen ads is stored in the facebook-ads-monitor key-value store in your account. To start over, use a new monitorName or delete its record from that store.

Pricing

Pay per result: $0.60 per 1,000 ads. No extra fee per run beyond the Apify default.

EU reach and demographics (includeAdDetails): +$0.75 per 1,000 ads that have them. Ads without EU, UK or Brazil data are not charged this fee.

Set a maximum cost per run in the Apify Console, and the scraper stops cleanly when it is reached.

Tips

  • Keep Apify Proxy with the Residential group, which is the default. Traffic is tiny, about 3 MB per 1,000 ads.
  • Meta returns about 10 ads per request, so 1,000 ads take about 100 requests. Run several queries at once to go faster.
  • Big brands have thousands of ads. Narrow with country, platforms, mediaType and dates, or set maxAdsPerQuery.
  • New Facebook pages have a profile ID in the URL that differs from the Ad Library page ID. The scraper resolves it automatically, but if a page returns nothing, open its "Page transparency" section or Ad Library page and paste that URL instead.
  • In monitor mode maxAdsPerQuery counts all ads checked, new and old. Leave it at 0 or set it above the advertiser's total so new ads are not missed.
  • To get a single ad, paste its link: https://www.facebook.com/ads/library/?id=<ad ID>.

Integrations, API and MCP

REST API. Run the Actor and get the results in one call (replace YOUR_APIFY_TOKEN; it's in Console → Settings → API & Integrations):

curl -X POST "https://api.apify.com/v2/acts/wakeful_outhouse~facebook-ads-library-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer YOUR_APIFY_TOKEN" -H "Content-Type: application/json" \
-d '{"queries": ["https://www.facebook.com/nike"], "country": "US", "maxAdsPerQuery": 50}'

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("wakeful_outhouse/facebook-ads-library-scraper").call(run_input={"queries": ["https://www.facebook.com/nike"], "country": "US", "maxAdsPerQuery": 50})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

AI agents (MCP). Give Claude, Cursor or any MCP client this Actor as a tool through the Apify MCP server:

  • hosted: https://mcp.apify.com?tools=wakeful_outhouse/facebook-ads-library-scraper
  • local: npx -y @apify/actors-mcp-server --actors wakeful_outhouse/facebook-ads-library-scraper (set APIFY_TOKEN)

No-code. Use the Apify integrations for Make, Zapier, n8n, Google Sheets, Slack and webhooks: for example, run the Actor on a Schedule and send each new competitor ad to a Slack channel or append the ad copy to a Google Sheet. All formats are available as JSON, CSV, Excel and HTML from the dataset.

More ad-intelligence tools

Same author, same data format, same pay-per-result pricing:

  • Google Ads Transparency Scraper — ad copy, YouTube IDs, impressions and regions from the Google Ads Transparency Center.
  • Google Trends Scraper — interest over time, interest by region, related queries and today's trending searches by country, to see which keywords are rising.
  • LinkedIn Ad Library Scraper — B2B ad copy, CTAs, landing pages, media, impressions by country and targeting from the LinkedIn Ad Library.

All tools: https://apify.com/wakeful_outhouse

FAQ

Is it legal? The Meta Ad Library is a public database Meta publishes so anyone can inspect ads. The scraper collects only what the website shows publicly without logging in. You are responsible for how you use the data.

Why are spend and impressions empty? Meta publishes spend and impressions only for political and issue ads. Set adType to issues, elections and politics to get them. For any ad shown in the EU, UK or Brazil you can get the number of people reached and the demographics with includeAdDetails.

Why does a keyword return ads that don't contain it? Meta matches any of the words and related terms. Turn on exactPhrase for stricter matching.

Something broke? Open an issue on the Issues tab with the run link. Fixes usually ship within a day.