Meta Ad Library Scraper with Variations: Facebook Ads, Media avatar

Meta Ad Library Scraper with Variations: Facebook Ads, Media

Pricing

from $0.14 / 1,000 ad extracteds

Go to Apify Store
Meta Ad Library Scraper with Variations: Facebook Ads, Media

Meta Ad Library Scraper with Variations: Facebook Ads, Media

Meta Ad Library scraper for Facebook and Instagram ads: flat rows with variation counts and direct image and video URLs. Search by keyword, advertiser Page id or library URL, no login. Ad text, headline, link, CTA, ISO dates, platforms. Pay per ad.

Pricing

from $0.14 / 1,000 ad extracteds

Rating

0.0

(0)

Developer

Detroit Web Agent - Open Data

Detroit Web Agent - Open Data

Maintained by Community

Actor stats

0

Bookmarked

18

Total users

6

Monthly active users

3 hours ago

Last modified

Share

Meta Ad Library Variations & Media URLs

Meta Ad Library scraper for Facebook and Instagram ads, no login: search by keyword or page and get flat rows with ISO dates, plus an only-new mode for monitoring.

Meta Ad Library Scraper: features, price and a real output row

Run it free on Apify

Price per 1,000 adsFree planStarterScaleBusiness
This Actor$0.65$0.65$0.65$0.65
Most-used alternative$0.75$0.75$0.75$0.75

Meta Ad Library Scraper sample output table from a real run

Search the public Meta Ad Library (facebook.com/ads/library) by keyword, advertiser Page id or a pasted library URL, and get one clean row per ad: advertiser, ad text, headline, link, call to action, image and video URLs, dates, platforms and variation count. No Facebook login, no cookies of yours, no browser.

  • In short: Meta Ad Library Scraper (Apify actor transparent_meteorite/meta-ad-library) returns ads from the public Meta Ad Library as flat, typed rows. It reads the same public pages and paging calls the Ad Library website uses, with no account.
  • Who it is for: marketers and agencies researching competitor creative, ecommerce and app teams, ad-intelligence tools, journalists checking who advertises what.
  • Input: search terms, advertiser Page ids and/or Ad Library URLs, plus country, active status, ad type, media type, start-date range, platforms, languages, max ads (1 to 50,000), only-new mode.
  • Output: 34 fields per ad: ad id, advertiser Page id, name, categories, like count, profile link and picture, active flag, start and last-seen dates, days running, platforms, body text, headline, link, caption, CTA, display format, media type, image and video URLs, carousel card count, variations count, Library URL, scrape time. Political and issue ads also carry Meta's published spend, impressions and reach ranges.
  • Pricing: pay per event. $0.00065 per ad delivered on every Apify plan, plus a start event of $0.00005 per GB of run memory. Duplicates and ads skipped by only-new mode are never charged.
  • Limits: only what the Ad Library publishes: no targeting, no exact spend for commercial ads, no ad performance. Meta rate-limits datacenter IPs, so residential proxy is the default.

Key facts

  • Actor name: Meta Ad Library Scraper
  • Data source: the public Meta Ad Library
  • Output formats: JSON, CSV, Excel, XML, HTML table, RSS (Apify dataset)
  • Access: Apify Console, REST API, JavaScript/Python clients, schedules, webhooks, Apify MCP server
  • Login or third-party API key needed: no, only an Apify account
  • Also known as: Facebook ads scraper, Instagram ads scraper, Meta Ad Library API alternative, competitor ad research tool

What is Meta Ad Library Variations & Media URLs?

Public Meta Ad Library (Facebook and Instagram ads) as flat rows with variation counts and direct image and video URLs. Search by keyword, advertiser Page id or library URL, no login. Ad text, headline, link, CTA, ISO dates, platforms. Pay per ad. Run it from the Apify Console, the API or a schedule, and export the results as JSON, CSV, Excel or HTML.

Run in 30 seconds

  1. Open the prefilled run (free Apify account; it creates a saved task with a working input).
  2. Press Start. The input is small on purpose, so the first run is quick and costs a few cents at most.
  3. Open the Output tab, switch to Table view, download as CSV, Excel or JSON.

Prefilled input:

{
"searchTerms": [
"coffee"
],
"country": "US",
"maxItems": 10
}

Ready-made presets by use case (each opens as a saved task you can edit):

Why choose this over alternatives

  • Flat, typed columns: media URLs, link, CTA and ISO dates in their own fields, where the alternative we tested returns a raw nested JSON snapshot.
  • A variation count on every ad in our test (the alternative: 63% of ads).
  • The same number of ads for the same query, at a lower price per ad.
  • Search by keyword, advertiser Page id or pasted Ad Library URL. No login.
This actorTypical alternatives
Price per ad$0.00065$0.00075
Ads returned for a 30-ad request30 of 3030 of 30
Time for 30 ads8 to 10 s9 s
Ads with a variation count100%63%
Ads with an image or video URL100%not measured
Output shapeflat typed columnsraw nested JSON

Measured 2026-10-11 (source: head-to-head test runs on the same query, "running shoes", United States, active ads, 30 ads each, one run per side, both runs succeeded). Speed and coverage were level; the differences are output shape, variation count and price. One run each is a small sample.

What you get: output fields

Every row has the same 54 keys: the 32 camelCase fields below plus 22 flat snake_case copies of the same data (listed after the table). A field is null (or an empty list) when the Library does not publish it for that ad.

FieldTypeMeaning
adArchiveIdstringThe ad's Library id. Stable, use it as your upsert key
libraryUrlstringDirect link to the ad in the Ad Library
pageId, pageNamestringThe advertiser Page, as the Library shows it publicly
pageCategoriesarrayThe Page's categories, for example ["Shoes"]
pageLikeCountnumberThe Page's like count as shown in the Library
pageProfileUrl, pageProfilePictureUrlstringThe advertiser's public profile link and picture
isActivebooleanWhether the ad was running when it was read
startDate, endDatestringISO dates (YYYY-MM-DD). endDate is the last day the Library saw the ad running
daysRunningnumberWhole days from startDate to endDate (or to the day of the run when the Library gives no end date)
platformsarrayAny of FACEBOOK, INSTAGRAM, MESSENGER, AUDIENCE_NETWORK, THREADS
bodyText, title, linkDescription, captionstringThe ad copy: main text, headline, description line and display link
linkUrlstringWhere the ad sends people
ctaText, ctaTypestringButton label and type, for example "Shop now" and SHOP_NOW
displayFormatstringThe creative format exactly as the Library reports it, for example DCO
mediaTypestringvideo when the ad has a video, image when it has only images, otherwise the display format in lower case
imageUrls, videoUrlsarrayMeta CDN links to the creative files
cardCountnumberNumber of cards in a carousel or multi-creative ad
variationsCountnumberHow many near-identical versions the Library groups with this ad. 1 when the Library reports no grouping
spend, impressionsText, reachEstimatemixedOnly when Meta publishes them (political and issue ads, some regions); otherwise null
targetedCountries, adCategoriesarrayOnly when Meta publishes them; otherwise empty
languagesarrayThe language filter you set, echoed back. Null when you set none. The Library does not label each ad's language
searchedForstringWhich search term, page:<id> or URL found this ad
scrapedAtstringISO timestamp of extraction

Flat copies, same values, named the way other ad scrapers name them: ad_archive_id, page_id, page_name, page_profile_picture_url, page_like_count, body_text, caption, cta_text, cta_type, link_url, link_description, title, image_urls, video_hd_url, video_sd_url, video_preview_image_url, start_date, end_date, is_active, publisher_platforms, collation_count, ad_library_url. The video fields are null on ads without a video.

With fetchDetails on, each row also has a details object: collationId, byline (paid for by), disclaimerLabel, pageIsDeleted, containsDigitalCreatedMedia, containsSensitiveContent, totalActiveTimeSeconds, isReshared, brandedContent, extraLinks, extraTexts, extraImageUrls, extraVideoUrls, pageCategories. It uses the same response, so it costs nothing extra.

Image and video URLs are Meta CDN links and expire after some days; download them promptly if you need the files.

Sample output

A real row from a test run on 2026-10-11 (build 0.1.6). The CDN URLs are shortened with ... and only the first image URL is shown; nothing else is changed.

{
"adArchiveId": "1339489931715040",
"pageId": "71740214065",
"pageName": "KURU Footwear",
"pageCategories": ["Shoes"],
"pageLikeCount": 184400,
"pageProfileUrl": "https://www.facebook.com/kurufootwear/",
"pageProfilePictureUrl": "https://scontent-mia3-1.xx.fbcdn.net/v/t39.35426-6/735831932_1039040892413861_1585147103869771473_n.jpg?...",
"isActive": true,
"startDate": "2026-07-06",
"endDate": "2026-10-10",
"daysRunning": 96,
"platforms": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK"],
"bodyText": "{{product.brand}}",
"title": "{{product.name}}",
"linkUrl": "https://www.kurufootwear.com/pages/outbreak",
"linkDescription": "{{product.description}}",
"caption": "shopkuru.com",
"ctaText": "Shop now",
"ctaType": "SHOP_NOW",
"displayFormat": "DCO",
"mediaType": "video",
"imageUrls": ["https://scontent-mia3-3.xx.fbcdn.net/v/t39.35426-6/735287112_941136988978881_7755665091702434084_n.jpg?..."],
"videoUrls": ["https://video-mia5-1.xx.fbcdn.net/o1/v/t2/f2/m366/...mp4?..."],
"cardCount": 3,
"variationsCount": 1,
"adCategories": [],
"spend": null,
"reachEstimate": null,
"impressionsText": null,
"targetedCountries": [],
"languages": null,
"libraryUrl": "https://www.facebook.com/ads/library/?id=1339489931715040",
"searchedFor": "running shoes",
"scrapedAt": "2026-10-11T04:51:30.946Z"
}

This row was chosen on purpose because it shows a common surprise: the text fields hold {{product.name}} style placeholders. That is what the Library publishes for catalog (dynamic product) ads, where Meta fills in the product at delivery time. In this 30-ad test run, 16 ads were of that kind. See the FAQ.

Sample output table (real run data)

Rows from a real past run (Apify run Sjrrb9eKmzRPrLcqt, Oct 22, 2026; query "running shoes", United States; 4 of the 25 ads it returned). Advertiser Pages only, no personal data.

AdvertiserAd startFormatCall to actionVariationsPlatformsQuery
Cholesterol Relief Community2026-06-01IMAGELearn more1Facebook, Instagram, Audience_Network +2running shoes
Amazon.com2026-10-08DPAShop now1Facebook, Instagramrunning shoes
Saucony2026-02-22DPAShop now1Facebook, Instagram, Audience_Network +2running shoes
KURU Footwear2026-07-06DCOShop now1Facebook, Instagram, Audience_Networkrunning shoes

Quick start

  1. Open the actor and keep the prefilled search term, or type your own.
  2. Set maxItems (default 100).
  3. Run. Rows appear in the dataset as they are found; export as JSON, CSV or Excel.
{ "searchTerms": ["running shoes"], "country": "US", "activeStatus": "active", "maxItems": 100 }

Example inputs from real runs

Each input below was used in a real run of this Actor in October 2026. Paste one into the Input tab (JSON view) to start from it.

1. Active US ads for running shoes (that run returned 100 rows)

{
"searchTerms": [
"running shoes"
],
"country": "US",
"activeStatus": "active",
"adType": "all",
"adCategory": "all",
"mediaType": "all",
"sortBy": "default",
"fetchDetails": false,
"maxItems": 100,
"onlyNewSinceLastRun": false
}

2. Active US ads for solar panels (that run returned 10 rows)

{
"searchTerms": [
"solar panels"
],
"country": "US",
"maxItems": 10,
"activeStatus": "active",
"adType": "all",
"adCategory": "all",
"mediaType": "all",
"sortBy": "default",
"fetchDetails": false,
"onlyNewSinceLastRun": false
}

3. Active US ads for protein powder (that run returned 10 rows)

{
"searchTerms": [
"protein powder"
],
"country": "US",
"maxItems": 10,
"activeStatus": "active",
"adType": "all",
"adCategory": "all",
"mediaType": "all",
"sortBy": "default",
"fetchDetails": false,
"onlyNewSinceLastRun": false
}

4. Video ads from one Facebook page, date range (that run returned 3 rows)

{
"pageIds": [
"15087023444"
],
"activeStatus": "all",
"mediaType": "video",
"minDate": "2026-08-01",
"maxDate": "2026-10-10",
"fetchDetails": true,
"maxItems": 20,
"country": "US",
"adType": "all",
"adCategory": "all",
"sortBy": "default",
"onlyNewSinceLastRun": false
}

5. Active US ads for coffee (that run returned 10 rows)

{
"searchTerms": [
"coffee"
],
"country": "US",
"maxItems": 10,
"activeStatus": "active",
"adType": "all",
"mediaType": "all",
"onlyNewSinceLastRun": false
}

Input options

No field is required by the form, but a run needs at least one target: a search term, a Page id or a Library URL (startUrls). A completely empty input runs the prefilled demo search (running shoes); input that has only unusable targets stops with the message Nothing to search. You can mix all three kinds in one run; each is searched in turn and maxItems is the total across all of them.

InputDefaultWhat it does
searchTermsnoneKeywords or advertiser names, one per line, for example running shoes
pageIdsnoneNumeric Facebook Page ids (the view_all_page_id value in an Ad Library URL). Returns the ads that Page runs
startUrlsnonePaste any facebook.com/ads/library/?... URL. Its own filters are used as they are (see "Filters & URL input")
libraryUrlsnoneSame as startUrls, kept for older runs
countryUSTwo-letter country code, or ALL
activeStatusactiveactive (running now), inactive (ended) or all
adCategoryallSame as adType, named as other scrapers do: all, political_and_issue_ads, housing, employment, credit. Overrides adType when not all
adTypeallall, political, housing, employment or credit. Political and issue ads add Meta's published spend and impression ranges
mediaTypeallall, image, video, meme or none
dateFrom, dateTo (or minDate, maxDate)noneYYYY-MM-DD. Only ads whose start date is on or after / on or before the date, checked on every row
platformsallAny of facebook, instagram, audience_network, messenger, threads
languagesnoneLanguage codes such as en, es. The Library filters by them
sortBydefaultdefault, relevance (the Library's relevancy ranking) or impressions (ranks by total impressions; the Library only publishes impressions for political and issue ads)
fetchDetailsfalseAdds the details object to each row. No extra requests, no extra charge
maxItems100Total ads to deliver, 1 to 50,000
onlyNewSinceLastRunfalseSkip ads delivered by an earlier run that used the same state store
stateStoreNamemeta-ad-library-seenNamed key-value store that remembers delivered ad ids
proxyConfigurationApify residential proxy, USSee "Proxy" below

The country, status, type, media, date, platform and language filters apply to searchTerms and pageIds. A pasted Library URL carries its own filters.

Filters & URL input

  • Paste a URL. Put any Ad Library search URL in startUrls and run it. Read from the URL: active_status, ad_type, country, q, search_type, view_all_page_id, media_type, start_date[min], start_date[max], sort_data, publisher_platforms and content_languages. Links that are not Ad Library search URLs are skipped and listed in the run summary.
  • Advertiser Pages. pageIds takes the numeric Page id or an Ad Library URL with view_all_page_id. Facebook links that only contain a vanity name (facebook.com/nike) are skipped, because the id cannot be read from them without a login.
  • Dates. The Library's own date filter matches ads delivered inside the range, so it also returns ads that started earlier. This actor drops those and keeps only ads whose start_date is inside minDate to maxDate.
  • Sorting. relevance reorders results. impressions is accepted by the Library but only changes the order for political and issue ads, the only ads with published impressions. A sort by newest is not offered because the Library has no such sort.
  • Platforms and languages. Both are applied by the Library itself, and the counts it reports change accordingly.

Input examples

Every ad one advertiser runs, active and ended:

{ "pageIds": ["15087023444"], "activeStatus": "all", "maxItems": 500 }

Video ads on Instagram for two keywords, started this year, in the United Kingdom:

{ "searchTerms": ["protein powder", "meal replacement"], "country": "GB", "mediaType": "video", "platforms": ["instagram"], "dateFrom": "2026-01-01", "maxItems": 1000 }

A search you built in the Ad Library website, pasted as it is:

{ "libraryUrls": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=running%20shoes"], "maxItems": 200 }

A daily watch list that returns only new ads:

{ "pageIds": ["15087023444"], "activeStatus": "active", "onlyNewSinceLastRun": true, "stateStoreName": "shoe-brands-watch", "maxItems": 500 }

Proxy

Meta rate-limits datacenter IPs on the paging call, so a datacenter run usually gets only the first page (about 30 ads). The default is therefore Apify residential proxy with a US exit, and the form is prefilled the same way. In a test with the proxy turned off, a run returned 26 ads in 132 seconds; with the residential default the same query returned 30 ads in 8 to 10 seconds. Keep the default unless you have a reason to change it.

Example

Input example

{
"searchTerms": [
"running shoes"
],
"startUrls": [],
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": [
"RESIDENTIAL"
],
"apifyProxyCountry": "US"
}
}

Sample output

Three real rows from a recent run of this Actor. Personal data is masked, some fields are left out and long values are shortened for readability.

[
{
"adArchiveId": "866569929827744",
"pageName": "Cholesterol Relief Community",
"isActive": true,
"startDate": "2026-06-01",
"daysRunning": 143,
"platforms": [
"FACEBOOK",
"INSTAGRAM",
"AUDIENCE_NETWORK",
"WHATSAPP",
"THREADS"
],
"title": "Natural Relief in Weeks",
"ctaType": "LEARN_MORE",
"displayFormat": "IMAGE",
"linkUrl": "https://shop.pipitea.com/ppch/sp"
},
{
"adArchiveId": "914467831604972",
"pageName": "Cholesterol Relief Community",
"isActive": true,
"startDate": "2026-05-26",
"daysRunning": 149,
"platforms": [
"FACEBOOK",
"INSTAGRAM",
"AUDIENCE_NETWORK",
"WHATSAPP",
"THREADS"
],
"title": "Natural Relief in Weeks",
"ctaType": "LEARN_MORE",
"displayFormat": "IMAGE",
"linkUrl": "https://shop.pipitea.com/ppch/sp"
},
{
"adArchiveId": "1675334610789516",
"pageName": "Amazon.com",
"isActive": true,
"startDate": "2026-10-08",
"daysRunning": 14,
"platforms": [
"FACEBOOK",
"INSTAGRAM"
],
"title": "{{product.name}}",
"ctaType": "SHOP_NOW",
"displayFormat": "DPA",
"linkUrl": "https://www.amazon.com/?tag=igcmaplco-us-20&ascsubtag=pig-CMAPCONS-1-9-z7nnru..."
}
]

Pricing

Pay per event. There is no subscription and no rental fee for this actor.

EventPrice (all Apify plans)
Ad extracted (one per ad row delivered)$0.00065
Actor start (one per GB of run memory, minimum one)$0.00005

The default run memory is 4 GB, so the start costs $0.0002 per run unless you lower the memory in the run options.

Worked examples at the default memory:

Ads deliveredCost
100 (the form default)100 x $0.00065 + $0.0002 = $0.0652
1,000$0.6502
10,000$6.5002
50,000 (the maximum for one run)$32.5002

A daily watch run that finds 40 new ads a day delivers 1,200 ads in 30 days: 1,200 x $0.00065 + 30 x $0.0002 = $0.786.

Apify's free plan includes $5 of monthly platform credit, which covers about 7,600 ads with this actor.

What is not charged: duplicates inside a run (the same ad found by two search terms is delivered once) and ads skipped by only-new mode. To cap spend, set Maximum cost per run in the run options; the actor checks the remaining budget before each ad and stops cleanly when the limit is reached.

What it does and who it is for

Meta publishes every ad that runs on Facebook, Instagram, Messenger, Audience Network and Threads in a public, searchable library. The website is built for browsing one ad at a time. This actor turns a search of that library into a table: one row per ad, the same 34 columns every time, ready for a spreadsheet, a database or a script.

It is built for people who study advertising:

  • Marketers and agencies collecting competitor creative, headlines and calls to action before a campaign.
  • Ecommerce and app teams watching what rivals launch and how long they keep an ad running.
  • Ad-intelligence and reporting tools that need a feed of new ads per advertiser.
  • Journalists and researchers checking who advertises on a topic, including the spend and impression ranges Meta publishes for political and issue ads.

There is no browser inside the actor. It makes plain HTTP requests with a Chrome-like TLS fingerprint, which is why a 30-ad run finishes in seconds.

When to use this vs Apify's Facebook Ads Library Scraper

Use this actor for flat, typed columns (media URLs, call to action and ISO dates in their own fields) from a keyword, Page id or pasted Ad Library URL. Use Apify's own Facebook Ads Library Scraper if you need its e-commerce enrichment (products and prices behind each ad) or its many pre-filters; its store page lists both and it has far more users (46,000+). Checked against its public store page on Oct 24, 2026.

Use cases and n8n automation ideas

Run this actor from an n8n workflow with the Apify node or an HTTP Request node, then read the dataset items in the next step. Ideas:

  • Competitor ad research. Pull the public Facebook and Instagram ads of a brand with copy, headline, link and creative URLs.
  • Creative swipe files. Save active ads by keyword into a sheet to study formats, calls to action and run dates.
  • Ad monitoring. Schedule a search from n8n and flag advertisers that launch new ads.

How to run it

In Apify Console

Open the actor, fill in the form and press Start. Rows appear in the Output tab while the run is going. The status line shows the current target and how many ads it has delivered, with the Library's approximate total when Meta reports one. When the run ends, use Export for JSON, CSV, Excel, XML or HTML.

From the API or a client library

Set APIFY_TOKEN to your token from Apify Console > Settings > API & Integrations.

curl -X POST "https://api.apify.com/v2/acts/transparent_meteorite~meta-ad-library/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"searchTerms":["running shoes"],"country":"US","activeStatus":"active","maxItems":100}'

Python (pip install apify-client)

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {"searchTerms": ["running shoes"], "country": "US", "activeStatus": "active", "maxItems": 100}
run = client.actor("transparent_meteorite/meta-ad-library").call(run_input=run_input)
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
print(ad["adArchiveId"], ad["pageName"], ad["ctaText"], ad["linkUrl"])

JavaScript / Node.js (npm install apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('transparent_meteorite/meta-ad-library').call({
searchTerms: ['running shoes'], country: 'US', activeStatus: 'active', maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'ads');

On a schedule

Create a schedule in Apify Console (Schedules > Create new), add this actor with your saved input, and pick a cron expression such as 0 6 * * * for 06:00 every day. Turn on onlyNewSinceLastRun so each run returns, and charges for, only ads you have not received yet.

With n8n, Make, Zapier or AI agents

Start the actor with the Apify API (POST /v2/acts/<actor>/runs) or the Apify node in n8n, Make or Zapier, wait for the run, then read GET /v2/datasets/<id>/items. Any MCP-capable agent can call it as a tool through the Apify MCP server. Every row has a stable adArchiveId for upserts. Webhooks work as for any Apify actor: add one for the "run succeeded" event and your endpoint receives the run id and dataset id when the data is ready.

Watch mode (new ads only)

Turn on onlyNewSinceLastRun and keep the same stateStoreName between runs. The actor stores the id of every ad it delivers in that named key-value store. On later runs, ads already in the store are skipped and not charged, so each run returns only new ads.

  • Use one store name per watch list, for example shoe-brands-watch. Two lists sharing a store would hide each other's overlaps.
  • An ad is recorded only after its row is pushed and charged. The store is saved every 50 ads and again at the end, and also when a run is aborted.
  • Watch mode reports new ads. It does not report ads that ended; for that, run with activeStatus: "all" and compare isActive and endDate between exports.

Run summary record

Each run writes a record named OUTPUT to its key-value store:

KeyMeaning
targetsHow many search terms, Pages and URLs were processed
adsDelivered, chargeCallsRows written and events charged (these match)
adsDuplicate, adsSkippedAlreadySeenAds not delivered, and why
chargeLimitReachedTrue when your maximum cost stopped the run
perTargetFor each target: the Library's reported total, ads delivered and pages read
warningsPlain-language notes, for example a target that failed

Limits and honest caveats

  • Only what the Library publishes. No audience targeting, no exact spend for commercial ads, no clicks, conversions or other performance data. Meta does not make those public.
  • Spend, impressions and reach are ranges, and only for some ads. Meta publishes them for political and issue ads and in some regions. For ordinary commercial ads those fields are null.
  • Catalog ads show placeholders. Dynamic product ads are published with {{product.name}} style text. The actor passes that through and does not guess the product.
  • Media links expire. Image and video URLs are Meta CDN links with a limited life.
  • Rate limits and captchas. The actor pauses 0.6 to 1.2 seconds between pages, retries the first page up to 3 times and later pages up to 5 times with exponential backoff, and waits longer when Meta signals a rate limit. If Meta asks for a captcha on the run's IP, the actor does not attempt to solve it: it stops that target, records a warning and moves on to the next one.
  • Very large result sets. One target is read for at most 2,000 pages, and one run delivers at most 50,000 ads. Split bigger jobs by date range, country or Page.
  • Meta can change the Library at any time, which can break or limit results until the actor is updated.

More tools from the same publisher that fit this workflow:

Use from AI agents: every actor here is callable through the Apify MCP server (mcp.apify.com) and our open-data-actors MCP endpoint.

Troubleshooting

SymptomLikely cause and fix
Run fails with Nothing to searchThe input had no search terms, Page ids or Library URLs. Add one
Run fails with No ads could be fetchedEvery target failed, usually because the IP was rate-limited. Keep the residential proxy default and try again
Only about 30 ads per targetThe proxy was switched to datacenter or turned off. Restore the residential default
Warning mentions a captchaMeta challenged that IP. Run again; a new run gets a different residential IP
Zero ads for a real advertiserCheck country (try ALL) and activeStatus (try all)
Watch-mode run returns everything againThe stateStoreName changed or the store was deleted. Keep the name identical between runs
A pageIds entry is ignoredPage ids must be numeric. A Page name or username is not an id

Terms and responsible use

  • Source: the public Meta Ad Library, which Meta publishes for transparency. The actor uses no login and no cookies, and never touches private profiles.
  • Personal data: the only person-or-business identifier in the output is the advertiser Page name and id that the Library itself shows. Use of the data must comply with the GDPR/CCPA, Meta's Terms and the law in your country.
  • This actor is independent and not affiliated with or endorsed by Meta. Meta can change the Library at any time, which can break or limit results. Do not use the data to harass, to profile private individuals, or to run anything deceptive.
  • Be reasonable with volume: the actor already paces its requests and backs off when Meta rate-limits.

More resources

Works well with

Other actors from Detroit Web Agent - Open Data that pair with this one:

Use it from AI assistants (MCP)

Meta Ad Library Scraper works as a tool for AI assistants through the official Apify MCP server. Add this server URL to any MCP client (Claude Desktop, Claude Code, Cursor, ChatGPT connectors, VS Code):

https://mcp.apify.com/?actors=transparent_meteorite/meta-ad-library
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?actors=transparent_meteorite/meta-ad-library",
"headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }
}
}
}

FAQ

Do I need a Facebook account or cookies? No. The actor does not log in and you supply no cookies.

Why is residential proxy the default? Meta rate-limits datacenter IPs after the first page of results. With residential IPs the actor pages through large result sets.

Why did I get fewer ads than the Library's result count? The count in the Library header includes variations and can shrink as ads end. Also check maxItems, active status and country filters, and look at OUTPUT.perTarget to see how many pages were read for each target.

Why do some ads have {{product.name}} as the title? They are catalog ads. Meta publishes the template, not the product each viewer saw. linkUrl, caption, the media URLs and the advertiser fields are still real.

Does it give exact spend? Only where Meta publishes it, as the ranges Meta shows (political and issue ads). Commercial ads have no public spend, so those fields are null.

Can it get ads from a Page URL? Use the Page's numeric id in pageIds, or paste a Library URL that already filters to that Page. To find the id, open the advertiser in the Ad Library and copy the view_all_page_id value from the address bar.

What does variationsCount mean? The Library groups near-identical versions of an ad under one entry. The count tells you how many versions are in that group. Advertisers testing many versions of one creative show a high number.

One of my targets failed. Did I lose the run? No. A failed target is recorded in OUTPUT.warnings and the run continues with the next target. The run is marked failed only when no ads at all could be fetched.

How fast is it? A 30-ad test run on 2026-10-11 finished in about 8 seconds. Larger runs add roughly a second of deliberate pause per page.

This Actor vs whoareyouanas/meta-ad-scraper: that one is the most-used. This one returns flat rows with ISO dates and has an only-new mode for scheduled monitoring.

Support

Missing an ad that the Library shows, a field that parsed wrongly, or need a field added? Open an issue on this actor's Issues tab with the run URL and what you expected. The run URL lets us see the exact input and the OUTPUT record.


Built and maintained by Detroit Web Agent - Open Data (Detroit, Michigan). Questions, bugs or a field you need: open an issue on this Actor's Issues tab and we will reply there.

More from DWA Open Data

Browse all 69 data Actors, with live prices and sample output, at open-data-actors.pages.dev.


Feedback: if this Actor was useful, or if it fell short, an honest review on the Reviews tab helps other users decide. Problems or feature requests: please open an Issue and we usually reply within one business day.

Changelog

  • 2026-10-09: First version (private).
  • 2026-10-11: Form prefill now matches the residential proxy default; added pageProfileUrl, pageProfilePictureUrl and daysRunning (build 0.1.6).
  • 2026-10-12: README expanded: full field table, sample output, pricing examples, API and scheduling guides, limits, FAQ and troubleshooting.
  • 2026-10-13: Added a Run in 30 seconds section with a one-click prefilled run link, saved use-case presets, cross-links to pairing actors and Store title and search description reworded around how buyers search.
  • 2026-10-13: Added startUrls (paste any Ad Library URL), minDate/maxDate, adCategory, sortBy and fetchDetails; every row now also has flat snake_case fields (body_text, cta_text, link_url, video_hd_url, ad_library_url and more); dates are checked on each ad's start date.
  • 2026-10-25: Listing refresh: new Store icon, README reorganised (overview, data fields, pricing, FAQ) and changelog tab added. No code change.

Volume tier pricing

Price per 1,000 events by Apify plan (paid plans get the lower rate automatically):

EventFreeBronzeSilverGold+
ad-extracted$0.57$0.4$0.25$0.14