Facebook Ads Library Scraper — Meta & Instagram Ads
Pricing
from $15.00 / 1,000 results
Facebook Ads Library Scraper — Meta & Instagram Ads
Extract ads from the Meta Ads Library (Facebook & Instagram). Get ad copy, running days, EU spend data, carousel cards, and landing page URLs. The only scraper that tracks how long each ad has been running — your key signal for finding competitor winning ads.
Pricing
from $15.00 / 1,000 results
Rating
5.0
(1)
Developer
Yuliia Kulakova
Maintained by CommunityActor stats
2
Bookmarked
1.3K
Total users
261
Monthly active users
13 days ago
Last modified
Categories
Share
Collect · Analyze · Outperform
The most data-rich Facebook Ads Library scraper on Apify —
daysRunning, structured spend ranges, full carousel cards, video URLs, and landing pages.
Why this one? · Input · Output · Use cases · Pricing · What's new
Facebook Ads Library Scraper extracts ads from the Meta Ads Library — Meta's public database of every ad running on Facebook, Instagram, Messenger, Threads, and Audience Network.
Built for marketers, agencies, and researchers who need clean, structured data — not raw HTML or incomplete JSON. Every field is normalized, deduped, and ready to pipe into your analysis tool or CRM.
🙏 Does this Actor save you time?
It is built and maintained by one developer. A rating on the Store page takes ten seconds and is the only signal new users have — it genuinely decides whether this Actor gets found at all.
Ran into something broken, missing, or confusing? Please open an Issue instead of leaving it unsaid. I read every one, reply within a day, and fix fast. Recent fixes, all shipped the same week: carousel and catalog ads now return every card's image, impressions and audience-size data now come through, and runs no longer fail on searches that simply have no matches.
Missing a field or a country? Ask — most requests are a small change.
✨ What makes this different
| Feature | This actor | Most others |
|---|---|---|
daysRunning — how long the ad has been live | ✅ computed automatically | ❌ |
Spend as structured {min, max} — not a raw string | ✅ | ❌ |
| All carousel cards extracted as individual objects | ✅ | First card only |
| Video URLs (fbcdn.net CDN) | ✅ | ❌ |
| Image URLs for all image ads | ✅ | ❌ |
Landing page URL via resolveSnapshotUrls | ✅ opt-in | ❌ |
| Cross-search deduplication | ✅ | ❌ |
| Login wall detection with clear error message | ✅ | ❌ |
| Filters: status, ad category, date range, country | ✅ | Partial |
💡 Why daysRunning is the most valuable field
An ad running for 60+ days is profitable. The advertiser keeps paying because it converts.
daysRunning lets you instantly separate proven winners from tests without any manual calculation. Sort by it descending and you have a ranked list of your competitor's best-performing creatives — right now.
No other Facebook ads scraper on Apify computes this field automatically.
⚙️ Input
| Field | Type | Default | Description |
|---|---|---|---|
searchTerms | string[] | ["Nike"] | Brand names or keywords to search |
countries | string[] | ["US"] | ISO 2-letter country codes (e.g. "US", "GB", "DE") |
adType | string | "ALL" | ALL · POLITICAL_AND_ISSUE_ADS · HOUSING · EMPLOYMENT · FINANCIAL_PRODUCTS_AND_SERVICES |
adActiveStatus | string | "ACTIVE" | ALL · ACTIVE · INACTIVE |
maxAds | integer | 25 | Max ads per search term + country pair |
resolveSnapshotUrls | boolean | false | Visit each ad snapshot page to extract the real landing page URL and CDN media files |
startDate | string | — | Show ads that were active on/after this date (YYYY-MM-DD) |
endDate | string | — | Show ads that were active on/before this date (YYYY-MM-DD) |
Note on date filters: Meta shows ads that were running during the specified period, which may include ads that started before
startDateif they were still active within your range. This is Meta's behavior, not a scraper limitation.
Example inputs
Quick test — Nike US active ads
{"searchTerms": ["Nike"],"countries": ["US"],"adActiveStatus": "ACTIVE","maxAds": 25}
Agency competitor research — 3 brands × 3 countries
{"searchTerms": ["Adidas", "Nike", "Puma"],"countries": ["US", "GB", "DE"],"adActiveStatus": "ACTIVE","maxAds": 200}
Political ads with spend data (EU/DSA)
{"searchTerms": ["election"],"countries": ["DE"],"adType": "POLITICAL_AND_ISSUE_ADS","adActiveStatus": "ALL","maxAds": 100}
Date range — ads from a specific campaign window
{"searchTerms": ["Nike"],"countries": ["US"],"adActiveStatus": "ALL","maxAds": 50,"startDate": "2025-01-01","endDate": "2025-06-30"}
resolveSnapshotUrls — get real landing page URLs
{"searchTerms": ["Nike"],"countries": ["US"],"adActiveStatus": "ACTIVE","maxAds": 20,"resolveSnapshotUrls": true}
📦 Output schema
Each item in the dataset represents one ad. Carousel ads include all cards as separate objects inside creatives.
{"adArchiveId": "1234567890","pageId": "987654321","pageName": "Nike","adActiveStatus": "ACTIVE","adDeliveryStartTime": "2025-11-01T00:00:00.000Z","adDeliveryStopTime": null,"daysRunning": 154,"publisherPlatforms": ["facebook", "instagram"],"mediaType": "VIDEO","cardCount": 3,"displayFormat": "CAROUSEL","categories": ["UNKNOWN"],"creativeVariantCount": 3,"snapshotImageUrls": null,"snapshotVideoUrls": null,"creatives": [{"body": "Just Do It. Shop the new Air Max collection.","title": "Air Max 2026","caption": "nike.com","description": null,"ctaText": "Shop Now","ctaType": "SHOP_NOW","destinationUrl": "https://www.nike.com/air-max","imageUrls": [],"videoUrl": "https://video.ftbs6-2.fna.fbcdn.net/...","cardIndex": 0}],"spend": { "min": 1000, "max": 5000 },"impressions": { "min": 100000, "max": 500000 },"estimatedAudienceSize": { "min": 1000000, "max": 2000000 },"demographicDistribution": null,"euTotalReach": null,"targetAges": null,"targetGender": null,"targetLocations": null,"bylines": null,"fundingEntity": null,"snapshotUrl": "https://www.facebook.com/ads/library/?id=1234567890","scrapedAt": "2026-04-04T12:00:00.000Z"}
Field reference
| Field | Type | Notes |
|---|---|---|
adArchiveId | string | Unique Meta ad ID |
pageName | string | Advertiser page name |
adActiveStatus | string | ACTIVE or INACTIVE |
daysRunning | integer | Days since ad delivery start — key profitability signal. For an ad still active this counts to today, because Meta's end date can sit in the past on an ad it also reports as active |
publisherPlatforms | string[] | e.g. ["facebook", "instagram", "messenger", "threads"] |
mediaType | string | VIDEO, IMAGE, or NONE — what media the ad carries. Carousel and catalog cards carry their own images, so those ads report IMAGE. For layout, use displayFormat |
cardCount | integer | How many cards this ad has — the length of creatives. Note a DCO ad uses cards for copy variants, so displayFormat is the reliable carousel test |
displayFormat | string | How Meta classifies the layout: DPA (catalog), CAROUSEL, DCO, IMAGE, VIDEO |
categories | string[] | Categories Meta files the ad under, e.g. ["EMPLOYMENT"]. Tells you whether the Ad Category filter was actually applied |
containsDigitalCreatedMedia | boolean | Meta's disclosure flag for AI-generated creative. false means no flag was recorded, not proof the creative is human-made |
totalActiveTime | integer | Seconds Meta reports the ad as active. Excludes paused periods, so it can be lower than daysRunning, which is calendar time |
currency | string | Currency of the spend range, when Meta reports one |
creativeVariantCount | integer | Meta's size of the group this ad was collated into. Every member of that group is already its own row — not a card count |
creatives | object[] | All creative variants; carousel = multiple objects |
creatives[].body | string | Ad copy text |
creatives[].videoUrl | string | Direct CDN video URL (fbcdn.net). Player-internal blob: handles are not reported — they are not downloadable files |
creatives[].imageUrls | string[] | Direct CDN image URLs (fbcdn.net). Carousel and catalog cards each carry their own image. Duplicates are removed |
creatives[].destinationUrl | string | Landing page URL — from GraphQL when available, or via resolveSnapshotUrls |
snapshotImageUrls | string[] | For multi-card ads with resolveSnapshotUrls: images found on the ad's page, in page order. A carousel lazy-loads, so this is what was rendered, not necessarily every card |
snapshotVideoUrls | string[] | Same, for video files |
spend | object | {min, max} in USD — see availability note below |
impressions | object | {min, max} — see availability note below |
estimatedAudienceSize | object | {min, max} potential reach |
demographicDistribution | object | Age/gender breakdown. Not available: Meta does not include it in search results, only on the ad's own page — see the note below |
fundingEntity | string | Who paid for the ad — the "Paid for by" byline (political ads only) |
disclaimerLabel | string | Which disclaimer Meta attached, e.g. PAID_FOR_BY |
pageLikeCount | integer | How many people follow the advertiser page |
pageCategories | string[] | Categories the advertiser page lists itself under |
bylines | string | The "Paid for by" disclaimer (political ads only) |
targetLocations | string[] | ISO country codes Meta reports the ad was targeted at or reached (political ads only) |
What Meta does not publish in search results. demographicDistribution, euTotalReach, targetAges, targetGender and targetLocations are absent from the Ads Library search response — checked on both commercial and political ads. They stay null here. Spend, impressions, estimated audience size, the funding byline and the disclaimer label all come through and are filled for political and issue ads.
On the Ad Category filter: Meta does not always apply it. Asking for political ads in Germany returned ordinary commercial ads. The run log lists the categories Meta actually labelled each batch with, and every record carries its own categories field — check it before relying on the filter.
Spend & impressions availability
| Ad type | spend & impressions |
|---|---|
| US / global commercial ads (Nike, Adidas, etc.) | null — Meta policy, not a scraper bug |
| EU/UK commercial ads | Available for some ad categories under DSA |
| Political, issue, housing, employment, financial ads | ✅ Returned as {min, max} objects |
🎯 Use cases
Competitor ad intelligence Find which creatives your competitors have kept running for 60, 90, 120+ days. Long-running = profitable. Build a swipe file of proven winners, not guesses.
Agency client reporting Bulk-export all active ads for a brand across every country and platform. Export to CSV, Google Sheets, or push straight into your reporting dashboard via Apify API.
Creative benchmarking What CTAs dominate your category? Which formats (video vs. image vs. carousel) are brands investing in? What copy angles are getting budget behind them?
Political ad monitoring EU/UK DSA transparency data: spend ranges, estimated reach, demographic targeting, and funding entity — all structured and ready for analysis.
Market research & trend tracking Run the same search weekly to track how competitors shift their messaging, seasonal spend, and creative strategy over time.
💰 Pricing
From $15.00 / 1,000 ads — no monthly fees, pay only for what you scrape.
| Mode | What you get | ~Total cost per 1,000 ads |
|---|---|---|
| Standard | All fields — copy, video URLs, image URLs, spend, all carousel cards | ~$15 |
resolveSnapshotUrls: true | Everything above + confirmed landing page URL for each ad | ~$16–17 |
resolveSnapshotUrlsmode visits an extra page per ad (~5 sec each), which adds some Apify platform compute time on top of the base price. No monthly fees — pay only for what you scrape.
🆕 What's new
2026-08-22
- Carousel and catalog ads now return every card's image. They previously came back with none — the images were in Meta's response all along, under a key the parser was not reading.
impressions,estimatedAudienceSize,fundingEntity,bylinesandcurrencyare now filled for political and issue ads. They were always empty because Meta sends them under different key names than the ones being read.creativeVariantCountreports the real number. It used to say1on every ad.daysRunningno longer understates ads that are still running. Meta sometimes reports an end date in the past on an ad it also reports as active; the count now runs to today.- A search with no matching ads finishes successfully with a
NO_RESULTSmarker. It used to fail the whole run — Meta serves an identical page whether a search is empty or the connection is being throttled, so the Actor now settles the question with a control query. - If Meta refuses one connection, the run switches to a backup automatically and only fails when every connection is refused — loudly, and without writing billable rows for data it never got.
- New fields:
cardCount,displayFormat(DPA/CAROUSEL/DCO/IMAGE/VIDEO),categories,disclaimerLabel,pageLikeCount,pageCategories,totalActiveTime,containsDigitalCreatedMedia.
⚠️ Limitations
- Spend/impressions are
nullfor US commercial ads. This is Meta's transparency policy — data is only disclosed for political/issue/housing/employment/financial ads and some EU ads under DSA rules. - Meta does not expose exact spend — only ranges (e.g. $1,000–$5,000).
resolveSnapshotUrlsadds ~5 seconds per ad (one extra page load). For 1,000 ads, budget ~90 minutes of run time.- Date range filters rely on Meta's own filtering, which may include ads that started before your
startDateif they were still active during your range. - Meta periodically updates their internal page structure. If you notice empty results, open an issue and we'll push an update within 24–48 hours.