Facebook Ads Library Scraper | Meta Ads Library, from $0.25/1K avatar

Facebook Ads Library Scraper | Meta Ads Library, from $0.25/1K

Pricing

from $0.25 / 1,000 ads

Go to Apify Store
Facebook Ads Library Scraper | Meta Ads Library, from $0.25/1K

Facebook Ads Library Scraper | Meta Ads Library, from $0.25/1K

Scrape the Meta Ad Library by brand name, page URL, keyword or Ad Library URL: every Facebook and Instagram ad with text, images, videos, carousel cards, link, call to action, dates and platforms. Plain HTTP, no login, no Meta token. New ads only mode and webhook.

Pricing

from $0.25 / 1,000 ads

Rating

0.0

(0)

Developer

Alexis Morain

Alexis Morain

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

2

Monthly active users

4 days ago

Last modified

Features

Limited permissions

Share

Facebook Ads Library Scraper

This Actor turns the Meta Ad Library into structured data. Give it a brand name, a Facebook page URL, a keyword, or a URL you copied from the Ad Library website, and it returns every Facebook, Instagram, Messenger and Threads ad it finds: ad text, headline, images, videos, carousel cards, landing page, call to action, start and end dates, platforms, and the version group each ad belongs to.

It runs over plain HTTP. No browser, no Facebook login, no cookies, no Meta developer token. That is why it fits in 512 MB and why a brand with a thousand ads takes about six minutes. Pricing is pay per event: $0.50 per 1,000 ads at the entry price, down to $0.25 per 1,000 ads on the Gold plan, plus $0.001 per run. A first run capped at 100 ads costs about five cents on the Free plan.

If you were looking for a Facebook Ads Library API, this is the closest thing that works for commercial ads. Meta's official Ad Library API only returns ads about social issues, elections or politics, plus ads delivered in the European Union and the United Kingdom, and it requires a Meta developer account with an identity check. This Actor reads the public Ad Library website the way a visitor does, in every country, and hands you JSON.

What makes it different: it is cheap, it needs nothing from you, and it is built to be scheduled. Entry price $0.50 per 1,000 ads, $0.25 on Gold. Plain HTTP with no login and no Meta token. A New ads only mode with a persistent registry, and a webhook that fires only when something new was found. Every version of an ad comes out as its own row, with its own ID, dates and text.


What this Facebook Ads Library scraper does

It searches in three ways, and they can be combined in one run.

Search by advertiser. You list brands as a name (Decathlon), a Facebook page URL (https://www.facebook.com/nike/) or a page ID (122695097770591). A name is resolved to a Facebook page the way the Ad Library search box does it for the country you picked, and only that page's ads come out, not every ad that mentions the brand. The log prints the page chosen and the other matches with their IDs, so you can pin the right one on the next run.

Search by keyword. Search terms work like the Ad Library search box: every ad whose text matches, from any advertiser. Use it to follow a market or a product (running shoes), not one brand. Tick Exact phrase to match the words in order instead of in any order.

Replay an Ad Library URL. If you built a search on facebook.com/ads/library with filters this input does not expose, paste the URL. The filters in the URL (country, status, media type, platforms, languages, dates) are kept for that URL. A single ad URL (?id=...) returns that one ad. An advertiser URL (?view_all_page_id=...) returns that page's ads.

On top of any search you get all the Ad Library filters (country, active or inactive, ad category, media type, platform, language, date range), a New ads only mode with a persistent registry for scheduled monitoring, and an optional webhook at the end of the run.

Cheap, no login, made for monitoring

Price. $0.0005 per ad on the Free plan, $0.00025 on Gold, plus $0.001 per run. That is $0.50 per 1,000 ads at the entry price. We measured about $0.056 of platform resources for a 1,000-ad run, so the entry price covers its cost. Details in the pricing section.

No login. The Actor reads the public Ad Library over HTTP. No Facebook account, no cookies, no Meta developer token, no browser. Nothing of yours can be restricted.

Any way you search. A brand name, a Facebook page URL or page ID, a keyword, or a URL copied from the Ad Library website with its filters.

Watch mode. Set Mode to New ads only, schedule the Actor, and each run returns and charges only ads it has never returned. Add a webhook and you hear about a new ad the day it appears.

Every version is a row. The Ad Library groups near-identical ads under "This ad has multiple versions". Each version comes out as its own row, with collationId and collationCount telling you which group it belongs to.

About version groups

Until late October 2026 the Ad Library list showed one ad per group and hid the others behind that link. On 18 October 2026 we measured 345 hidden ads in the first 1,000 of Decathlon France, and the Actor opened every group to fetch them. Since then Meta serves the versions inside the list itself. On 1 November 2026 we compared runs with and without unfolding on Gymshark (5,179 ads) and Nike (2,349 ads): the counts were identical.

So today the list already contains every version, and Every version of each ad (includeAllVersions, on by default) rarely adds anything. When it is on, the Actor still sends one extra request for each group it sees, in case Meta hides some again, and fromVersionGroup is true only for a row that came from that extra request. Expect false almost everywhere. Turning the option off saves those requests and the time they take. Each row is priced as an ad either way, and an ad is never returned twice in a run.

Why scrape the Meta Ad Library?

  • Scrape competitor ads. What a brand runs right now, since when, on which platforms, with which offers and landing pages.
  • Facebook ad spy and creative research. Build a swipe file of ad texts, images and videos for a market, sorted by how many days each ad has been running. An ad that has run for 90 days is usually one that works.
  • Instagram ads research. The same ads, filtered to Instagram with the Platforms option, or read from publisherPlatforms in the results.
  • Agency pitches and reporting. Export a prospect's ads in a few clicks before a meeting.
  • Lead generation. The advertiser pages that run ads are companies with a budget: pageName, pageUrl, pageLikeCount, pageCategories and the landing page domain give you a qualified list.
  • Alerts. Schedule the Actor daily in New ads only mode and get a webhook when a competitor launches something.
  • Political and issue ad research. Filter by the political and issue ad category to get spend and impressions ranges, which Meta publishes for those ads only.

How to scrape Facebook ads

From the Apify console

  1. Open the Actor and type a brand in Advertisers, for example Decathlon, or paste its Facebook page URL.
  2. Pick a country if you want the ads shown there only. Leave it empty for all countries.
  3. Choose active ads, inactive ads or both.
  4. Set Max ads per search, or 0 for everything.
  5. Press Start, then download the results as JSON, CSV, Excel or HTML, or read them through the API.

To follow a market instead of a brand, use Search terms. To reproduce a search you built on the Ad Library website, paste its URL in Ad Library URLs.

From the API

curl -X POST "https://api.apify.com/v2/acts/alexmorain~facebook-ads-library-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"advertisers": ["Decathlon"], "countries": ["FR"], "maxAdsPerSearch": 100}'

The full Python, JavaScript and cURL examples are further down, in "Using the Facebook Ads Library API from your code".

Which fields should I fill?

You wantFillNotes
All the ads of one brandadvertisersName, page URL or page ID. Raise pagesPerAdvertiser for brands with several pages.
All the ads of a market or a productsearchTermsAdd exactPhrase for a fixed phrase.
The ads of a page you already found on the websiteadLibraryUrlsFilters in the URL are kept.
One known adadLibraryUrls with the ?id= URLReturns that ad.
Ads in one or several countriescountriesCodes like US, GB, FR, or English names.
Only running ads, or only stopped onesactiveStatusactive (default), inactive, all.
Only videos, only imagesmediaTypeall, image, video, meme, image_and_meme, none.
Only Instagram adsplatformsfacebook, instagram, messenger, audience_network, threads, whatsapp.
Ads in a languagelanguagesTwo-letter codes like en, fr, de.
Ads shown in a periodshownFrom, shownUntilMeta's rule: see the date filter note below.
Political and issue ads with spend rangesadType = political_and_issue_adsSpend and impressions only exist for these.
A daily competitor alertmode = new-only and webhookUrlSee the monitoring section.

Input examples

A brand, in France, running ads only:

{
"advertisers": ["Decathlon", "https://www.facebook.com/nike/"],
"countries": ["FR"],
"activeStatus": "active",
"maxAdsPerSearch": 500
}

A market, Instagram only, videos only, English ads in the United States:

{
"searchTerms": ["running shoes"],
"countries": ["US"],
"platforms": ["instagram"],
"mediaType": "video",
"languages": ["en"],
"maxAdsPerSearch": 300
}

A search copied from the Ad Library website, with every version of each ad:

{
"adLibraryUrls": [
"https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=FR&view_all_page_id=122695097770591"
],
"includeAllVersions": true,
"maxAdsPerSearch": 0
}

A daily competitor watch:

{
"advertisers": ["Decathlon", "Intersport", "Go Sport"],
"countries": ["FR"],
"mode": "new-only",
"maxAdsPerSearch": 0,
"webhookUrl": "https://hooks.slack.com/services/..."
}

Details that need a word

  • Advertisers accepts a name, a page URL (https://www.facebook.com/brand/) or a page ID. For a name, the log prints the page chosen and the other matches. Big brands run ads from several pages (one per country, one per product line): raise Pages per advertiser name (1 to 20), or paste the page IDs you want.
  • A name is not always the right advertiser. A search for decathlon can return an unverified page with 1,775 likes behind the verified Decathlon France page. The Actor keeps Meta's order and only moves an exact verified name, or an alias taken from a pasted URL, to the front. A pasted page address that matches no page exactly ends as "not found" rather than falling back to the closest suggestion, because that would bill you for another advertiser's ads.
  • Brand name as a keyword is noisy. Searching decathlon as a keyword in France returns resellers and fan pages: 20% of the results in our measurement. Searching by page does not.
  • Shown from and Shown until follow Meta's rule: an ad is kept if it was shown at some point in the window, even if it started before. To filter by launch date, filter on startDate in the results.
  • Countries. Several countries are searched together and each ad comes out once.
  • Max ads per search applies to each advertiser page, each search term and each URL, every version counted as an ad. 0 means no cap. The default is 200.
  • Up to 500 targets per run (advertisers, search terms and URLs together).

What data can it extract? Every output field

One item per ad. Fields Meta does not publish for an ad are null.

Advertiser

FieldTypeDescription
pageIdstringFacebook page ID of the advertiser
pageNamestringAdvertiser page name
pageUrlstringAdvertiser Facebook page
pageLikeCountintegerLikes of the advertiser page
pageCategoriesarrayCategories of the advertiser page, for example Sporting Goods
pageProfilePictureUrlstringAdvertiser profile picture (Meta CDN, signed URL that expires)

Ad identity and timing

FieldTypeDescription
adArchiveIdstringAd Library ID of the ad
adLibraryUrlstringPublic page of the ad in the Meta Ad Library
isActivebooleanRunning now or stopped
startDatestringDay the ad started running, UTC
endDatestringLast day the ad ran; for an active ad, the latest day Meta reports
daysRunningintegerDays between start and end, both counted
publisherPlatformsarrayFACEBOOK, INSTAGRAM, MESSENGER, THREADS, AUDIENCE_NETWORK
categoriesarrayMeta ad categories (POLITICAL, ISSUE...), empty for ordinary ads
containsAiMediabooleanMeta flags the ad as containing digitally created or altered media

Creative

FieldTypeDescription
displayFormatstringIMAGE, VIDEO, CAROUSEL, DCO (dynamic creative), DPA (catalog), EVENT...
bodystringAd text. For catalog and dynamic ads whose text is a template ({{product.name}}), the text of the first card
titlestringHeadline
linkDescriptionstringLink description under the headline
captionstringDisplayed link domain
linkUrlstringLanding page URL
ctaTextstringCall to action button text
ctaTypestringCall to action type, for example SHOP_NOW
imageUrlsarrayImage URLs of the ad and its cards (Meta CDN, signed URLs that expire)
videosarrayVideos: hdUrl, sdUrl, previewImageUrl
cardsarrayCarousel or dynamic creative cards: title, body, linkUrl, linkDescription, ctaText, imageUrl, videoUrl

Version groups

FieldTypeDescription
collationIdstringID of the version group the ad belongs to
collationCountintegerNumber of ads in its version group, as Meta reports it
fromVersionGroupbooleantrue only when the ad was not in the Ad Library list and came from opening its version group. Since Meta serves versions in the list (checked 1 November 2026), this is rarely true

Political and issue ads only

FieldTypeDescription
spendobjectSpend range (min, max)
impressionsobjectImpressions range (min, max)
currencystringCurrency of the spend range
reachEstimateobjectReach estimate when Meta publishes it

Provenance

FieldTypeDescription
inputstringThe advertiser, search term or URL from your input that found this ad
inputTypestringadvertiser, searchTerm or url
countriesarrayCountry filter of the search that found the ad
scrapedAtstringWhen the ad was read, UTC

Example output

Two items, shortened. They are two versions of the same group (same collationId):

[
{
"adArchiveId": "1600894127669355",
"adLibraryUrl": "https://www.facebook.com/ads/library/?id=1600894127669355",
"pageName": "Example Sports",
"pageId": "122695097770591",
"pageLikeCount": 1075878,
"isActive": true,
"startDate": "2026-09-14",
"endDate": "2026-10-16",
"daysRunning": 33,
"publisherPlatforms": ["FACEBOOK", "INSTAGRAM"],
"displayFormat": "CAROUSEL",
"body": "Ready for the next run? New trail shoes are in.",
"linkUrl": "https://www.example.com/trail-shoes",
"ctaText": "Shop now",
"ctaType": "SHOP_NOW",
"collationId": "1403288121396887",
"collationCount": 3,
"fromVersionGroup": false,
"input": "Example Sports",
"inputType": "advertiser"
},
{
"adArchiveId": "2379460792481796",
"adLibraryUrl": "https://www.facebook.com/ads/library/?id=2379460792481796",
"pageName": "Example Sports",
"isActive": true,
"startDate": "2026-09-20",
"displayFormat": "DCO",
"body": "Grip on every terrain",
"collationId": "1403288121396887",
"collationCount": 3,
"fromVersionGroup": false,
"input": "Example Sports",
"inputType": "advertiser"
}
]

You can download the dataset in JSON, CSV, Excel, XML or HTML. The Output tab has two ready views: Ads (link, advertiser, status, dates, format, text, headline, link, call to action, platforms, version-group flag) and Creatives (images, videos and cards).

Monitor competitor ads: New ads only mode

Set Mode to New ads only and schedule the Actor daily. It keeps a registry of every ad it returned and charged before, in a named key-value store in your account (facebook-ads-library-registry), and returns only ads it has never returned. Skipped ads are not charged.

Two things to know:

  • Every run reads the whole search again, because the Ad Library does not sort by launch date: a new ad can sit on page 30. You pay only for the new ads, so a quiet day costs the start fee.
  • A new version added to an existing group counts as a new ad, because every version is a row of its own with its own ID.

By default the registry is tied to the exact targets, countries and filters, so changing any of them starts a fresh one. Set your own Registry key to keep one registry while you edit the list.

Webhook at the end of the run

Add a webhookUrl and the Actor POSTs a small JSON summary when the run ends, only if at least one ad was returned:

{
"actor": "facebook-ads-library-scraper",
"runId": "<run id>",
"mode": "new-only",
"items": 12,
"searches": 3
}

Slack and Discord incoming webhooks work as they are. The URL is stored encrypted and never written to the log. Use the final URL: a redirect is not followed, except 307 and 308, which get the same POST once. An unreachable webhook is logged as a warning and never fails the run.

Using the Facebook Ads Library API from your code

Every run is an API call. Your token is in the Apify console under Settings, Integrations.

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("alexmorain/facebook-ads-library-scraper").call(run_input={
"advertisers": ["Decathlon"],
"countries": ["FR"],
"activeStatus": "active",
"platforms": ["instagram"],
"maxAdsPerSearch": 200,
})
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
print(ad["pageName"], ad["displayFormat"], ad["startDate"], ad["adLibraryUrl"])

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('alexmorain/facebook-ads-library-scraper').call({
searchTerms: ['running shoes'],
countries: ['US'],
mediaType: 'video',
maxAdsPerSearch: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const ad of items) console.log(ad.pageName, ad.body, ad.linkUrl);

cURL

Run and wait for the items in one call:

curl -X POST "https://api.apify.com/v2/acts/alexmorain~facebook-ads-library-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"advertisers": ["Decathlon"], "countries": ["FR"], "maxAdsPerSearch": 100}'

For runs that take more than a few minutes, start the run and poll it instead, since the synchronous endpoint times out after 300 seconds:

curl -X POST "https://api.apify.com/v2/acts/alexmorain~facebook-ads-library-scraper/runs?token=<YOUR_TOKEN>&maxTotalChargeUsd=5" \
-H "Content-Type: application/json" \
-d '{"advertisers": ["Decathlon"], "maxAdsPerSearch": 0}'

Then read https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=csv when the run has finished. maxTotalChargeUsd is a hard ceiling: the Actor stops cleanly when it is reached and you are never charged beyond it.

What people use it for

Competitor ad analysis on Facebook and Instagram

List the brands you compete with, set the country you sell in, and run once with active and inactive ads. Sort by daysRunning: the long-running ads are the ones the advertiser kept paying for. Group by displayFormat to see whether they bet on video or carousels, by ctaText to see the offer, by linkUrl to see which landing pages get the traffic.

Finding a competitor's ad tests

The version groups are where an advertiser tests copy. A group with collationCount of 8 is eight variants of one creative idea. Reading body across the versions of a group shows which angles are being tried.

Creative research before a brief

Search a product category as a keyword, filter by media type and language, and export body, title, imageUrls and videos. Download the files you want to keep: the CDN links are signed and expire after a few days.

Detecting a competitor entering a market

Run the same brand with countries set to a market you do not expect it in. A first result in that country, with a recent startDate, is the signal. With New ads only and a webhook, you hear about it the day it happens.

Political and issue ads

Set the ad category to political and issue ads. Those ads come with spend and impressions ranges, a currency and, when Meta publishes it, a reach estimate. Inactive political ads stay in the library for seven years.

Lead lists from advertisers

Companies that run ads are companies that spend. Search a keyword in your target market and keep the distinct pageName, pageUrl, pageCategories and linkUrl domains.

Facebook Ads Library scraper pricing

You pay per ad returned, plus a small start fee. Platform usage (compute, proxies) is included in that price. There is no monthly fee. The price per ad goes down with your Apify subscription plan, which is why the Store shows "from $0.25 / 1,000 ads".

EventWhen it firesFreeBronzeSilverGold and above
AdPer ad pushed to the dataset, each version counted as an ad$0.0005$0.0004$0.0003$0.00025
Actor startOnce when the run starts, per GB of memory (the default is 512 MB, so one event)$0.001$0.001$0.001$0.001

Per 1,000 ads, that is $0.50 on the Free plan, $0.40 on Bronze, $0.30 on Silver and $0.25 from Gold.

Worked examples at Free plan prices:

  • The default run, 200 ads from one brand: 200 x $0.0005 + $0.001 = $0.10.
  • 1,000 ads of one brand: 1,000 x $0.0005 + $0.001 = $0.50.
  • A daily watch of three competitors in New ads only mode, with 15 new ads on a given day: 15 x $0.0005 + $0.001 = $0.0085 that day. A day with no new ad costs $0.001.

Every version of an ad is an ad and is charged as one. Ads skipped by New ads only mode are never charged. The run log opens with the maximum cost of the run at Free plan prices when you set a cap.

How this compares to other options

Prices as listed on the Apify Store on 21 October 2026. Check each page for its current terms.

OptionPriceWhat you need
This Actor$0.50 per 1,000 ads on Free, $0.25 on GoldAn Apify account
apify/facebook-ads-scraper$5.80 per 1,000 adsAn Apify account
Meta Ad Library API (official)FreeMeta developer account and identity confirmation; returns political and issue ads, plus ads delivered in the EU and UK

At the entry price, 1,000 ads cost $0.50 here against $5.80 on the Store's general-purpose Facebook ads scraper, about a twelfth. On Gold the gap is about twenty-three times. Other Ad Library scrapers on the Store price per result, per run or by monthly rental, so compare the cost of the volume you actually need. Measured on our side, a 1,000-ad run uses about $0.056 of platform resources, so the entry price is not a loss leader.

Why this Facebook Ads Library scraper

Every version as its own row

Versions of one ad come out as separate rows with their own ID and dates, and a "new ads only" check sees a version added to an existing group. See "About version groups" above.

Plain HTTP, no browser, no login

The Actor reads the same GraphQL endpoints the Ad Library website calls. There is no browser to start, which keeps memory at 512 MB and the platform cost to a few cents per thousand ads. No account of yours is involved, so nothing of yours can be restricted.

It deals with Meta's bot check

Meta answers a first request with a JavaScript challenge. The Actor replays the challenge request, reloads the page and carries on. Meta also refuses all the datacenter IPs we tried and part of the residential ones, always on the first request of a session. The Actor opens a fresh residential IP until one is accepted, then keeps it. In our runs between a third and a half of the sessions were refused at the first attempt, and a fresh IP went through. The price per ad does not change with the number of refusals.

Failure that tells you what to do

A run that returns nothing because every search failed ends as FAILED with the reason in the status message: refused by Meta, advertiser not found, invalid input. It does not end as an empty success. A partial run says what stopped it: the maximum charge, the timeout, or a version group Meta refused to unfold (the listed ad is still in your dataset).

One ad, one charge

An ad found by two searches in the same run comes out once. A duplicate pushed would be a duplicate billed.

Limits and what this scraper does not do

  • Speed. The Ad Library serves 10 ads per page. We measured about 2.6 ads per second per search. A brand with 1,000 ads takes about six minutes. Up to four searches run in parallel. A brand with 20,000 ads needs more than the default timeout of one hour: raise the run timeout or split the work by country or by date.
  • History. Inactive ads stay in the library for one year, political and issue ads for seven years. Nothing older exists to be scraped.
  • Spend and impressions exist for political and issue ads only. For an ordinary ad, spend and impressions are null: Meta does not publish them.
  • No targeting, age, gender or payer data. Meta publishes the audience details of an ad only for ads delivered in the European Union, and this version does not read them. The fields are not in the output rather than empty.
  • No search by ad ID. The Ad Library search does not find an ad by its number. Paste the ad URL (?id=) in Ad Library URLs instead.
  • Signed media links. Image and video URLs come from Meta's CDN and expire after a few days. Download what you want to keep.
  • The date filter is a delivery filter. An ad that started before the window and was still running inside it is returned. Filter on startDate yourself for a launch date.
  • Residential proxies. Leave the proxy configuration on Residential. With the plain Apify proxy the Actor starts on datacenter IPs and switches to residential by itself when Meta keeps refusing, which costs a few seconds. If you supply your own proxy URLs, the Actor keeps exactly what you chose.
  • Scope. The Actor reads the public Ad Library and nothing else. It does not touch personal profiles, comments, reactions, groups or anything behind a login.

FAQ

Is there a Facebook Ads Library API?

Meta publishes one, the Ad Library API, but it returns only ads about social issues, elections or politics, plus ads delivered in the European Union and the United Kingdom. It also needs a Meta developer account with an identity check. For commercial ads in the rest of the world there is no official API. This Actor reads the public Ad Library website and returns the ads as JSON, so it works as an alternative for commercial ads in every country.

Can I scrape the Meta Ad Library without a Facebook account?

Yes. It needs no login, no cookies and no Meta token. It reads the public Ad Library the way a visitor who is not logged in does.

How do I scrape Facebook ads of a competitor?

Type the brand name or paste its Facebook page URL in Advertisers, choose a country, press Start. For a brand that runs ads from several pages, raise Pages per advertiser name or paste each page URL.

How do I scrape Instagram ads?

Instagram ads are in the Meta Ad Library with the Facebook ones. Choose Instagram in Platforms to get only the ads shown on Instagram, or read publisherPlatforms in the results. An ad shown on both platforms lists both.

Can I see how long an ad has been running?

Yes: startDate, endDate and daysRunning. For an active ad, the end date is the latest day Meta reports.

How far back does the Ad Library go?

Inactive ads stay in the library for one year, political and issue ads for seven years.

Why did a name return the wrong page?

A name is matched the way the Ad Library search box does it for the country you chose. Check the log: it lists the other pages with their IDs. Paste the right page URL or ID in Advertisers.

What are version groups, and what is includeAllVersions?

The Ad Library groups near-identical ads and used to list only one per group. Meta now serves the versions in the list, so the Actor gets them without extra work. With Every version of each ad on (the default), it still opens each group it sees, to catch versions Meta might hide again. fromVersionGroup is true for rows that only that step found, which is rare today. Turn the option off to skip the extra requests. collationId and collationCount tell you which group an ad belongs to.

How much does it cost to scrape 1,000 Facebook ads?

$0.50 on the Free plan, $0.25 on Gold, plus $0.001 for the start. The first 100 ads cost about five cents.

How do I export Facebook ads to CSV or Excel?

From the run's Storage tab, or through the dataset API with format=csv or format=xlsx.

My run was refused. What do I change?

Keep the proxy on Residential and run again in a few minutes. If every search was refused even through residential IPs, the run ends as FAILED and says so; nothing is charged beyond the start.

Can I get spend and impressions for any ad?

No. Meta publishes spend and impressions ranges for political and issue ads only.

Can I run it every day and be told about new ads?

Yes. Use Mode New ads only on a daily schedule, with a Webhook URL. See the monitoring section.

Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by Apify users, are safe. However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

Integrations, exports and agents

Runs can be scheduled from the Apify console, hourly through monthly, which is all a standing competitive watch needs. Combine a schedule with New ads only and a webhook and you get a call only when new ads appear. For every run, whatever its result, attach an Apify webhook on the ACTOR.RUN.SUCCEEDED event: Apify POSTs the run and dataset IDs to your endpoint, so a pipeline can pull the ads into your own store without polling.

The dataset is readable over the Apify API in JSON, CSV, XML, Excel, RSS and HTML. Apify's integrations push it to Google Sheets, Slack, Airtable, Zapier, Make and the usual storage targets without code. The Actor is also callable from an agent: anything that speaks the Apify API can start a run and read the dataset, and the Apify MCP server exposes Actors as tools to MCP-capable clients.

Support

Something wrong or missing? Open an issue in the Issues tab and it gets fixed; a reproducible input gets a fix faster than a description. To call the Actor from your code, see the API tab, with endpoints and snippets prefilled.

More ad libraries from the same author: LinkedIn Ad Library Scraper and Google Ads Transparency Scraper.