Facebook Ad Library Scraper & Competitor Ad Change Monitor
Pricing
from $1.05 / 1,000 ad scanneds
Facebook Ad Library Scraper & Competitor Ad Change Monitor
Scrape the active Facebook and Instagram ads of exact Pages from the Meta Ad Library, no login or API key. Track every verified ad change across runs: new, stopped, resumed and asset updates in webhook-ready JSON with ad copy, links, media and platforms.
Pricing
from $1.05 / 1,000 ad scanneds
Rating
0.0
(0)
Developer
Kamer Ozkan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 hours ago
Last modified
Categories
Share
Track what changed in a competitor's Facebook and Instagram ads.
This Actor scrapes the active ads of exact Facebook Pages from the Meta Ad Library and tracks new, stopped, resumed, and changed ads across later runs. It is designed for competitor research, swipe-file exports, scheduled monitoring, agency reporting, and webhook automation.
You do not need a Facebook account, cookies, or a Meta Marketing API key. The Actor reads the same public Ad Library that anyone can open in a browser.
What problem does it solve?
A normal Facebook Ad Library scraper downloads the same ad rows every day. Your workflow still has to decide what is actually new, what disappeared, and whether a failed or partial scrape created a false alarm.
This Actor keeps monitor history and returns a clean change feed:
NEW: an ad appeared after the baseline and its own start date is on or after the previous accepted scanDISCOVERED: Meta returned a previously unseen ad whose start date predates the last accepted scanMISSING_ONCE: one tentative absence, available only when requestedSTOPPED_CONFIRMED: absent from two consecutive complete scansRESUMED: a previously stopped ad returnedASSET_CHANGED: the same Ad Library ID returned with different creative content
The first successful run creates the monitoring baseline. The default ALL_CHECKED output returns every current ad as a CURRENT row, while keeping existing ads out of the NEW event stream. Scheduled users can switch to CHANGES_ONLY.
Why use this Actor?
Exact Page isolation, plus keyword feeds
The input accepts native Facebook Page IDs such as 15087023444, Ad Library URLs that contain view_all_page_id, Page URLs such as https://www.facebook.com/nike, and Page usernames. Usernames are resolved to one exact Page ID before monitoring starts, so a Page monitor is never mixed with resellers, fan pages, or unrelated advertisers.
Keywords such as a product, brand, or competitor name are supported as separate targets. A keyword target returns the active ads Meta ranks for that term in the selected country, with the real Page ID and Page name on every row, and tracks which of those ads are new. Because keyword results mix many advertisers and change ranking over time, keyword targets always use the new-launch feed and never claim that an ad stopped.
Real ad copy, links, media, and platforms
Every row carries the ad's primary text, headline, destination URL, call-to-action, publisher platforms (Facebook, Instagram, Messenger, Audience Network, Threads), start date, format, and direct media URLs for images and videos, exactly as the Ad Library exposes them.
Safer stopped-ad detection
An ad is not marked stopped after one absence. STOPPED_CONFIRMED requires:
- Two consecutive successful source runs
- Complete pagination in both runs
- The ad missing from both complete snapshots
- At least six hours between the first absence and confirmation
Failed, blocked, timed-out, or capped scans do not advance the stopped-ad counter. Immediate retries cannot confirm a stopped ad.
Meta serves media from rotating CDN hosts with signed, expiring URL parameters. Those volatile parts are excluded from asset identity, so an unchanged creative never produces a false ASSET_CHANGED event. A different image, video, headline, or primary text still does.
Automatic large-advertiser protection
AUTO mode chooses the safest behavior for every Page:
- Complete scan: full lifecycle monitoring
- Result or page cap reached: new-launch feed only
The Actor never claims that an ad stopped when the Page was only partially scanned.
Changes-only output
Use CHANGES_ONLY for scheduled runs. The dataset stays empty when nothing changed, making it easy to connect the Actor to Slack, Discord, Make, Zapier, n8n, or your own webhook.
Quick start
Use one exact Page ID for the first test:
{"pageIds": ["15087023444"],"country": "ALL","monitorName": "competitor-watch","mode": "AUTO","maxAdsPerPage": 300,"outputMode": "ALL_CHECKED"}
The first run returns the current active ads and creates the baseline. Run it again with the same monitorName, Page IDs, and country to receive verified changes.
Example output
The CURRENT record is unedited output from production run Pb1C64QubSd3Wkfjz (Nike, Germany) on 2026-09-02. That run finished HEALTHY, exhausted all six Ad Library result pages, accepted the lifecycle comparison, and charged 60 ad scans and zero change events. The stopped-ad sequence is an explicitly labeled deterministic replay of the same live snapshot that demonstrates both confirmation stages. Signed media URL parameters are shortened to ?... for readability only.
1. A checked ad (CURRENT)
One ad, one Page, one record. Fields the Ad Library does not publish for this ad stay null inside current; nothing is guessed.
2. How a stop is confirmed, never guessed
An ad disappearing from one scan is not a stopped ad. The engine reports it in two deliberate steps:
- First absence is tentative.
MISSING_ONCEsays the ad was absent from one complete, successful scan.evidence.tentativeistrueand nothing is confirmed. - Confirmation needs a second complete absence. Only then does
STOPPED_CONFIRMEDfire, with the absence count, the first missing timestamp, and the confirmation interval inevidence. - Incomplete scans confirm nothing. A partial or failed source run is rejected as
INCOMPLETE_SOURCE_RUN: zero events, state untouched, no phantom stops. - The first observation of a monitor bills zero verified changes, by a hard rule in the billing code, so starting a new monitor never charges for a wall of baseline events.
Input fields
| Field | Description | Default |
|---|---|---|
pageIds | Up to 20 Facebook Page IDs, Page URLs, Page usernames, or Ad Library URLs | Empty |
keywords | Up to 10 search terms, each monitored as a new-launch feed | Empty |
keywordSearchType | keyword_unordered (broad match) or keyword_exact_phrase | keyword_unordered |
country | Delivery country, or ALL for the complete active library | ALL |
monitorName | Stable history name for one watchlist | competitor-watch |
mode | AUTO, FULL_LIFECYCLE, or NEW_LAUNCH_FEED | AUTO |
maxAdsPerPage | Per-Page and per-keyword result and billing safety cap, up to 5,000 | 300 |
outputMode | Current ads plus changes, or changes only | ALL_CHECKED |
includeBaseline | In changes-only mode, label first-run ads as NEW | false |
includeTentative | Include internal MISSING_ONCE events | false |
proxyConfiguration | Apify Proxy settings; residential proxies are the default and included in the price | Apify residential |
Monitoring modes
Auto
Recommended for most users. Full lifecycle is used only when all result pages finish. Large advertisers automatically fall back to a safe new-launch feed.
Full lifecycle
Requires a complete scan of the Page's active ads. If the configured cap is reached, the target is reported as INCOMPLETE, history is not advanced, and no ad scans are billed for that target.
New launch feed
Tracks previously seen Ad Library IDs and emits only new ones. This mode can operate on a capped snapshot because it never produces stopped-ad claims. Keyword targets always use this mode.
Keyword targets
Add search terms to keywords when you do not know the Page yet or want to watch a whole product category:
{"keywords": ["running shoes", "protein powder"],"keywordSearchType": "keyword_unordered","country": "US","maxAdsPerPage": 300,"outputMode": "CHANGES_ONLY"}
Each keyword receives its own history scope (monitorName, keyword, match type, country). Every row carries the advertiser's real Page ID and name in advertiserId and advertiserName and the search term in keyword. The first run returns the current ranked ads; later runs emit NEW or DISCOVERED rows for ads that were not seen before. A missing ad is never reported as stopped, because it may simply have dropped out of Meta's ranking. When you find a Page worth monitoring closely, add its Page ID to pageIds to get full stopped-ad detection.
Output modes
Changes only
Returns only lifecycle events. Use this for schedules, webhooks, Slack, Discord, Make, Zapier, and n8n. The first baseline produces zero rows because existing ads are not new launches.
Changes and all checked ads
The default mode. Adds one CURRENT row per checked ad and includes any verified change events. Use it for the first run, one-time exports, audits, and swipe-file workflows.
Ad fields by format
The Ad Library exposes different structured fields for each ad format. A null value means the source did not provide that field. The Actor does not guess missing copy, OCR text embedded in artwork, or transcribe videos.
| Format | Consistently available | Notes |
|---|---|---|
IMAGE | Primary text, headline, destination URL, call-to-action, original and resized image URLs | Text embedded in an image is not OCR output. |
VIDEO | Primary text, headline, destination URL, call-to-action, HD and SD video URLs, preview image | Spoken and on-screen text are not transcribed. |
CAROUSEL | Card titles, card bodies, card links, and card media | The first card supplies headline, body, and destinationUrl when the top-level snapshot is empty. cardCount is inside current. |
DCO, DPA, and MULTI_IMAGES | Every image, video, and text variant Meta returns | Dynamic and catalog ads can rotate variants; asset identity uses the full media set. |
Media URLs are signed by Meta and expire after a few weeks. Download assets you want to keep soon after the run. Asset identity never depends on the signed parts, so expiry does not create change events.
Supported countries
ALL returns every active ad of the Page regardless of delivery country. The single-country filter supports 63 markets across Europe, the Americas, Asia-Pacific, the Middle East, and Africa, including US, GB, CA, AU, DE, FR, ES, IT, NL, BR, MX, IN, JP, AE, ZA, and TR.
How to find the Page ID
- Open the Meta Ad Library.
- Search for the advertiser and open its ads.
- Copy the URL. It contains
view_all_page_id=<number>.
Example:
https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&view_all_page_id=15087023444&search_type=page
You can paste the full Ad Library URL, the numeric Page ID, the Page URL (https://www.facebook.com/nike), or the username (nike). Usernames must match the Page's exact username; when no exact match exists the Actor reports PAGE_ALIAS_NOT_FOUND instead of guessing a similar Page.
Scheduling and webhooks
For daily monitoring:
- Save the Actor input as an Apify Task.
- Keep the same
monitorNameand scope settings. - Add an Apify Schedule.
- Add a webhook for
ACTOR.RUN.SUCCEEDED. - Read the default dataset. Zero rows means no confirmed change was emitted.
Every change includes a deterministic eventId. Use it as the idempotency key when a webhook or downstream workflow retries delivery.
Changing monitorName, the Page ID, the keyword, the keyword match type, or country creates a different history scope.
This Actor is also exposed to AI agents through Apify's MCP server (mcp.apify.com): an agent can discover it by search and run it with the same pay-per-event billing, with no separate integration.
Billing
The Actor separates the cost of scanning from the cost of confirmed changes. An unchanged ad can still incur the scan charge when it is hidden by CHANGES_ONLY, because the source request, Page isolation, and history comparison were completed.
- Ads scanned: $1.50 per 1,000
- Verified changes: $20.00 per 1,000
- Actor start: $0.005 per GB of run memory
- Platform usage and residential proxies: included
The first accepted observation creates a baseline and never incurs verified change charges. Later runs charge that event only for confirmed new, stopped, resumed, or modified ads.
Example scan costs before any later verified changes:
| Ads scanned | Scan cost |
|---|---|
| 10 | $0.015 |
| 100 | $0.15 |
| 1,000 | $1.50 |
One Page with 100 active ads checked daily for 30 days costs $4.50 in scan charges, plus the Actor start for each run and any verified change events.
The default 300-ad cap limits scan charges to $0.45 per Page. With 20 Pages at the full default cap, the maximum scan charge is $9.00 plus verified changes and the Actor start. Raise the cap up to 5,000 for very large advertisers; most advertisers run far fewer active ads.
Dataset rows are not a separate billable event, so ALL_CHECKED does not create a second scan charge.
These cases are not billed as ad scans:
- Page lookup failure, unknown Page ID, or invalid keyword
- Source request failure or block
- Page contamination (an ad from a different Page)
- Explicit
FULL_LIFECYCLErun that cannot finish pagination - Suspicious empty snapshot after a previously active library
- Records beyond the run's maximum charge limit
The OUTPUT record contains exact scan and change billing counters plus a per-Page accounting summary.
Important limitations
- The Meta Ad Library is a public transparency source, not the Marketing API. The Actor does not provide spend, reach, impressions, conversions, or campaign performance for regular commercial ads.
- The Actor monitors the ads Meta reports as active. Inactive ads are not part of the snapshot, so an ad that stops is detected through its absence, not through an end date.
- A missing Ad Library record does not prove that a campaign was deleted inside Ads Manager.
- A complete but empty snapshot cannot erase a previously active library. The target is flagged as
SUSPICIOUS_EMPTY, history is preserved, and no stopped events are emitted. - Media links depend on what Meta exposes publicly and expire after a few weeks.
- Very large advertisers may use
NEW_LAUNCH_FEEDin Auto mode rather than full stopped-ad detection. - The Actor monitors one delivery country (or
ALL) per run. Create separate tasks for separate countries. - Keyword targets follow Meta's ranking. They are a discovery and new-launch feed, not a complete advertiser library, so they never confirm stopped ads and their
DISCOVEREDrows can include older ads that entered the ranking. - Avoid overlapping runs that use the same monitor name and scope. Schedule the next run after the previous run finishes.
- Meta reports dates at day-level granularity. A
NEWevent means the ad's start date is on or after the previous accepted scan date, not that the exact launch minute is known. - Meta rate-limits datacenter IP addresses, so the Actor routes its single browser session through Apify residential proxies by default. Proxy usage is included in the event price. A blocked or rate-limited session is retried once and then reported as a failed target without any ad scan charge.
FAQ
Can I search by keyword such as "running shoes"?
Yes. Add the term to keywords. Keyword targets return the ranked active ads for that term with the real Page behind every ad and track new launches across runs. Stopped-ad detection stays reserved for exact Page targets, because keyword rankings change between runs.
Why was my first dataset empty?
You selected CHANGES_ONLY, so the first successful run created a silent baseline. Use the default ALL_CHECKED mode when you want the current ad snapshot on the first run.
Why did Auto mode use New Launch Feed?
The Page had more active ads than the configured cap. Auto mode refused to make stopped-ad claims from a partial snapshot.
Does a stopped event require two days?
It requires two consecutive complete scheduled runs, not a fixed number of days. With a daily schedule, confirmation normally takes two daily absences.
Can I monitor several competitors?
Yes. Add up to 20 Pages. Every Page receives an independent state and completeness decision.
Is this affiliated with Meta?
No. This Actor is not affiliated with or endorsed by Meta Platforms. Users are responsible for using public data lawfully and in accordance with applicable rules.