Meta Ad Library Monitor avatar

Meta Ad Library Monitor

Pricing

from $2.80 / 1,000 advertiser checkeds

Go to Apify Store
Meta Ad Library Monitor

Meta Ad Library Monitor

Finds a company active ads in the Meta Ad Library through Meta own Graph API and returns one flat row per ad with creative text, platforms, start date and a snapshot link. Covers every ad delivered to the EU, plus issue and election ads worldwide. Bring your own Meta token.

Pricing

from $2.80 / 1,000 advertiser checkeds

Rating

0.0

(0)

Developer

Mamba Labs

Mamba Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Share

๐Ÿ”Ž What can Meta Ad Library Monitor do?

Give it a company name or domain and your own Meta access token. It searches the Meta Ad Library and returns one flat row per ad: creative text, headline, start date, the platforms it ran on, and a link to Meta's own snapshot of the ad.

The coverage, first, because it decides whether this actor is any use to you. It reads Meta's Ad Library Graph API, which is the only route Meta sanctions. That API publishes two things:

  • every ad delivered to an audience in the EU, whatever the ad is about
  • social issue, election and politics ads worldwide

So an EU heavy list gets excellent coverage of ordinary commercial advertising. A US or UK list of ordinary product ads mostly comes back not_found, and that is Meta's dataset rather than a fault in the lookup. The row says not_found instead of pretending.

There is no second route, and that is deliberate. The public Ad Library website carries all public ads with no token, and reading it is what several Store competitors do. Meta's robots.txt says Disallow: / for every agent it has not named, and the file opens by stating that automated collection is prohibited without express written permission. That is a written prohibition rather than a convention, so this actor does not do it.

๐Ÿ“ฆ What you getโš™๏ธ Features and integrations
๐Ÿ“ข Active ads for a company from the Meta Ad Library
๐Ÿ–ผ๏ธ Creative text, platforms, start date and snapshot URL
๐ŸŒ All ads in the EU, political ads elsewhere
๐Ÿงพ 27 flat fields, snake_case, one row per ad
๐Ÿ”‘ BYOK, Facebook's own Graph API
๐ŸŽš๏ธ Country, status, type and media filters
๐Ÿšฆ Honest coverage statement, this is the dataset Meta publishes
โฌ‡๏ธ Export to JSON, CSV, Excel, HTML or XML

Bought by competitive intelligence and paid media teams, agencies auditing a prospect's ad spend before a pitch, and researchers working with political ad transparency data.

๐Ÿšซ Coverage is not all ads everywhere, and the happy path is unverified. Meta publishes all ads only for the EU; elsewhere the library holds political and issue ads only. That is Meta's dataset, not our limitation, and no tool can widen it. Separately, this actor is BYOK and no Meta access token was available to test with, so error paths are verified but a real ad row has never been produced. Treat this listing as unproven until that changes.

๐Ÿ’ก Why use Meta Ad Library Monitor?

Read this before anything else: coverage is not universal and it is not our choice. The Ad Library holds all ads only in the EU. Everywhere else it holds only political and issue ads. So a US SaaS company running product ads is largely not in this dataset, and fetch_status: not_found for such a company is Meta's coverage, not a failure of this actor. Every row carries a coverage_note saying what the search could and could not have found.

Within EU coverage it is excellent. Every active ad, the creative text, the platforms, the start date and a permanent snapshot of how the ad actually looked.

The advertiser gate is real. Meta's advertiser search is a fuzzy text search over page names, so searching "Apple" returns a lot of pages that are not Apple. Pages that fail the identity check are dropped, and advertisers_rejected tells you how many.

Spend and impressions are political ads only, and null is never zero. Meta publishes those numbers for the political archive and for nothing else.

๐Ÿงญ One sanctioned API, one gate

  1. Search the archive for the company by name, in the country audiences you chose. ad_reached_countries is required by Meta and a request without it fails outright, so it always has a value.
  2. Gate every advertiser page the fuzzy search returned against the company name and the domain stem. Pages that fail are dropped and counted.
  3. Return one row per surviving ad, flat, snake_case, with the identity columns repeated so the rows join back to your list.

A company with no matching ads gets exactly one row with the ad columns null and a status, so nothing silently disappears from your table.

๐Ÿ“‹ What data can Meta Ad Library Monitor extract?

Every row carries 27 flat fields. These are the ones a buyer actually filters and sorts on.

FieldTypeMeaning
degradedbooleanTrue when this row could not be produced normally, for example the company site was unreachable and no discovery could run. A degraded row is never charged.
degradation_reasonstring | nullWhy the row is degraded, in plain words. Null on a normal row.
company_domainstring | nullThe company domain this row is about, normalized. Null when only a handle or a name was supplied. This is the join key across the whole Mamba Labs fleet.
company_namestring | nullThe company name as supplied or derived. Improves search accuracy and is what the identity gate matches against.
page_idstring | nullThe Facebook page running the ad. Stable, unlike the page name, so this is the field to store if you are tracking one advertiser over time.
page_namestring | nullThe page name as Meta holds it. Meta advertiser search is fuzzy and returns near matches, so this value is checked against the company name by the identity gate before any row ships.
advertiser_matchstring | nullHow the matched page was confirmed to be this company: name_match or domain_match. Rows whose page failed both checks are not returned at all, and their count appears in advertisers_rejected.
advertisers_rejectedinteger | nullHow many distinct advertiser pages the fuzzy search returned that did NOT pass the identity gate. A search that returned eleven pages and kept one is a different fact from a search that returned one, and this is the column that tells them apart.
ad_idstring | nullMeta own identifier for this ad. Null on a summary row for a company with no matching ads.
ad_creative_bodystring | nullThe primary body text of the ad. Meta serves several variants for a multi variant ad; this is the first non empty one.
ad_creative_link_titlestring | nullThe headline on the ad link card, where the ad has one.
ad_creation_timestring | nullWhen the ad was created, ISO 8601.
ad_delivery_start_timestring | nullWhen the ad started running. This is the date to sort on for "what are they pushing right now".
ad_delivery_stop_timestring | nullWhen the ad stopped running. Null on an ad that is still running, which is a real and useful answer rather than a missing one.
ad_snapshot_urlstring | nullThe Ad Library permalink for this ad. Open it and Meta shows the creative as it ran. Meta own API hands back a render_ad link with the caller access token baked into the query string, so this actor returns the permalink instead: same ad, no credential riding along in your spreadsheet.
publisher_platformsstring | nullWhich Meta surfaces the ad ran on, comma separated: facebook, instagram, audience_network, messenger.
languagesstring | nullLanguages the ad was served in, comma separated.
impressionsstring | nullPOLITICAL AND ISSUE ADS ONLY. Meta publishes this for the political archive and for nothing else, so a commercial advertiser returns NULL here and null is NOT zero impressions. It arrives as a band, for example "10000 to 49999", and the band ships as the band rather than being flattened to a midpoint Meta never published.
spendstring | nullPOLITICAL AND ISSUE ADS ONLY, same as impressions. A commercial advertiser returns NULL and a buyer must not read that as zero spend. Also a band, also shipped as published.
currencystring | nullCurrency of the spend band, where a spend band exists.
estimated_audience_sizestring | nullMeta own estimate of the audience reached, as a band, on the ads that carry one.
ads_matchedinteger | nullHow many ads matched for this company before the maxAds cap. Repeated on every row for that company so the number survives a filter.
countries_searchedstring | nullWhich country audiences were actually searched. Coverage depends entirely on this: inside the EU the archive holds all ads, and outside it only political and issue ads, so a null result means very different things in the two cases.
coverage_notestring | nullPlain words about what the search could and could not have found, including the EU versus political only distinction and anything that stopped the request. Read this before concluding a company does not advertise.
coveragenumber | nullHow much of what this actor can return actually came back on this row, from 0 to 1. Computed over this actor value fields only, never over the identity or status columns. Null on a degraded row, where nothing was attempted. This is a reporting field: nothing is dropped for low coverage and no event fires on it.
fetch_statusstringok, not_found, not_extractable, blocked, identity_mismatch, auth_failed or skipped. Read this before reading any value on the row. not_found means we looked and there is nothing there; blocked and not_extractable mean we could not look, and they must never be read as an absence.
run_datestringISO 8601 timestamp of this run. Social counts move, so a row without a date is a number with no shelf life.

โš ๏ธ How to read these values. ad_snapshot_url is the field to hand to a human. It renders the ad exactly as it ran, which no amount of creative text can substitute for.

๐Ÿ› ๏ธ How to see what ads a company is running

  1. Create a Meta app at developers.facebook.com and generate an app access token. Political and issue ad access additionally needs a verified identity, which is Meta's requirement.
  2. Put the token in metaAccessToken. It is marked secret and never renders on this page.
  3. Put the company name in company_name and its domain in company_domain. The name drives the search and both drive the identity gate.
  4. Leave ad_reached_countries on EU unless you are specifically after political ads elsewhere.
  5. For a list, pass an array of objects with the same fields.

๐Ÿงช Using it in Clay

Add an Enrichment > Apify column, pick this actor, and map company_name and company_domain.

This actor returns MANY rows per company, unlike the rest of the Mamba Labs fleet. In Clay that is usually what you want in a dedicated ad research table rather than in your main account table. If you only need "are they advertising, yes or no", set maxAds to 10 and read ads_matched.

๐Ÿ’ต How much does it cost?

Pay per event. You are charged for output, never for input.

EventFires whenPrice
advertiser-checkedOnce per company for which the Ad Library was searched and a non degraded result was produced, whether or not any ads were found. An advertiser with no ads fires this once and nothing else, because looking and finding nothing is a real answer and it is the work you asked for. A degraded row, where no search ran, fires nothing.$0.0040
ad-returnedOnce per ad row actually returned, after the identity gate. Ads belonging to a page that failed the gate are not returned and are not charged: the work was done and the honest answer is that those ads are not this company.$0.0020

๐Ÿ’ณ What you are billed for. advertiser-checked fires once per company. ad-returned fires once per ad row actually returned after the gate, so a company with no ads costs one check and nothing more, and ads belonging to a rejected page cost nothing at all.

The API call runs on your own token, which is why the per ad price is low.

What the same coverage costs bought a la carte: The Apify Store carries Facebook Ad Library scrapers that drive the public web interface, which is fragile, blocked periodically and outside Meta terms. This actor uses the sanctioned Graph API on the buyer own token, so it cannot be blocked as a scraper and it cannot break when Meta changes its front end. The value added over the raw API is the advertiser resolution, the identity gate on a fuzzy page name search, and the flat one row per ad shape.

โŒจ๏ธ Input

FieldTypeRequiredMeaning
company_domainstringnoBare company domain, for example gymshark.com. Used to derive the advertiser search term when no company name is given, and used by the identity gate to check that a matched advertiser page really is this company.
company_namestringnoStrongly recommended here. Meta advertiser search is a fuzzy text search over page names, so the company name is what the identity gate compares a matched page against. Without it the gate falls back to the domain stem, which is weaker.
metaAccessTokenstringnoYOUR OWN Meta app access token, free to create at developers.facebook.com. REQUIRED: the Ad Library API is not open. Political and issue ad data additionally requires a verified identity on your Meta account, which is Meta requirement and not ours. Marked secret, so the value never renders on this page.
ad_reached_countriesstringnoWhich country audiences to search. This parameter is REQUIRED by Meta and a request without it fails outright. The EU set is where the Ad Library covers ALL ads rather than only political ones, so it is the default. Sent as a string for Clay compatibility.
ad_active_statusstringnoWhether to return currently running ads, stopped ads, or both. ACTIVE is the default because a currently running ad is the buying signal; ALL is what you want for a creative history or a competitive teardown. Sent as a string for Clay compatibility.
ad_typestringnoALL returns every ad the Ad Library holds for those countries. POLITICAL_AND_ISSUE_ADS narrows to the political archive, which is the only archive that carries impressions and spend, and which requires a verified identity on your Meta account. Sent as a string for Clay compatibility.
media_typestringnoNarrow to a creative format. Useful for a creative teardown where you only care about video, and irrelevant for a simple "are they advertising" check. Sent as a string for Clay compatibility.
maxAdsstringnoHow many ad rows to return per company. This is a cost dial, not a change of answer: the row always reports how many ads matched before the cap. Sent as a string for Clay compatibility.
skipCachestringnoWhen "false" (default) a successful lookup is cached for seven days and reused, which costs you nothing on a repeated run. Set "true" to force a fresh fetch. Sent as a string for Clay compatibility.
{
"company_domain": "gymshark.com",
"company_name": "Gymshark",
"ad_reached_countries": "EU",
"ad_active_status": "ACTIVE",
"maxAds": "25"
}

๐Ÿ“ค Output

Exports to JSON, CSV, Excel, HTML or XML. One flat, snake_case row per company. No nested objects, so it drops straight into Clay, a spreadsheet or a warehouse table without a flattening step.

{
"degraded": false,
"degradation_reason": null,
"company_domain": "gymshark.com",
"company_name": "Gymshark",
"page_id": "102590181603009",
"page_name": "Gymshark Women",
"advertiser_match": "name_match",
"advertisers_rejected": 9,
"ad_id": "2824771397896004",
"ad_creative_body": "Hol dir die soften, leichten Gymsets fรผrs Training (und den chaotischen Alltag) โœจ",
"ad_creative_link_title": "Everyday Seamless ab 30 โ‚ฌ ๐Ÿ’ธ",
"ad_creation_time": "2026-08-21",
"ad_delivery_start_time": "2026-08-21",
"ad_delivery_stop_time": null,
"ad_snapshot_url": "https://www.facebook.com/ads/library/?id=2824771397896004",
"publisher_platforms": "facebook, instagram, audience_network, messenger, threads",
"languages": "de",
"impressions": null,
"spend": null,
"currency": null,
"estimated_audience_size": null,
"ads_matched": 10,
"countries_searched": "AT, BE, BG, CY, CZ, DE, DK, EE, ES, FI, FR, GR, HR, HU, IE, IT, LT, LU, LV, MT, NL, PL, PT, RO, SE, SI, SK, GB",
"coverage_note": "Searched EU audiences, where the Ad Library covers all ads, plus non EU audiences where it covers only political and issue ads. A commercial advertiser outside the EU is legitimately absent.",
"coverage": 1,
"fetch_status": "ok",
"run_date": "2026-08-23T05:50:09.867Z"
}

false versus null, and why the difference matters

false means we looked and the answer is no. null means we could not look, or the platform withheld it. They are never interchangeable in this output. If you filter for companies with no presence on this platform, filter on false, because null rows are unknown rather than absent and including them will overstate your list.

๐Ÿ’ก Tips

  • Search the EU set first, even for a US company. It is the only region with full coverage, and plenty of US companies advertise into Europe.
  • ad_delivery_stop_time: null means the ad is still running. Sort on it to find live campaigns.
  • Read advertisers_rejected on a thin result. A common cause is a short or generic company name matching many pages, none of them the right one.
  • Do not read a null spend as zero spend. It means this is a commercial ad and Meta does not publish spend for those.
  • Set ad_active_status to ALL for a creative teardown, and leave it on ACTIVE for buying signals.

โš ๏ธ Known limits

  • Coverage is the whole product risk and it is not a bug. All EU delivered ads, plus issue and election ads worldwide. Measured on real advertisers: EU brands return full ad sets, US commercial advertisers frequently return nothing.
  • You need your own Meta access token, and for issue and election ads Meta additionally requires an identity confirmed account. Both are free.
  • Impressions and spend are issue and election ads only, and they arrive as bands. They ship as bands. Flattening a band to a midpoint would invent a precision Meta chose not to publish.
  • The advertiser search is fuzzy text, so an identity gate runs on the page name and rejected advertisers are counted on the row. Read advertisers_rejected before concluding a company runs no ads.
  • No public website route. Meta prohibits automated collection of its site in writing, so the token route is the only one here. If you need all public ads outside the EU, that is a different tool and it is not this one.

โ“ FAQ

Why does a company I know advertises come back with no ads? Almost always coverage: outside the EU the Ad Library holds only political and issue ads. Check countries_searched and coverage_note.

Why is spend null? Because the ad is commercial. Meta publishes spend for political and issue ads only, and null is not zero.

Do I need my own token? Yes. The Ad Library API is not open, and an actor that pretended otherwise would return empty columns and call them data.

Why does this actor return several rows per company when the others return one? Because the unit of the answer is an ad. A single row per company would have to nest the ads, and nested output breaks Clay.

Is this scraping Facebook? No. It is the documented Graph API on your own token.

๐Ÿงฉ Want other GTM data?

Mamba Labs builds a fleet of GTM enrichment actors that share one flat, Clay-ready output convention, so their rows join on company_domain with no cleaning step:

๐Ÿ•ต๏ธ Agent Accessibility Auditor๐Ÿค– AI Tooling Detector
๐Ÿ“ก B2B Buying Signals Aggregator๐Ÿš€ Prospect Engine
๐Ÿ“ Publishing Frequency Trackerโฉ Sequencer Lead Push
๐Ÿ”„ Company Change-Event Feed๐Ÿงญ Company Discovery List Builder
๐Ÿข Company Firmographic Enricher๐Ÿชช Company Identity Resolver
๐ŸŒ Company Social Presence Mapper๐Ÿท๏ธ Contact Classifier
๐Ÿ“ฌ Domain Deliverability Checker๐Ÿ”— Domain to LinkedIn URL Resolver
โœ‰๏ธ Work Email Waterfall Finder๐ŸŽช Event Presence Index
๐Ÿ’ฐ Funding and Press Signal Scanner๐Ÿง‘โ€๐Ÿ’ผ GTM Hiring Signal Scraper
๐Ÿ“‹ Job Posting Monitor๐Ÿงฑ Tech Stack Detector
๐ŸŽฏ ICP Fit Scorer๐Ÿ”‘ Job Board Keyword Scanner
โš–๏ธ Legal Entity Resolver๐Ÿ’ผ LinkedIn Company Page Mapper
๐Ÿ’ฌ LinkedIn Post Tracker and Comment Capture๐Ÿ“ธ Instagram and Facebook Brand Mapper
๐Ÿ“ฎ Outbound Stack Detector๐Ÿ“„ Page Finder and Extractor
๐Ÿ‘ค People Finder and Email Verifier๐Ÿ“Œ Pinterest Brand Presence Mapper
๐Ÿ›๏ธ Government Contract Award Monitor๐Ÿ“… Public Company Reporting Window Finder
๐Ÿ‘ฅ Team Page People Extractor๐ŸŽต TikTok Brand Presence Mapper
๐Ÿ… Workplace Program Detectorโ–ถ๏ธ YouTube Channel Stats Extractor

Every actor in the suite takes a domain or a company and returns one flat row, so they stack in the same Clay table without reshaping anything.

๐Ÿ› ๏ธ Need something custom built for you or your team? Tell us what you are trying to find and we will build it. Talk to Mamba Labs.

๐Ÿ†˜ Support

Issues, field requests and bug reports: open an issue on the actor's Issues tab. Mamba Labs reads every one.

โ„น๏ธ Sourcing and legal. Ads come from the Meta Ad Library through Facebook's Graph API and require your own access token, so that call is governed by your agreement with Meta. Coverage is exactly what Meta publishes: all ads in the EU, political and issue ads elsewhere. You are responsible for how you use the output.

Built by Mamba Labs.