Facebook Ads Library Scraper avatar

Facebook Ads Library Scraper

Pricing

from $2.72 / 1,000 ads

Go to Apify Store
Facebook Ads Library Scraper

Facebook Ads Library Scraper

Scrape the Meta Ad Library without login: ads from any Facebook page, keyword or Ad Library URL, in every country — creatives, copy, CTA, links, platforms, dates, spend and reach, advertiser details and the products behind each ad. Exact results limit. Pay per ad.

Pricing

from $2.72 / 1,000 ads

Rating

0.0

(0)

Developer

Badr Bouargan

Badr Bouargan

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Categories

Share

Facebook Ads Library Scraper – Meta, Instagram Ads & Spend

Get every ad of any brand, page or keyword from the Meta Ad Library in a clean spreadsheet, in seconds, without a Facebook account.

Scrape the Meta Ad Library (Facebook Ads Library): ad copy, creatives (images, videos, carousels), CTA, destination links, platforms (Facebook, Instagram, Messenger, Threads, WhatsApp, Audience Network), start and end dates, spend and reach when Meta publishes them, advertiser details, and the products and prices behind each ad. Your results limit is exact: you never get, or pay for, more ads than you asked for.

How to use it in 3 steps

  1. Paste what you want to watch: a Facebook page URL (https://www.facebook.com/nike), any Meta Ad Library URL (set your filters on facebook.com/ads/library and copy the address bar), or type keywords such as running shoes in Search keywords / page names.
  2. Set the results limit per URL or keyword (for example 50).
  3. Click Start. Ads appear in the Ads table during the run; export them to CSV, Excel or JSON.

The prefilled example (20 Sephora ads) finishes in about 10 seconds and costs under $0.10.

What can it do?

  • 🧩 Ads published across Meta platforms: Facebook, Instagram, Messenger, Threads, WhatsApp and Audience Network
  • 🔎 Any Ad Library search: brand, keyword, country, language, media type, active or inactive, ad category. Paste the URL and every filter in it is kept
  • 🔤 Keyword search without building a URL: type black friday and choose a country (or ALL)
  • 🎯 A single ad: paste https://www.facebook.com/ads/library/?id=…
  • 🌍 Every country at once (ALL) or one country
  • 📅 Date range, sorting (impressions or most recent) and active status
  • 🏢 Advertiser details: Instagram username and followers, page likes, category, verification, page spend, related pages in other countries
  • 💸 Spend, reach, impressions and EU audience (age, gender, country, payer and beneficiary) when Meta publishes them
  • 🛒 E-commerce enrichment: the product, price, brand and rating behind each ad's link
  • 🔢 Only the total number of ads of a page, for quick market sizing
  • 📤 Export to JSON, CSV, Excel, XML or HTML, or use the API, webhooks, Make, Zapier, n8n or the Apify MCP server

Use it for competitor ad research, creative inspiration, market and pricing intelligence, and transparency or regulatory reporting.

What you can paste

You pasteWhat you get
https://www.facebook.com/SHEINOFFICIAL (also m., web., fb.com, /pg/…)All ads of that page
https://www.facebook.com/profile.php?id=100064… or /people/Name/100064…/All ads of that page
https://www.facebook.com/ads/library/?…&view_all_page_id=…That advertiser, with the URL's filters
https://www.facebook.com/ads/library/?…&q=shoes&country=FRThat search, with the URL's filters
https://www.facebook.com/ads/library/?id=1106694961565426That one ad
Keyword: running shoes (in Search keywords / page names)Ads whose text matches, in the chosen country
Page name: @nikeAll ads of that page

Several URLs pasted on one line (separated by commas or new lines), duplicates and extra spaces are cleaned up automatically. Anything that is not Facebook (an Instagram link, a Facebook group) is skipped and listed in FAILED_INPUTS, never billed. With an empty input, the Actor runs the Sephora example and says so in the log.

Input example

{
"startUrls": [
{ "url": "https://www.facebook.com/SHEINOFFICIAL" },
{ "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&media_type=image&search_type=page&view_all_page_id=15087023444" }
],
"searchQueries": ["running shoes", "@nike"],
"resultsLimit": 50,
"country": "US",
"activeStatus": "active",
"sorting": "total_impressions",
"onlyAdsNewerThan": "3 months",
"isDetailsPerAd": false,
"enrichWithEcommerceData": false
}

The input uses the same field names as the Store's reference Facebook Ads scraper (startUrls, resultsLimit, onlyTotal, isDetailsPerAd, includeAboutPage, activeStatus, …), so an existing input works as it is.

Output example

One row per ad (shortened; real row from a run):

{
"inputUrl": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&media_type=all&search_type=page&view_all_page_id=16453004404",
"facebookUrl": "https://www.facebook.com/sephora/",
"pageID": "16453004404",
"adArchiveID": "1570487428042958",
"pageName": "Sephora",
"isActive": true,
"startDateFormatted": "2026-08-01T07:00:00.000Z",
"endDateFormatted": "2026-10-09T07:00:00.000Z",
"startDate": 1785567600,
"endDate": 1791529200,
"publisherPlatform": ["FACEBOOK", "INSTAGRAM", "MESSENGER", "THREADS"],
"categories": ["UNKNOWN"],
"collationCount": null,
"spend": null,
"reachEstimate": null,
"impressionsWithIndex": { "impressionsText": null, "impressionsIndex": -1 },
"snapshot": {
"pageName": "Sephora",
"pageProfileUri": "https://www.facebook.com/sephora/",
"pageLikeCount": 20340746,
"pageCategories": ["Health/beauty"],
"title": "{{product.name}}",
"body": { "text": "Shop these picks, thank yourself later 💖" },
"caption": "sephora.com",
"ctaText": "Shop now",
"ctaType": "SHOP_NOW",
"linkUrl": "http://www.sephora.com/",
"displayFormat": "DPA",
"cards": [{ "body": "Shop these picks, thank yourself later 💖", "ctaType": "SHOP_NOW", "originalImageUrl": "https://scontent.xx.fbcdn.net/…" }],
"images": [],
"videos": []
}
}

With extra ad details, each row gets ad_details (advertiser page and Instagram data, page spend, EU audience and reach). With About, it gets pageInfo. With e-commerce, it gets ecommerceData:

{ "ecommerceData": [{ "name": "Soft Pinch Liquid Blush", "offers": { "price": 25, "priceCurrency": "USD" },
"brand": { "slogan": "Rare Beauty" }, "rating": 4.6, "reviewCount": 1820, "url": "https://www.sephora.com/product/…" }] }

With Get only the total ad count, you get one row per URL: { "inputUrl": "…", "pageID": "16453004404", "totalCount": 1680, "url": "…" }.

Every run also writes two records in the key-value store:

  • RUN_SUMMARY: { "status": "SUCCEEDED", "adsSaved": 13, "productsBilled": 0, "urls": 7, "failedInputs": 2, "stoppedByBudget": false, … }
  • FAILED_INPUTS: what gave nothing, with the reason (never billed), e.g. { "input": "https://www.instagram.com/nike/", "type": "invalidInput", "reason": "Skipped: not a Facebook page URL or Meta Ad Library URL. …" }

Pricing

Pay per event. Platform usage is included, and there is no start fee.

EventFreeStarterScaleBusiness
Ad (or one total with onlyTotal)$4.64 / 1,000$4.00 / 1,000$3.36 / 1,000$2.72 / 1,000
Add-on: E-commerce enrichment (per product found)$4.56 / 1,000$2.56 / 1,000$2.24 / 1,000$1.92 / 1,000

Example: 1,000 ads on the Free plan = $4.64. The results limit is exact, and you can also cap any run with a maximum cost per run: the Actor stops cleanly before going over it. Failed inputs are never billed.

What it can and cannot do

✅ Can❌ Cannot
Every ad Meta shows logged-out visitors in the Ad Library, in every countryAds Meta does not show in the Ad Library
Spend, reach and impressions when Meta publishes them (political, social-issue and EU-targeted ads)Spend or reach of ordinary commercial ads outside the EU: Meta publishes none
Page name, URL, photo, description, related pages (About)Confirmed owner, address and page history (shown only to signed-in users)
Products behind real product pagesCatalog templates ({{product.name}}), sign-up pages and app links (skipped, not billed)
Keyword search exactly like the Ad Library search boxBetter relevance than Meta's own search (keywords match words anywhere in the ad)

FAQ

Do I need a Facebook account, cookies or the Meta API? No.

Can I scrape all countries? Yes: country is ALL by default, or paste an Ad Library URL with any country.

How many ads can I get? Everything the Ad Library lists for your search. Leave the limit empty for all ads; a big brand can have thousands.

Why is totalCount 50001? The Ad Library stops counting at 50,000: 50001 means "more than 50,000 ads".

How fast is it? About 30 ads every few seconds. Extra ad details add one request per ad.

Why do some keyword results look unrelated? Meta's keyword search matches the words anywhere in the ad (text, page, links). For exact results, open the Ad Library, search with quotes ("running shoes"), and paste that URL.

Is it legal? The Actor only collects data Meta makes public in the Ad Library. Some of it may be personal data under the GDPR: use it for a legitimate purpose only.

Troubleshooting

  • A URL is in FAILED_INPUTS with "not found": the page has no ads in the Ad Library, or its alias is different. Open the page in the Ad Library, select it, and paste that URL (it contains view_all_page_id).
  • "No ads match these settings": your filters (active status, dates, country) exclude every ad. Try activeStatus = Active and inactive, or country ALL.
  • "Partial: Facebook rate-limited": Facebook slowed the run down after many pages. You keep (and pay for) only what was saved; run again later for the rest.
  • The run stopped early: check RUN_SUMMARY: stoppedByBudget: true means your maximum cost per run was reached.
  • Something else? Open an issue on the Issues tab with your run ID.

Use it via API

Python (pip install apify-client)

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("badr_xba/facebook-ads-library-scraper").call(run_input={
"startUrls": [{"url": "https://www.facebook.com/nike"}],
"searchQueries": ["running shoes"],
"resultsLimit": 50,
"country": "US",
})
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
print(ad["pageName"], ad["adArchiveID"], (ad.get("snapshot") or {}).get("linkUrl"))

JavaScript (npm install apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('badr_xba/facebook-ads-library-scraper').call({
startUrls: [{ url: 'https://www.facebook.com/nike' }],
searchQueries: ['running shoes'],
resultsLimit: 50,
country: 'US',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'ads');

cURL (runs the Actor and returns the ads in one call)

curl -X POST "https://api.apify.com/v2/acts/badr_xba~facebook-ads-library-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"startUrls":[{"url":"https://www.facebook.com/nike"}],"resultsLimit":20}'

Integrations

Connect the results to Make, Zapier, n8n, Google Sheets, Slack or any webhook from the Integrations tab, schedule daily runs to track competitors' new ads, or let an AI agent call it through the Apify MCP server (mcp.apify.com).