Facebook & Meta Ads Library Scraper + Tracker avatar

Facebook & Meta Ads Library Scraper + Tracker

Pricing

from $0.49 / 1,000 baseline ad results

Go to Apify Store
Facebook & Meta Ads Library Scraper + Tracker

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

Luka

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

3 days ago

Last modified

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.

Actual Meta Ads Library buyer results with creative and coverage fields

πŸš€ Start in 60 seconds

  1. Keep Baseline β€” current ads.
  2. Enter a keyword, a Facebook page URL, or an Ad Library search URL.
  3. Keep 15 ads per target for a small first test.
  4. 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

WorkflowUse it whenFirst runLater run with the same scopeResult billing
BaselineYou need the ads visible nowReturns current matching adsReturns a fresh current snapshotOne baseline_ad_result per delivered row
ChangesYou want repeat monitoringCreates state and returns current ads as NEWReturns the current snapshot labelled NEW, UPDATED, UNCHANGED, plus any safely proven ENDED adsOne 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;
  • maxAdsPerTarget value.

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 groupExamplesAvailability
Ad identityadId, pageId, pageName, adLibraryUrlCore identity fields
Dates and statestartDate, endDate, state, isActiveSource-dependent
Copy and CTAbodies, cardTitles, cardDescriptions, ctaTextsWhen present in the ad
Creative mediaimageUrls, videoUrls, snapshotUrls, displayFormatDepends on creative format
Delivery contextpublisherPlatforms, country, targetedOrReachedCountriesWhen Meta publishes it
Destination evidenceobservedLinkUrls, observedDestinationUrl, resolution fieldsWhen a destination is exposed and can be evaluated
Political-ad disclosuresreachEstimate, spend, currency, impression boundsPolitical and issue ads only, when published
MonitoringchangeStatus, changedFields, changeEventId, observedAtChanges workflow
CoveragecoverageStatus, sourceExhaustedExplains whether collection was complete or limited
Stable automation and provenancestableId, sourceClass, sourceName, sourceUrlDeduplication 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

InputWhat it controlsPractical advice
productLevelCurrent snapshot or repeat comparisonStart with Baseline; use Changes for scheduled monitoring
searchTermsKeyword and brand searchesOne term per line; nike is a safe test
pageUrlsSpecific Facebook advertisersNumeric-page-ID or Ad Library page URLs are the most reliable
startUrlsSearches prepared in Meta Ad LibraryFilters embedded in the URL take precedence for that URL
maxAdsPerTargetResult ceiling for each targetConsole prefill is 15; omitted API/Task input defaults to 100; reaching it produces CAPPED coverage
adTypeCommercial or political/issue adsPolitical ads can expose reach and spend fields
countryAd delivery countryALL is supported only for political/issue ads; commercial ALL runs use and report US
activeStatusActive, inactive, or all adsFilter before collection to avoid irrelevant delivered rows
mediaTypeAny, image, video, or meme creativesLeave ALL unless the format itself is your research question
dateFrom, dateToFirst-shown date rangeOptional; use YYYY-MM-DD
Advanced limitsPagination, network, and timeout ceilingsSafe 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 planBaseline per 1,000 rowsChanges per 1,000 rows1,000-row Baseline total1,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 runCalculationMaximum 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.

StatusMeaning
COMPLETEThe source was exhausted within the selected limits
CAPPEDmaxAdsPerTarget was reached before source exhaustion
PARTIALA timeout, budget, pagination ceiling, or recoverable source problem prevented complete collection
EMPTYNo matching ad was found; sourceExhausted shows whether that empty result was fully proven
CHALLENGEDThe 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.