Facebook & Meta Ads Library Scraper + Tracker
Pricing
from $0.49 / 1,000 baseline ad results
Facebook & Meta Ads Library Scraper + Tracker
Scrape Facebook and Meta Ads Library creatives, copy, CTAs and landing links. Track competitor ads and detect new, updated and safely ended ads.
Pricing
from $0.49 / 1,000 baseline ad results
Rating
0.0
(0)
Developer
Luka
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Use this Facebook Ads Library scraper to collect current Facebook and Instagram ads from the Meta Ad Library, or reuse the same search as a change feed for competitor monitoring. It also works as a Meta ads scraper for one-time exports: add a keyword, Facebook page, or prepared Ad Library URL and receive normalized ad copy, creative URLs, calls to action, dates, advertiser context, destinations, and explicit coverage status.
For the easiest first run, choose Baseline, keep the prefilled nike search and 15-ad limit, then click Start.

π Start in 60 seconds
- Keep Baseline β current ads.
- Enter a keyword, a Facebook page URL, or an Ad Library search URL.
- Keep 15 ads per target for a small first test.
- Click Start and open the Dataset when the run finishes.
{"productLevel": "BASELINE","searchTerms": ["nike"],"country": "US","activeStatus": "ACTIVE","maxAdsPerTarget": 15}
You can combine input lists, but one run accepts at most 25 total targets across searchTerms, pageUrls, and startUrls. The Console starts with a buyer-friendly 15-result prefill; API and Task inputs that omit maxAdsPerTarget keep the compatible default of 100.
π― Choose the right workflow
| Workflow | Use it when | First run | Later run with the same scope | Result billing |
|---|---|---|---|---|
| Baseline | You need the ads visible now | Returns current matching ads | Returns a fresh current snapshot | One baseline_ad_result per delivered row |
| Changes | You want repeat monitoring | Creates state and returns current ads as NEW | Returns the current snapshot labelled NEW, UPDATED, UNCHANGED, plus any safely proven ENDED ads | One changes_ad_result per delivered row |
You do not need to run Baseline before Changes. The first successful Changes run creates its own comparison state.
For meaningful comparisons, repeat the same:
- target or prepared Ad Library URL;
- country, ad category, status, format, and date filters;
maxAdsPerTargetvalue.
Run the same monitoring scope sequentially. Changing the scope creates a different comparison, and overlapping runs of the same scope should be avoided.
π¦ What you get
Each row is a normalized ad record. Fields are returned when Meta exposes them for that ad and category.
| Field group | Examples | Availability |
|---|---|---|
| Ad identity | adId, pageId, pageName, adLibraryUrl | Core identity fields |
| Dates and state | startDate, endDate, state, isActive | Source-dependent |
| Copy and CTA | bodies, cardTitles, cardDescriptions, ctaTexts | When present in the ad |
| Creative media | imageUrls, videoUrls, snapshotUrls, displayFormat | Depends on creative format |
| Delivery context | publisherPlatforms, country, targetedOrReachedCountries | When Meta publishes it |
| Destination evidence | observedLinkUrls, observedDestinationUrl, resolution fields | When a destination is exposed and can be evaluated |
| Political-ad disclosures | reachEstimate, spend, currency, impression bounds | Political and issue ads only, when published |
| Monitoring | changeStatus, changedFields, changeEventId, observedAt | Changes workflow |
| Coverage | coverageStatus, sourceExhausted | Explains whether collection was complete or limited |
| Stable automation and provenance | stableId, sourceClass, sourceName, sourceUrl | Deduplication key, official-source identity, and canonical public source URL |
Representative Changes row:
{"adId": "388120997678322","pageId": "1497383683837785","pageName": "adidas","state": "INACTIVE","bodies": ["Discover the latest collection."],"ctaTexts": ["Shop now"],"imageUrls": ["https://scontent.example.fbcdn.net/ad-creative.jpg"],"publisherPlatforms": ["FACEBOOK", "INSTAGRAM"],"country": "US","changeStatus": "NEW","coverageStatus": "COMPLETE","observedAt": "2026-08-20T11:45:21.357Z"}
The Dataset includes focused views for quick review:
- Buyer overview β the most useful advertiser, creative, destination, change, and coverage fields;
- New, updated and ended ads β change-first monitoring view;
- Creative research swipe file β copy, CTA, media, and destination research;
- All fields β complete normalized export for API, CSV, or downstream analysis.
Blank or absent optional fields mean the source did not expose that value for that ad. They are not filled with guesses.
ποΈ Input guide
| Input | What it controls | Practical advice |
|---|---|---|
productLevel | Current snapshot or repeat comparison | Start with Baseline; use Changes for scheduled monitoring |
searchTerms | Keyword and brand searches | One term per line; nike is a safe test |
pageUrls | Specific Facebook advertisers | Numeric-page-ID or Ad Library page URLs are the most reliable |
startUrls | Searches prepared in Meta Ad Library | Filters embedded in the URL take precedence for that URL |
maxAdsPerTarget | Result ceiling for each target | Console prefill is 15; omitted API/Task input defaults to 100; reaching it produces CAPPED coverage |
adType | Commercial or political/issue ads | Political ads can expose reach and spend fields |
country | Ad delivery country | ALL is supported only for political/issue ads; commercial ALL runs use and report US |
activeStatus | Active, inactive, or all ads | Filter before collection to avoid irrelevant delivered rows |
mediaType | Any, image, video, or meme creatives | Leave ALL unless the format itself is your research question |
dateFrom, dateTo | First-shown date range | Optional; use YYYY-MM-DD |
| Advanced limits | Pagination, network, and timeout ceilings | Safe defaults protect cost; lower limits can make coverage partial |
For a low-cost first run, set maxAdsPerTarget explicitly to 15 in API calls. Otherwise the compatible default is 100.
blockMediaDownloads should normally stay on. It reduces bandwidth by skipping media-file downloads during collection while still returning the published image and video URLs.
π° Pricing
This Actor uses Pay per event. The current active price is:
Total = $0.02 run start + delivered rows Γ the result price for the selected workflow
The actor_start event is configured with isOneTimeEvent: true: it is a flat $0.02 once per successful run, not $20 per run. It is preflighted before collection and charged only after the Actor has a usable source collection or a positively verified empty result. A blocked, failed, or no-collection attempt charges zero start events.
| Apify plan | Baseline per 1,000 rows | Changes per 1,000 rows | 1,000-row Baseline total | 1,000-row Changes total |
|---|---|---|---|---|
| Free | $0.700 | $1.100 | $0.720 | $1.120 |
| Bronze | $0.630 | $1.045 | $0.650 | $1.065 |
| Silver | $0.560 | $0.990 | $0.580 | $1.010 |
| Gold | $0.490 | $0.935 | $0.510 | $0.955 |
| Platinum | $0.455 | $0.935 | $0.475 | $0.955 |
| Diamond | $0.420 | $0.935 | $0.440 | $0.955 |
Examples on the Free plan:
| Example run | Calculation | Maximum event charge |
|---|---|---|
| 15 Baseline rows | $0.02 + 15 Γ $0.0007 | $0.0305 |
| 100 Baseline rows | $0.02 + 100 Γ $0.0007 | $0.0900 |
| 100 Changes rows | $0.02 + 100 Γ $0.0011 | $0.1300 |
| 1,000 Changes rows across multiple targets | $0.02 + 1,000 Γ $0.0011 | $1.1200 |
At 1,000 delivered Baseline rows, Gold reduces the row price by 30% and the complete event charge by 29.2% after the flat start. For 1,000 Changes rows, Gold reduces the row price by 15% and the complete event charge by 14.7%. Platinum and Diamond keep the same Changes price as Gold; their additional discount applies to Baseline rows.
In Changes mode, every delivered NEW, UPDATED, UNCHANGED, and safely proven ENDED row uses the Changes price because each repeat run performs a fresh live scan. State operations, summaries, suppressed rows, and failed delivery attempts are not separate result events.
The examples show event charges at the listed rates. Your Apify account still applies its own platform billing rules shown at run time.
β Coverage you can trust
The Actor reports why a target stopped instead of presenting every short result as complete.
| Status | Meaning |
|---|---|
COMPLETE | The source was exhausted within the selected limits |
CAPPED | maxAdsPerTarget was reached before source exhaustion |
PARTIAL | A timeout, budget, pagination ceiling, or recoverable source problem prevented complete collection |
EMPTY | No matching ad was found; sourceExhausted shows whether that empty result was fully proven |
CHALLENGED | The source blocked or challenged collection |
ENDED is conservative. It is emitted only when the previous comparison state and the current scan provide complete-enough evidence. A CAPPED, PARTIAL, or challenged run cannot convert a missing ad into ENDED.
If collection cannot meet that contract, the run reports the limitation or fails closed instead of silently claiming complete coverage.
π API and automation
Use the same stable input keys from the Console through the Apify API:
const run = await client.actor('luminar/meta-ads-library-creative-changefeed').call({productLevel: 'CHANGES',searchTerms: ['nike'],country: 'US',activeStatus: 'ACTIVE',maxAdsPerTarget: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
After one successful manual run, save the input as your own private Apify Task and add a Schedule. Webhooks, Make, Zapier, n8n, or your own code can then filter NEW, UPDATED, and ENDED rows for alerts while retaining UNCHANGED rows as context.
For Google campaign research, use the companion Google Ads Transparency Center Scraper & Tracker.
β FAQ and support
Do I need to run Baseline before Changes?
No. The first Changes run establishes state and returns current ads as NEW. Repeat the same scope to compare later runs.
Why did a repeat Changes run return UNCHANGED rows?
Meta Changes is a labelled live snapshot. It returns the current monitored rows on every run so an automation has complete current context; those delivered rows use the Changes result price.
Why are copy, spend, reach, or media fields missing on some ads?
Meta exposes different fields by ad type and creative format. Spend and reach disclosures are primarily available for political and issue ads. Missing values remain absent instead of being inferred.
Can I schedule competitor monitoring?
Yes. First confirm the input manually, then save it as a private Task and attach an Apify Schedule. Keep the monitoring scope unchanged between runs.
How do I report a problem?
Open the Actor's Issues or Support tab and include the run ID, sanitized input, expected result, and the target coverage status. Do not post API tokens or private credentials.