Facebook Ads Library Scraper: Meta Ad Library Monitor avatar

Facebook Ads Library Scraper: Meta Ad Library Monitor

Pricing

from $3.40 / 1,000 ads

Go to Apify Store
Facebook Ads Library Scraper: Meta Ad Library Monitor

Facebook Ads Library Scraper: Meta Ad Library Monitor

Facebook Ads Library scraper for Meta ads on Facebook and Instagram. Paste any Ad Library link or search by keyword or Page ID, filter by start date, and get ad copy, CTAs, landing pages, run dates and image and video URLs. Monitor mode returns only new ads. No login.

Pricing

from $3.40 / 1,000 ads

Rating

0.0

(0)

Developer

The Mine Works

The Mine Works

Maintained by Community

Actor stats

1

Bookmarked

46

Total users

9

Monthly active users

9 days ago

Last modified

Share

Updated 10 Oct 2026: paste any Ad Library link, filter by start date.

60 Meta ads in 26 seconds: a recorded run searched 3 brand names in the US Ad Library and delivered 60 active ads with copy, CTAs and creative links

From The Mine Works, makers of Threads Scraper and B2B Leads Finder, with over 140,000 runs across 170+ public actors.

Why choose this actor?

  • 60 ads from 3 brand searches in 26 seconds, with no Facebook login. A recorded run searched three brand names in the US Ad Library and delivered 60 active ads in 26 seconds at 512 MB. You need no Facebook account, no Meta developer app and no access token.
  • The creative itself, not just the copy. Of 313 ads in our recent runs, 289 came with image links and 203 with video links, next to the ad text, headline, call to action, landing page, start date and the platforms each ad runs on (Facebook, Instagram, Messenger, Threads, WhatsApp, Audience Network).
  • You pay only for ads delivered. $3.40 to $5.80 per 1,000 ads depending on your Apify plan. Searches that come back empty or blocked are never charged: in that same run, the third brand returned nothing and cost nothing.
  • Paste the Ad Library link you are already looking at. Copy the address of any Ad Library search, advertiser page or single ad from your browser into adLibraryUrls. The actor keeps the filters in the link and drops tracking tags. In our test on 10 Oct 2026, a pasted advertiser link returned 30 ads and a pasted single ad link returned that one ad.
  • Only ads that started in your date window. Set startDateMin and startDateMax. In a test on 10 Oct 2026, a keyword search for July to September 2026 kept 9 of the 30 ads on the page and left out the other 21 without charging for them.

Run it on Apify

Bookmark this Actor on its Store page so it is one click away next time.

Part of The Mine Works Marketing, SEO and reviews family: Similarweb Scraper, Google Ads Transparency Scraper, Google News Scraper, Trustpilot Reviews Scraper, Google Trends Scraper, Semrush Scraper.

Try it in one minute

Paste this into the input's JSON tab and start the run. It returns 10 ads currently running in the US for "lab grown diamonds". We run exactly this every day as a health check, and it finishes in about 12 seconds.

{
"searchTerms": ["lab grown diamonds"],
"country": "US",
"adActiveStatus": "active",
"maxAdsPerSearch": 10
}

There are three ways to say what you want. adLibraryUrls takes links copied from the Ad Library in your browser: a keyword search, an advertiser's page of ads or a single ad. searchTerms takes keywords such as a brand, product or phrase, and matches the ad text of every advertiser, so a brand name also finds creators and resellers who mention it. pageIds takes numeric Facebook Page IDs, such as "162640217636958" (Clean Origin, a lab grown diamond brand), and returns ads from that one advertiser. You can mix all three in one run; links are searched first, then Page IDs, then keywords. The input form comes prefilled with one keyword and one Page ID, so clear the one you do not need. country is a two letter code such as US, GB, IN or AE, or ALL for every country.

Apify's free plan includes $5 of credit every month, which covers about 853 ads at this actor's price (the Free plan rate of $0.0058 per ad, plus the $0.005 start fee on each of 10 runs at the default memory).

Copy to your AI assistant

themineworks/meta-ad-library-scraper on Apify. Searches the public Meta (Facebook and Instagram) Ad Library by pasted Ad Library link, keyword or advertiser Page ID and returns one row per ad: advertiser, ad text, headline, call to action, landing page, start date, platforms, format, image and video URLs and the Ad Library search it came from (search_url), with no login. Call ApifyClient("TOKEN").actor("themineworks/meta-ad-library-scraper").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. Required: adLibraryUrls (list of facebook.com/ads/library links copied from a browser; the link's own filters are used), searchTerms (list of keywords) or pageIds (list of numeric Facebook Page IDs). Optional: searchType ("keyword_unordered" default or "keyword_exact_phrase"), country (default "US", or "ALL"), adActiveStatus ("active" default, "inactive", "all"), adType ("all" default or "political_and_issue_ads"), mediaType ("all" default, "image", "video", "meme"), startDateMin and startDateMax ("YYYY-MM-DD"; keep only ads that started in that window, inclusive), publisherPlatforms (list of "facebook", "instagram", "messenger", "audience_network", "threads", "whatsapp"), contentLanguages (list of two letter codes such as "en"), maxAdsPerSearch (default 10; the Ad Library page holds about 30 ads per search, so use more terms or Page IDs for more), proxyConfiguration (default Apify residential), monitorMode (default false; true delivers and charges only ads not delivered by an earlier run with the same input). Ad rows have no _type; each run also writes one row with _type "summary" and, when ads were delivered, one with _type "info"; neither is charged. A bad date ends the run before anything is fetched, with the reason in the summary row under input_error and nothing charged; a link that is not an Ad Library search is skipped and listed in the summary row under invalid_urls. Full spec: GET https://api.apify.com/v2/acts/themineworks~meta-ad-library-scraper/builds/default (Bearer TOKEN), which returns inputSchema and readme. Token: https://console.apify.com/account/integrations?fpr=ymnoit&utm_source=apify-readme&utm_medium=referral

Key features

  • Pasted link, keyword or advertiser search. Paste Ad Library links with adLibraryUrls, search ad text across all advertisers with searchTerms (any words, or the exact phrase with searchType), or pull one advertiser's ads with pageIds. Filter by country, by active or inactive status, by ad type (all ads, or political and issue ads), by media type (image, video or meme), by platform (publisherPlatforms) and by ad language (contentLanguages).
  • Start date window. startDateMin and startDateMax keep only ads that started running between those two dates, both included. Ads outside the window are left out and not charged.
  • 21 fields per ad. Archive ID, advertiser Page ID, name and link, active flag, start and end dates, platforms, format, ad text, headline, caption, call to action text and type, landing page, variant count, image URLs, video URLs, Ad Library link, the search the ad came from and capture time.
  • About 30 ads per search. The actor reads the first page of results the Ad Library serves for each link, keyword or Page ID, which held 22 to 30 ads per search in our runs. maxAdsPerSearch trims that number; to get more ads, add more links, keywords or Page IDs.
  • Links only, never media downloads. Image and video creative come as Meta CDN URLs. The actor never downloads media, so runs stay small and fast.
  • Built in stop switches. If two searches in a row return no ads, the run stops early instead of working through the rest of your list against a block. A cost guard also ends a run that makes many requests without delivering ads.

How to use it

Basic: ads for one keyword

{
"searchTerms": ["meal kit delivery"],
"country": "US",
"adActiveStatus": "active",
"maxAdsPerSearch": 30
}

30 is about as many as one search returns. Setting maxAdsPerSearch higher does not get more ads from the same search.

Several brands in one run

{
"searchTerms": ["RYZE Superfoods", "Arrae", "Ironmaid"],
"country": "US",
"adActiveStatus": "active",
"maxAdsPerSearch": 45
}

This is the input of our recorded run: 60 ads in 26 seconds. Each keyword is a separate search with its own fresh IP. Keyword search matches ad text, so the "Arrae" search also returned ads from creators who mention the brand. Use pageIds when you want one advertiser's own ads only.

{
"adLibraryUrls": [
"https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&is_targeted_country=false&media_type=all&search_type=page&view_all_page_id=162640217636958",
"https://www.facebook.com/ads/library/?id=913692170489722"
],
"maxAdsPerSearch": 30
}

Run your search on facebook.com/ads/library, set the filters you want, then copy the address bar. In our test on 10 Oct 2026 this input returned 31 ads: 30 from the advertiser link and the one ad from the single ad link. The link's own filters are used as they are. Filters the link leaves out, such as country, come from the input fields. Parts of the link that are not search filters, such as fbclid or utm_source, are dropped and named in the log. A link with no keyword, advertiser or ad id in it is skipped with a message in the log and listed in the summary row under invalid_urls.

Ads that started in a date window

{
"searchTerms": ["lab grown diamonds"],
"country": "US",
"adActiveStatus": "all",
"startDateMin": "2026-07-01",
"startDateMax": "2026-09-30",
"maxAdsPerSearch": 30
}

In our test on 10 Oct 2026 this kept 9 of the 30 ads on the page, with start dates from 2 Jul to 11 Sep 2026, and charged for those 9 only. Either date can be left out for an open window. Both dates are included. A date that is not written as YYYY-MM-DD stops the run at the start with a message saying which field is wrong, before any search is made, so no ads are charged.

Exact phrase, one platform, one language

{
"searchTerms": ["free shipping"],
"searchType": "keyword_exact_phrase",
"publisherPlatforms": ["threads"],
"contentLanguages": ["en"],
"maxAdsPerSearch": 5
}

These three filters are the Ad Library's own. In our test on 10 Oct 2026 all 5 ads returned ran on Threads.

Competitor creative teardown, by Page ID

{
"pageIds": ["107940537227344", "108401623899597"],
"country": "US",
"adActiveStatus": "all",
"maxAdsPerSearch": 30
}

To find an advertiser's Page ID, run a keyword search for the brand first: every ad row carries page_id and page_name. Then track that advertiser by ID. adActiveStatus: "all" includes ads that have stopped running, which shows how long the brand kept each creative live.

Weekly watch on a category

{
"searchTerms": ["lab grown diamond", "moissanite ring", "engagement ring sale"],
"country": "US",
"adActiveStatus": "active",
"maxAdsPerSearch": 30
}

Save this as a task and schedule it weekly (Apify Console, Schedules, Create new). Compare ad_archive_id values with last week's export to see which ads are new and which were switched off. Each run delivers and charges every ad it finds again; add "monitorMode": true to get only the ads you have not received before (see Run it on a schedule).

Several markets for the same brand

The Ad Library is country scoped, so run the same input once per country (US, GB, IN, AE and so on), for example as one saved task per market. An ad running only in Germany will not appear in a US search.

Political and issue ads

{
"searchTerms": ["climate"],
"country": "US",
"adType": "political_and_issue_ads",
"adActiveStatus": "all",
"maxAdsPerSearch": 30
}

This filter limits results to the Ad Library's political and issue category. The rows carry the same fields as any other ad; spend and impression ranges are not extracted.

Input parameters

ParameterTypeDefaultWhat it does
adLibraryUrlsarray of stringsnoneLinks copied from facebook.com/ads/library: a keyword search, an advertiser's page of ads (view_all_page_id=) or a single ad (id=). The link's filters are used as they are; filters it leaves out come from the fields below. Searched first.
searchTermsarray of stringsnone (prefilled with lab grown diamonds)Keywords. Each one is a separate Ad Library search that matches ad text across all advertisers.
pageIdsarray of stringsnone (prefilled with one Page ID)Numeric Facebook Page IDs. Each one returns that advertiser's ads. Searched before searchTerms.
searchTypestringkeyword_unorderedHow searchTerms match: keyword_unordered (any words, any order) or keyword_exact_phrase (the words together, in order).
countrystringUSTwo letter country code of the Ad Library region, such as US, GB, IN, AE, or ALL for every country.
adActiveStatusstringactiveactive, inactive or all.
adTypestringallall for every ad, or political_and_issue_ads.
mediaTypestringallall, image, video or meme (image and meme ads).
startDateMinstringnoneKeep only ads that started on or after this date, YYYY-MM-DD.
startDateMaxstringnoneKeep only ads that started on or before this date, YYYY-MM-DD.
publisherPlatformsarray of stringsnone (all)Only ads shown on these platforms: facebook, instagram, messenger, audience_network, threads, whatsapp. Other values are ignored with a log line.
contentLanguagesarray of stringsnone (all)Only ads in these languages, as two letter codes such as en, es, de.
maxAdsPerSearchinteger10Most ads kept from each link, keyword or Page ID, 1 to 2,000. A search returns about 30, so values above 30 change nothing. Also your cost cap.
downloadImagesbooleanfalseKept for older inputs. Has no effect: image URLs are always returned in image_urls and no media is downloaded.
downloadVideosbooleanfalseKept for older inputs. Has no effect: video URLs are always returned in video_urls.
proxyConfigurationobjectApify residentialProxy for the run. Leave it as it is: Meta challenges datacenter IPs, and the actor only fetches small HTML pages.
monitorModebooleanfalseDeliver only ads not delivered by an earlier run with the same input. Skipped ads are not charged. Made for daily or weekly schedules.

If adLibraryUrls, searchTerms and pageIds are all empty, the run writes only a summary row and charges no ads. If startDateMin or startDateMax is not a real date in YYYY-MM-DD form, or startDateMin is later than startDateMax, the run stops at the start with a message naming the field, before any search is made, so no ads are charged. The same happens when every entry in adLibraryUrls is unusable and there are no keywords or Page IDs.

What data do you get?

One row per ad, plus a summary row per run. Ad rows have no _type field.

The advertiser: page_id, page_name, page_url (the Facebook Page link).

The ad: ad_archive_id (Meta's Ad Library ID), snapshot_url (the ad's page in the Ad Library), is_active, start_date, end_date, publisher_platforms (for example FACEBOOK, INSTAGRAM, MESSENGER, THREADS, WHATSAPP, AUDIENCE_NETWORK), display_format (seen in our runs: VIDEO, DCO, IMAGE, DPA, CAROUSEL), collation_count (how many versions Meta groups under this ad).

The creative: ad_body (primary text), ad_title (headline), ad_caption (usually the display domain), cta_text and cta_type (for example "Shop now" and SHOP_NOW), link_url (landing page), image_urls and video_urls (Meta CDN links; video ads also carry their preview image in image_urls).

Where and when: search_url, the Ad Library search page the ad was found on (your pasted link, or the search the actor built from a keyword or Page ID), so rows from several searches in one run can be told apart; scraped_at, the ISO time the row was written.

A note on dates: Meta gives active ads an end date too, the day you ran the search, so end_date on an active ad means "still running as of this date". Dates are midnight US Pacific time, written in UTC (for example 2026-09-24T07:00:00.000Z).

Summary row (_type: "summary", never charged): ads (delivered), charged_for, charge_failures, yield_guard (with empty_streak, total_empty and yield_guard_tripped, which says whether the run stopped after two empty searches in a row) and scraped_at. With a date window set it also has start_date_filter (start_date_min, start_date_max and left_out_outside_window, the number of ads left out). When a pasted link could not be used it has invalid_urls, one message per link.

Info row (_type: "info", never charged): written when at least one ad was delivered, with the count and a scheduling tip.

Stable fields for automations

These fields were present in all 313 ad rows of our recent runs, except search_url, which was added on 10 Oct 2026 and was in all 80 ad rows of our tests that day. Their names will not change, so a Google Sheet, Zapier zap or n8n flow can map them once.

FieldWhat it is
ad_archive_idMeta's Ad Library ID, the key to store and compare on
page_idAdvertiser's Facebook Page ID
page_nameAdvertiser's Page name
page_urlAdvertiser's Facebook Page link
is_activeTrue while the ad is running
start_dateDate the ad started, ISO 8601
end_dateDate it stopped, or the search date for a running ad
publisher_platformsPlatforms the ad runs on
display_formatCreative format, such as VIDEO or CAROUSEL
cta_typeCall to action code, such as SHOP_NOW
link_urlLanding page
image_urlsImage links; can be an empty list
video_urlsVideo links; can be an empty list
snapshot_urlThe ad's page in the Ad Library
scraped_atWhen this row was written, ISO 8601
search_urlThe Ad Library search the ad came from

ad_caption and cta_text were also in every row. ad_body was missing from 2 of 313 rows, ad_title from 28 and collation_count from 120, because Meta had no value for them, so treat those three as optional. Catalog ads (DCO and DPA) sometimes show Meta's template field names, such as product.name, in ad_body and ad_title instead of real copy, because that is what the Ad Library itself displays.

Output examples

A video ad (recorded run cghR3RKXCUuOiBJW0, US, 24 Sep 2026; CDN links trimmed):

{
"ad_archive_id": "1453706910129969",
"page_id": "107940537227344",
"page_name": "RYZE Superfoods",
"page_url": "https://www.facebook.com/ryzesuperfoods/",
"is_active": true,
"start_date": "2026-07-13T07:00:00.000Z",
"end_date": "2026-09-24T07:00:00.000Z",
"publisher_platforms": ["FACEBOOK", "INSTAGRAM"],
"display_format": "VIDEO",
"ad_body": "RYZE is powered by functional mushrooms and adaptogens. Our creamy and delicious blend features six functional mushrooms, prebiotics, zero added sugar and 100% organic or non-GMO ingredients. ...",
"ad_title": "Pour Yourself a Better Cup of Coffee ☕️",
"ad_caption": "shop.ryzesuperfoods.com",
"cta_text": "Shop now",
"cta_type": "SHOP_NOW",
"link_url": "https://shop.ryzesuperfoods.com/fb",
"collation_count": 1,
"image_urls": ["https://scontent.fcia6-1.fna.fbcdn.net/v/t39.35426-6/742895735_1585698500035948_4695356029445265094_n.jpg?..."],
"video_urls": ["https://video.fcia6-1.fna.fbcdn.net/o1/v/t2/f2/m366/AQPzV2NbuIF0KN3MnF577OC5DRBPhvHho4mbDIeVLpVx1gK6MSkAw..."],
"snapshot_url": "https://www.facebook.com/ads/library/?id=1453706910129969",
"scraped_at": "2026-09-24T08:00:30.480Z"
}

A carousel ad found by a keyword search (recorded run WLT3r1crfueypC8IS, India, 24 Sep 2026; text and links trimmed):

{
"ad_archive_id": "913692170489722",
"page_id": "167389649992739",
"page_name": "Australian Diamond Brokers",
"page_url": "https://www.facebook.com/australiandiamondbrokers/",
"is_active": true,
"start_date": "2024-03-18T07:00:00.000Z",
"end_date": "2026-09-24T07:00:00.000Z",
"publisher_platforms": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER"],
"display_format": "CAROUSEL",
"ad_body": "Huge range Of 300,000+ Natural and Lab Grown Diamonds. ...",
"ad_title": "Australian Diamond Brokers",
"ad_caption": "australiandiamondbrokers.com",
"cta_text": "Book now",
"cta_type": "BOOK_TRAVEL",
"link_url": "http://www.australiandiamondbrokers.com/",
"collation_count": 1,
"image_urls": [
"https://scontent.fkov1-1.fna.fbcdn.net/v/t39.35426-6/431505730_1092793451764261_5935955348634153424_n.jpg?...",
"https://scontent.fkov1-1.fna.fbcdn.net/v/t39.35426-6/431446828_1445981082948368_627989504511235869_n.jpg?..."
],
"video_urls": [
"https://video.fkov1-1.fna.fbcdn.net/o1/v/t2/f2/m412/AQNTFLF9xz00BsErxwSa7CUVbg5xgSRHJ6mQAx0BQuiGwX3LDTgMIbimO14i84s0uLn3Lh0T75jrbURPXxptwAM.mp4?..."
],
"snapshot_url": "https://www.facebook.com/ads/library/?id=913692170489722",
"scraped_at": "2026-09-24T13:26:16.475Z"
}

The full row had 4 image links and 5 video links, one per carousel card.

An ad with no headline (same run): ad_title is missing because the ad has none.

{
"ad_archive_id": "1189548263302663",
"page_id": "507817735747837",
"page_name": "Starbyjainjewellers",
"page_url": "https://www.facebook.com/61570050003630/",
"is_active": true,
"start_date": "2025-12-23T08:00:00.000Z",
"end_date": "2026-09-24T07:00:00.000Z",
"publisher_platforms": ["FACEBOOK", "INSTAGRAM"],
"display_format": "VIDEO",
"ad_body": "People often ask, “Are lab-grown diamonds fake?” 💎 ...",
"ad_caption": "instagram.com",
"cta_text": "Visit Instagram profile",
"cta_type": "VIEW_INSTAGRAM_PROFILE",
"link_url": "http://instagram.com/starbyjainjewellers",
"collation_count": 1,
"image_urls": ["https://scontent.fkov1-1.fna.fbcdn.net/v/t39.35426-6/593712614_2054003398729145_6428826672116963368_n.jpg?..."],
"video_urls": ["https://video.fkov1-1.fna.fbcdn.net/o1/v/t2/f2/m86/AQNLNoar94LOKfbW0LfsL5PhtvZLbpDd3VTfAoUvYmIQnX4yiIKbACcm8ggSNo1QBT9M1fzHzgZRBb-lj7AdJJ3Vk9WndV_IlVoaXqY.mp4?..."],
"snapshot_url": "https://www.facebook.com/ads/library/?id=1189548263302663",
"scraped_at": "2026-09-24T13:26:14.431Z"
}

The summary row of the recorded run (60 ads, all charged; the Ironmaid search returned nothing, which counts as one empty search):

{
"_type": "summary",
"ads": 60,
"charged_for": 60,
"charge_failures": 0,
"yield_guard": { "empty_streak": 1, "total_empty": 1, "yield_guard_tripped": false },
"scraped_at": "2026-09-24T08:00:50.740Z"
}

A run where Meta returned nothing (our health check run Mi91iOMftzcH2OfYJ, 23 Sep 2026): no ads, no ad charges, only the start fee. A rerun of the same input a minute later returned 10 ads.

{
"_type": "summary",
"ads": 0,
"charged_for": 0,
"charge_failures": 0,
"yield_guard": { "empty_streak": 1, "total_empty": 1, "yield_guard_tripped": false },
"scraped_at": "2026-09-23T09:03:48.063Z"
}

Pricing

Pay per event. You are charged for each ad delivered to your dataset, plus a small start fee per run. The rate falls as your Apify plan rises.

EventFreeBronzeSilverGold and above
Ad delivered (ad-scraped), per ad$0.0058$0.005$0.0042$0.0034
Per 1,000 ads$5.80$5.00$4.20$3.40
Run start (apify-actor-start)$0.005 per GB of run memory, minimum one eventsamesamesame

The start fee, exactly. Apify's apify-actor-start event is charged once when a run starts, one event per GB of memory with a minimum of one. At the default 512 MB, and at 1 GB, that is one event, $0.005 per run. A 4 GB run would pay $0.02. This actor does not need more than 512 MB.

Never charged: searches that return no ads (blocked, empty or no matches), ads left out by your start date window, links that are not Ad Library searches, the summary row and the info row. An ad is charged only after it is saved to your dataset.

Charged once per search that finds it: the actor removes repeats within one search, not across searches. An ad that matches two of your keywords is delivered and charged once for each. In a 10 keyword run with overlapping terms ("lab grown diamond" and "lab grown diamonds"), 24 of 219 ads were repeats. Use distinct keywords, or Page IDs, to avoid paying twice.

What real jobs cost on Gold: the recorded run (60 ads) cost $0.204 plus $0.005. A weekly watch of 3 keywords at about 30 ads each costs about $0.31 a week. Ten competitors by Page ID at up to 30 ads each costs up to $1.02 plus $0.005.

There is no price change scheduled for this actor. The Pricing tab on this page always shows the rate for your own plan.

Run it on a schedule

Switch on monitorMode and the actor remembers which ads it has delivered for this input. Each later run delivers only ads you have not received before, which are the ads that went live since the last run, and you pay only for those.

  1. Fill in the input, tick Monitor mode, and save it as a task.
  2. In Apify Console open Schedules, click Add schedule, and pick Daily or Weekly (or a cron such as 0 8 * * 1).
  3. Add the saved task to the schedule and click Save.
{
"searchTerms": ["lab grown diamond", "moissanite ring"],
"country": "US",
"adActiveStatus": "active",
"maxAdsPerSearch": 30,
"monitorMode": true
}

The first run delivers every ad it finds. Each later run with the same input delivers only ads whose ad_archive_id it has not delivered before. Skipped ads are never charged; the start fee applies to every run as usual. The Ad Library page shows about 30 ads per search, so a new ad is caught when it is among them; schedule often enough that new ads do not scroll past. The last row of each run (_type: "info") gives new_this_run, skipped_already_seen and a scheduling tip. The history belongs to the input: change the links, search terms, Page IDs, country, dates or other filters and a new history starts; change maxAdsPerSearch and it carries on. Saving an older task again with the new fields left empty keeps its history. Monitor mode shows new ads, not ads that were switched off; for that, compare two full runs.

FAQ

What is the Meta Ad Library? It is Meta's public archive of ads running on Facebook, Instagram, Messenger, Threads, WhatsApp and the Audience Network, which anyone can search at facebook.com/ads/library without logging in. This actor runs the same searches and returns the results as rows.

How many ads can I get? About 30 per link, keyword or Page ID: the actor reads the first page of results the Ad Library serves for each search (22 to 30 per search in our runs) and does not page further. For more ads, add more links, keywords or Page IDs. A start date window can leave fewer, because ads on that page that started outside the window are left out. Each run also stops early if two searches in a row return nothing.

How fresh is the data? Live. Each run searches the Ad Library at the moment it runs. is_active and end_date reflect that day.

Do I need a Facebook account, a Meta developer app or an access token? No. The actor reads the public Ad Library page. There is no login, no app and no token.

Do I need a proxy? No setup is needed. The actor uses Apify's residential proxy by default because Meta challenges datacenter IPs. It fetches only small HTML pages, never images or videos.

Why did a search return no ads? Either nothing matched in that country and status, or Meta refused the request that time. The actor tries each search up to 3 times before moving on, and an empty search is never charged. If a whole run comes back empty, wait a few minutes and run it again: one of our daily health checks returned nothing, and the same input a minute later returned 10 ads.

Does it include spend, impressions or audience data? No. Meta publishes spend and impression ranges only for political and issue ads, and this actor does not extract them even there. You get creative and metadata for every ad type.

Can I download the images and videos? The rows contain direct links in image_urls and video_urls, and you can download from those links yourself. Meta's CDN links expire after a while, so save the files you need soon after the run. The downloadImages and downloadVideos options no longer do anything.

How do I find an advertiser's Page ID? Run a keyword search for the brand: every ad row carries page_id next to page_name. You can also open any of the brand's ads in the Ad Library and read the Page ID there. Or skip the ID: open the advertiser's ads in the Ad Library and paste that link into adLibraryUrls.

Can I paste a link from the Ad Library? Yes. Put it in adLibraryUrls. Three kinds of link work: a keyword search (q=), an advertiser's page of ads (view_all_page_id=) and a single ad (id=). The actor keeps these filters from the link: country, active_status, ad_type, media_type, search_type, start_date[min], start_date[max], publisher_platforms, content_languages, is_targeted_country and sort_data. Anything else in the link is dropped and named in the log. A link to a normal Facebook page, such as facebook.com/brandname, is not an Ad Library link and is skipped.

How do the date filters work? startDateMin and startDateMax keep ads whose start_date falls between the two dates, both included, compared as the calendar day the Ad Library shows. The actor also passes the window to the Ad Library so the page holds more ads from that period. The date range inside a pasted link works differently: the Ad Library treats it as "was this ad running at some point in the window". In our test on 10 Oct 2026, a pasted keyword link with a January 2024 range returned ads that started in November and December 2023. If you want ads that started in the window, use startDateMin and startDateMax; they also apply to pasted links.

How do I get the data out? From the run's Storage tab as JSON, CSV, Excel, XML or HTML, or through the Apify API. CSV and Excel flatten the URL lists into numbered columns.

Can I run it on a schedule or get only new ads? Yes. Save your input as a task and add a schedule in Apify Console (Schedules, then Create new). Set monitorMode to true and each run delivers, and charges, only ads not delivered by an earlier run with the same input.

Can I use it from Claude, ChatGPT or another AI assistant?

  • Connector URL: https://mcp.apify.com/?tools=themineworks/meta-ad-library-scraper.
  • Claude: Settings > Connectors > Add custom connector, paste the URL, sign in with Apify.
  • ChatGPT: developer mode, add an MCP connector with the URL, sign in with Apify.
  • Cursor or VS Code: add it as an HTTP MCP server with that URL.
  • Claude Code: claude mcp add -t http meta-ad-library-scraper "https://mcp.apify.com/?tools=themineworks/meta-ad-library-scraper".

It is also one of the tools inside our E-commerce Intel MCP server, which bundles 8 e-commerce research tools.

Is it legal to scrape the Meta Ad Library? The actor reads only the public Ad Library, a transparency archive Meta makes available to anyone without logging in. Ad creative can still contain personal data, such as a face or a name in a testimonial, and you are responsible for how you use it, including Meta's terms and data protection law such as GDPR and CCPA. This is general information, not legal advice. This actor is independent and not affiliated with or endorsed by Meta.

Integrations

Results land in a standard Apify dataset, so they connect without extra code:

  • Google Sheets: send each run's ads to a sheet with Apify's Google Sheets integration.
  • Make, Zapier and n8n: start a run and read its dataset with the official Apify apps and nodes.
  • Webhooks: get a call to your own URL when a run succeeds, then fetch the dataset.
  • API and SDKs: start runs and read results with the Apify API, or the Python and JavaScript clients.
  • MCP clients: Claude, ChatGPT, Cursor and other MCP clients can call the actor through https://mcp.apify.com/?tools=themineworks/meta-ad-library-scraper.

More from The Mine Works

Marketing, SEO and reviews

Social media and video

Leads and business directories

LinkedIn

Real estate

Science, health and government data

Jobs and hiring

E-commerce and marketplaces

Company and business data

Food and local services

Developer and AI tools

More tools

Support

Found a bug or need a field? Open an issue on the Issues tab of this actor. To ask for a new source, email dmineworks@gmail.com.

Facebook Ads Library Scraper pulls ads from Meta's public Ad Library by pasted link, keyword or Page ID, with copy, CTAs, landing pages and creative links, an optional start date window, no login, from $3.40 per 1,000 ads.