Facebook Ads Library Scraper & Ad Monitor
Pricing
from $0.30 / 1,000 ads
Facebook Ads Library Scraper & Ad Monitor
Scrape the Meta Ad Library by keyword, Facebook Page or Ad Library URL: ad copy, media, start dates, days running, platforms, landing pages, EU reach and political spend. For competitor research, ad spying and brand monitoring, with only-new-ads alerts. No login, no browser.
Pricing
from $0.30 / 1,000 ads
Rating
0.0
(0)
Developer
PANIX AI LAB
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrape ads from the Meta Ad Library (Facebook, Instagram, Messenger, Threads, WhatsApp and Audience Network) by keyword, Facebook Page or pasted Ad Library URL. Each ad is one clean row: ad copy, headline, call to action, landing page, images, videos with their length, carousel cards, start date, days running, platforms, and spend, impressions and reach where Meta publishes them. Turn on ad details to add EU reach by country, age and gender, payer and beneficiary, and the advertiser's Instagram followers.
No Facebook login, cookies, Meta API token or browser. Runs start in seconds, results appear while the run is going, and you pay only for ads you receive.
What you can do with it
- 🔎 Search by keyword in one or many countries at once, without building URLs:
"running shoes"in US, GB and DE is one input. - 🏢 Get every ad of a competitor: paste
https://www.facebook.com/nike, a numeric Page ID, or an Ad Library page link. - 🔗 Paste any Ad Library URL: every filter in it is kept (country, status, category, media type, platforms, languages, dates, sort order, exact phrase). Single-ad links (
?id=...) return that one ad. - 🏆 Find winning ads: keep only ads that have run for at least N days, or ads launched in the last 7 days.
- 🔁 Monitor on a schedule: name a watchlist and receive only ads you have not received before. Repeats are not charged.
- 🌍 EU transparency data (optional): reach by country, age and gender, targeted age and gender, payer and beneficiary, advertiser Instagram followers, likes and verification.
- 🧮 Count ads without downloading them: how many active ads does a brand or keyword have right now?
- 🤖 AI-ready: optional Markdown per ad for ChatGPT, Claude or a RAG pipeline, plus a summary per advertiser.
Who uses it
- Marketers and media buyers: see which offers, hooks and creatives competitors run, and for how long.
- Agencies: audit a prospect's ads before a pitch, or list the businesses advertising on a keyword in a country.
- E-commerce and dropshipping: spot products and landing pages that advertisers keep paying to promote.
- Brand monitoring: a daily watchlist reports new ads that mention your brand or come from your competitors.
- Researchers and journalists: political and issue ads with spend, impressions and "paid for by", plus EU reach.
- AI and data teams: clean JSON or Markdown for dashboards, LLM analysis and RAG pipelines.
Why this scraper
- Every way in, in one run: keywords, Facebook Pages (URL or ID) and pasted Ad Library URLs together, and each keyword in as many countries as you pick.
- Pasted URLs keep every filter, including dates, languages, platforms, sort order and exact phrase.
- Filters for winning ads: minimum days running, a launch-date window that is checked on every ad, one row per creative group, and one ad per advertiser.
- Monitoring built in: watchlists return only new ads on scheduled runs, and repeats are free.
- More useful columns: days running, video length, landing domain, UTM tags, carousel cards, political spend as numbers, optional EU reach and audience, and Markdown for AI.
- Exact limits, no hard caps: you get exactly the number of ads you ask for, from 1 to everything Meta returns, on every Apify plan.
- Results while it runs, plus a SUMMARY record that explains each source: totals, filters and errors.
- Low price: $0.50 per 1,000 ads on the Starter plan plus $0.003 per run. Failed sources, duplicates and filtered ads are free.
Coming from another Ad Library scraper?
| Problem people often run into | How this Actor handles it |
|---|---|
| Only Ad Library URLs are accepted, so you build URLs by hand | Type keywords, Page URLs or Page IDs, or paste URLs |
| One country per run | Pick several countries; each keyword runs in each one |
| The date filter returns ads that started long before your dates | startDateFrom and startDateTo mean "started running between", checked on every ad |
| No way to find long-running ("winning") ads | minDaysRunning |
| The same creative comes back many times | skipDuplicateVersions, plus de-duplication across all inputs |
| Daily runs charge again for ads you already have | A watchlist with onlyNewAds; repeats are not charged |
| Results appear only when the run ends | Ads are saved page by page as they arrive |
| Limits overshoot, or each search is capped | Exact limits, no caps |
| One blocked request fails the whole run | Retried from a new IP address, from the same results page |
Reliability. When Meta blocks a request, it is retried from a new IP address and continues from the same results page, so a block costs seconds instead of the run. Sources that still fail are listed in the run summary with a reason and are never charged. If Meta retires one of its internal query IDs, the Actor reads the current ones from Meta's own web app and carries on.
How to use it
- Click Try for free and open the Input tab.
- Add search terms, Facebook Pages or Ad Library URLs (you can mix them).
- Pick countries and filters, and set Max ads per source.
- Click Start. Ads appear in the Output tab within seconds.
- Download as JSON, CSV, Excel or HTML, or connect the results to your tools (see API and integrations below).
Input examples
Keyword search in three countries
{"searchTerms": ["running shoes", "protein powder"],"countries": ["US", "GB", "DE"],"maxAdsPerSource": 100}
Every active ad of your competitors
{"pageUrls": ["https://www.facebook.com/nike", "https://www.facebook.com/adidas", "15087023444"],"countries": ["ALL"],"activeStatus": "active","maxAdsPerSource": 0}
Winning ads: video ads that have run for 30+ days, one per creative
{"searchTerms": ["skincare"],"countries": ["US"],"mediaType": "video","minDaysRunning": 30,"skipDuplicateVersions": true,"maxAdsPerSource": 200}
New launches from the last 7 days, newest first
{"searchTerms": ["black friday"],"countries": ["US"],"startDateFrom": "7 days","maxAdsPerSource": 300}
Daily competitor monitor: only ads you have not received yet (save this as a scheduled task)
{"pageUrls": ["https://www.facebook.com/nike"],"monitoringKey": "nike-daily","onlyNewAds": true,"maxAdsPerSource": 500}
Paste an Ad Library URL with any filters you set on facebook.com (political ads in the UK in this example), plus EU reach and advertiser details
{"startUrls": [{"url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=political_and_issue_ads&country=GB&media_type=all&q=energy&search_type=keyword_unordered"}],"includeAdDetails": true,"maxAdsPerSource": 50}
How many ads? Counts only
{"searchTerms": ["coffee", "yoga mat"],"pageUrls": ["https://www.facebook.com/shopify"],"countries": ["US"],"countOnly": true}
Output
One row per ad. A real row from a run on 29 October 2026 (with ad details on, media links shortened):
{"adArchiveId": "1454592559544426","adLibraryUrl": "https://www.facebook.com/ads/library/?id=1454592559544426","isActive": true,"status": "ACTIVE","startDate": "2026-05-13","lastSeenDate": "2026-10-29","daysRunning": 170,"pageId": "1917715138510680","pageName": "Follow Your Legend","pageUrl": "https://www.facebook.com/followyourlegend/","pageCategories": ["Brand"],"pageLikeCount": 124078,"platforms": ["facebook", "instagram", "audience_network", "messenger", "threads"],"displayFormat": "VIDEO","mediaType": "video","bodyText": "AlpacaCloud is our custom-engineered blend of alpaca fiber and eucalyptus fiber—crafted to deliver the softest, most breathable socks you’ve ever worn. ...","title": "Your feet deserve better than basic socks.","ctaText": "Shop now","ctaType": "SHOP_NOW","linkUrl": "https://followyourlegend.com/pages/alpacacloud%C2%AE-socks-for-running","linkDomain": "followyourlegend.com","videos": [{"hdUrl": "https://video-xxc1-1.xx.fbcdn.net/...", "sdUrl": "https://video-xxc1-1.xx.fbcdn.net/...", "previewImageUrl": "https://scontent-xxc1-1.xx.fbcdn.net/...", "durationSeconds": 44}],"videoDurationSeconds": 44,"categories": ["UNKNOWN"],"containsAiGeneratedMedia": false,"mediaUrlsExpireAt": "2026-11-03T08:57:18Z","sourceType": "searchTerms","searchTerm": "running shoes","searchCountry": "DE","positionInSource": 6,"totalAdsInSource": 6993,"euTotalReach": 144059,"payer": "Follow Your Legend","beneficiary": "Follow Your Legend","advertiserInstagramUsername": "followyourlegend","advertiserInstagramFollowers": 406804,"details": {"euReachByCountry": {"DE": 20548, "DK": 13194, "SE": 12541, "IT": 11373},"euReachByAgeGender": {"18-24": {"male": 12734, "female": 1645, "unknown": 978}},"audienceGender": "All", "audienceAgeMin": 18, "audienceAgeMax": 65},"scrapedAt": "2026-10-29T21:37:24Z"}
Main fields:
| Field | What it is |
|---|---|
adArchiveId, adLibraryUrl | Ad Library ID and a link to the ad |
status, isActive, startDate, endDate, lastSeenDate, daysRunning | When the ad ran. daysRunning counts both the first and the last day |
pageId, pageName, pageUrl, pageLikeCount, pageCategories | The advertiser |
bodyText, title, caption, linkDescription, ctaText, ctaType | The ad copy. For dynamic ads ({{product.name}} templates) the real text is taken from the cards |
textVariations | Other texts of the same ad (dynamic creative, carousel cards) |
linkUrl, linkDomain, utmParameters | Landing page, its domain and its UTM tags |
imageUrls, videos, videoUrls, videoDurationSeconds, cards, cardsCount | Creatives. cards holds each carousel card with its own text, link and media |
mediaUrlsExpireAt | Meta's media links stop working at this time (usually a few days). Download files before then |
platforms, displayFormat, mediaType, categories | Where it runs and what kind of ad it is |
spend, impressions, reachEstimate, currency, paidForBy | For political and issue ads: Meta's ranges as text plus lower and upper numbers |
isNew, firstSeenDate | With a watchlist: whether the ad is new since the last run |
details, euTotalReach, payer, beneficiary, advertiser* | With ad details on |
searchTerm, searchCountry, sourceType, sourceUrl, positionInSource, totalAdsInSource | Which input found the ad, its rank there, and the total Meta reports for that search |
markdown, raw | Optional: Markdown summary, and Meta's original ad object (contact e-mails and phone numbers removed) |
The Output tab has ready-made views: Overview, Creatives, Spend & reach, Advertisers, Monitoring and Counts.
Each run also saves two records in its key-value store:
- SUMMARY: per source, the total ads Meta reports, ads delivered, pages read, why it stopped, ads left out by each filter, and the error if it failed.
- ADVERTISERS: per advertiser, the number of ads and active ads, platforms, media types, first and last start date, longest-running ad and top landing domains.
Pricing
Pay per result: you pay for ads delivered to your dataset, nothing else.
| Apify plan | Per 1,000 ads | Ad details, per 1,000 ads |
|---|---|---|
| Free | $0.60 | $0.30 |
| Starter | $0.50 | $0.25 |
| Scale | $0.40 | $0.20 |
| Business and higher | $0.30 | $0.15 |
- Run start: $0.003 per run (covers start-up and empty scheduled checks).
- Count rows (
countOnly): $0.001 per source. - Never charged: failed sources, duplicates, ads removed by your filters, ads already delivered to your watchlist, and details that Meta did not return.
- Examples (Starter): 1,000 ads = $0.503. A daily monitor that finds 20 new ads = $0.013 per day. 1,000 ads with EU details = $0.753.
- Set a maximum cost per run in Run options; the run stops cleanly at that amount and keeps everything delivered so far.
Good to know
- What Meta shows: active ads in every country. Meta keeps inactive ads mainly when they are about politics or social issues (7 years) or ran in the EU (1 year), so older commercial ads elsewhere may be missing from the public Ad Library, for every scraper.
- Counts above 50,000 are reported by Meta as 50,000+ (
totalAdsInSource: 50001,totalIsLowerBound: true). - Dates: Meta's own date filter means "ran during these days".
startDateFromandstartDateTohere mean "started running between these days", and every ad is checked. - Media links expire after a few days (see
mediaUrlsExpireAt), as in the Ad Library itself. - Speed: about 30 ads every 3–5 seconds per source, and several sources run in parallel (
maxConcurrency). In our tests, 9 sources with 60 ads each finished in 28 seconds. - Ad details cost one extra request per ad, so runs take longer. EU reach exists only for ads delivered in the EU.
API and integrations
Python (pip install apify-client)
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("panix/facebook-ads-library-scraper").call(run_input={"searchTerms": ["running shoes"],"countries": ["US", "GB"],"maxAdsPerSource": 100,})for ad in client.dataset(run.default_dataset_id).iterate_items():print(ad["pageName"], ad["daysRunning"], ad["adLibraryUrl"])
JavaScript / Node.js (npm install apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('panix/facebook-ads-library-scraper').call({searchTerms: ['running shoes'],countries: ['US'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.length, items[0]?.pageName);
cURL (runs and returns the ads in one call, for runs up to 5 minutes)
curl -X POST "https://api.apify.com/v2/acts/panix~facebook-ads-library-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"searchTerms": ["running shoes"], "countries": ["US"], "maxAdsPerSource": 30}'
No-code tools
- n8n: in the Apify node, run the Actor
panix/facebook-ads-library-scraperwith the input JSON, then read the run's dataset items. - Make: Apify app → Run an Actor (wait until it finishes) → Get Dataset Items.
- Zapier: Apify app → Run Actor action, then fetch the dataset items of that run.
- Google Sheets, Slack, webhooks: under the Actor's Integrations tab.
AI agents (MCP): add https://mcp.apify.com/?actors=panix/facebook-ads-library-scraper to Claude, Cursor or any MCP client and ask, for example, "Which ads has Nike been running in Germany for more than 60 days?"
FAQ
Do I need a Facebook account, cookies or a Meta API token? No. The Actor reads the public Ad Library like a logged-out visitor.
Why did I get fewer ads than totalAdsInSource?
Your maxAdsPerSource limit, your filters (see adsLeftOut in SUMMARY), duplicates across inputs, or the end of Meta's results. Meta's total is an estimate.
What happens when Meta blocks a request?
It is retried on a new IP address from the same results page, up to maxRetries times. If a source still fails, the run continues with the other sources, the failure is listed in SUMMARY with an error code, and that source costs nothing.
How does "only new ads" work?
With a monitoringKey, the IDs of delivered ads are stored in your Apify account (key-value store facebook-ads-library-watchlists). With onlyNewAds on, later runs with the same key skip those ads and stop soon after they reach ads you already have. Delete the record to start over. Without a monitoringKey, onlyNewAds uses an automatic watchlist named after your inputs.
Why is the watchlist name a secret field? A watchlist name can show which brands you track, so Apify stores it encrypted in saved inputs, tasks and schedules, and the Actor keeps it out of the run log. Through the API you send it as plain text, as before.
Can I get ad spend for normal (non-political) ads?
Meta publishes spend and impressions only for political and issue ads. For other ads, daysRunning, the number of versions (collationCount) and EU reach (with ad details) are the best public signals of how much an ad is used.
Is it legal? The Meta Ad Library is a public transparency tool. This Actor collects only what it shows publicly and removes e-mail addresses and phone numbers from the raw data. Results can still include public names of people (for example, political advertisers), which can be personal data under the GDPR. Use the data for a legitimate purpose, and check Meta's terms and your local law. This Actor is not affiliated with or endorsed by Meta.
Support
Found a problem or need a field? Open an issue on the Issues tab. Include the run ID; the SUMMARY record usually shows what happened.