Facebook Ad Library Scraper avatar

Facebook Ad Library Scraper

Pricing

from $2.00 / 1,000 ads

Go to Apify Store
Facebook Ad Library Scraper

Facebook Ad Library Scraper

Collect Facebook Ad Library creatives, media links and available advertiser details by keyword or Page across selected countries. Pay per delivered ad row plus a start fee.

Pricing

from $2.00 / 1,000 ads

Rating

0.0

(0)

Developer

kane liu

kane liu

Maintained by Community

Actor stats

1

Bookmarked

36

Total users

4

Monthly active users

20 hours ago

Last modified

Security

Limited permissions

Share

Collect public Facebook Ad Library ads by keyword or advertiser Page, with creative text, media links and available advertiser details in exportable rows.

  • Ad headlines, body text, calls to action and destination URLs.
  • Images, videos and carousel cards, with available platform and date information.
  • Keyword and Page searches filtered by country, status and media type.
  • Optional creative variants, asset downloads and incremental monitoring.
  • $2 per 1,000 delivered rows on the Free plan, plus a small start fee.

What does Facebook Ad Library Scraper do?

Facebook Ad Library Scraper collects ads from Meta's public Ad Library. Use it to compare advertiser creatives, organize campaign research or monitor newly seen ads. It returns one ad per row, not an advertiser directory or private account data.

  • Keyword search: fill searchQuery or searchQueries with brands, products or topics.
  • Advertiser search: fill pageIds or pageUrls to collect ads from particular Pages. Keywords and Pages can share a run.
  • Market filters: choose a two-letter country, such as US, GB or DE, or ALL for worldwide searches.
  • Details: enrichDetails is on by default. Available disclosure and public advertiser contact information is added to existing ad rows, not billed as separate contact rows.
  • Creative variants: expandCollations is off by default. Each expanded variant is another ad row and is billed at the same price.

What data can you extract from Facebook Ad Library?

All rows use rowType: "ad". Optional fields depend on what Meta discloses and whether enrichment succeeds.

FieldDescriptionExample
rowTypeEntity represented by this row.ad
idStable row identifier, equal to the ad archive ID.123456789012345
adArchiveIdMeta's ad archive identifier.123456789012345
pageIdAdvertiser Page identifier.1234567890
pageNameAdvertiser name.Example Shop
pageProfileUrlAdvertiser's Facebook Page link.https://www.facebook.com/example-shop/
titleCreative headline.Explore our collection
bodyTextAd copy.Browse this season's products.
ctaTextCall-to-action label.Shop Now
linkUrlAd destination URL.https://example.com/shop
displayFormatCreative format reported by Meta.IMAGE
imageUrlsAvailable image links.[]
videoUrlsAvailable video links.[]
cardsCarousel card content and links.[]
publisherPlatformsPlatforms named in the ad disclosure.["FACEBOOK", "INSTAGRAM"]
startDateAd start time, when available.2026-10-01T00:00:00Z
endDateEnd time; omitted for an active ad.2026-10-12T00:00:00Z
isActiveActive status, or null if not disclosed.true
spendDisclosed spending range, not an estimate made by this Actor.{"lowerBound":"100","upperBound":"199","currency":"USD"}
impressionsDisclosed impression range.{"lowerBound":"1000","upperBound":"4999"}
euTotalReachEU reach where disclosed.1200
euTransparencyAvailable EU audience disclosures.{"euTotalReach":1200,"targetsEu":true}
phonesPublic advertiser phone entries, if available.[]
emailsPublic advertiser email entries.[{"value":"name@example.com","type":"business"}]
addressAvailable advertiser address components.{"full":null}
orgAdvertiser organization identity.{"name":"Example Shop","id":"1234567890"}
webAdvertiser website and social links.{"website":"https://example.com","socials":[]}
leadAbsencesReasons contact fields are missing or unavailable.{}
assetKeysKeys for successfully downloaded media files.["asset-123456789012345-image.jpg"]
scrapedAtCollection timestamp.2026-10-24T08:00:00Z

searchQuery, searchType and searchedPageId identify the search that found a row. leadSource and leadReveal describe the available contact evidence. The current contact extraction leaves geo and person as null; it does not infer coordinates or named people.

How to scrape Facebook Ad Library

  1. Open Facebook Ad Library Scraper in Apify Console.
  2. Enter a keyword or advertiser Page, then choose the country.
  3. Set maxResults to a small number, such as 3.
  4. Click Start and inspect the run status and dataset.
  5. Download the rows or read them through the API.

With every target field empty, the Actor uses the form's sample keyword shopify and returns at most 3 rows. This example run uses normal pricing. Filling one target field selects the matching search automatically; there is no mode setting to choose.

Use searchQuery for one input or searchQueries for several. Duplicate keywords are merged. A brand keyword can also match ads from other advertisers that mention the brand.

Use numeric IDs in pageIds, or Facebook Page links and exact Page names in pageUrls. Clear the prefilled keyword for a Page-only run. Unresolved Page names are skipped with a page_unresolved warning rather than replaced with another advertiser.

What to fill in

FieldWhat to enterDefault
searchQueryOne keyword, brand or topic.Empty; form prefills shopify
searchQueriesAdditional keywords as an array.[]
pageIdsNumeric advertiser Page IDs as strings.[]
pageUrlsPage links or exact Page names.[]
countryTwo-letter country code, or ALL.US
adTypeall or political_and_issue_ads.all
activeStatusactive, inactive or all.active
mediaTypeall, image or video.all
sortByrelevancy, newest or impressions.relevancy
startDateFromEarliest ad start date, in UTC.Empty
startDateToLatest ad start date, in UTC.Empty
maxResultsRow limit for each keyword or Page, from 1 to 5000.70; form prefills 3
enrichDetailsAdd available disclosure and advertiser contact details.true
maxDetailsDetail-enrichment limit; 0 means all collected ads.25
expandCollationsExpand grouped creatives into separately billed rows.false
downloadAssetsSave each ad's first image and first video.false
incrementalExclude ads delivered by earlier matching incremental runs.false

Keyword example:

{
"searchQuery": "shopify",
"country": "US",
"maxResults": 3
}

Advertiser example:

{
"pageUrls": ["https://www.facebook.com/nike/"],
"country": "US",
"maxResults": 3
}

Dates accept YYYY-MM-DD or ISO date-times. A date-only upper bound includes that whole day; undated ads are excluded when a date filter is set. Dates do not advance automatically. newest uses monthly grouping rather than guaranteeing exact timestamp order.

  • maxItems and limit are aliases for maxResults; query and keyword are aliases for searchQuery.
  • Unknown fields do not fail the run. Close misspellings are corrected when possible; other unknown fields are ignored with a note. Invalid filter choices are ignored with a warning.
  • Invalid Page links or dates stop collection with INVALID_INPUT: <field> — <how to fix>, before any row is charged. The start fee is separate.
  • The Actor writes its input interpretation to INPUT_REPORT in the default key-value store before validation finishes, including filled, corrected and ignored fields.

Output example

Illustrative ad row; optional media and disclosure fields may be absent:

{
"rowType": "ad",
"id": "123456789012345",
"adArchiveId": "123456789012345",
"pageId": "1234567890",
"pageName": "Example Shop",
"pageProfileUrl": "https://www.facebook.com/example-shop/",
"title": "Explore our collection",
"bodyText": "Browse this season's products.",
"ctaText": "Shop Now",
"linkUrl": "https://example.com/shop",
"displayFormat": "IMAGE",
"isActive": true,
"imageUrls": [],
"videoUrls": [],
"scrapedAt": "2026-10-24T08:00:00Z"
}

Export the dataset as JSON, CSV, Excel, XML, RSS or an HTML table. JSON preserves nested contact objects and creative lists. RUN_SUMMARY records row counts and completion information; ERROR_SUMMARY explains failures.

Why use this Facebook Ad Library scraper?

  • Pay for delivered rows. Row charges apply to ads written to the dataset, not unsuccessful searches; a start fee also applies.
  • Keep delivered results. Rows already written remain available after a stop. A partial response can still deliver usable ads, but stopping before delivery is not guaranteed to preserve collected data.
  • Understand missing data. Unavailable fields stay empty or absent instead of being invented.
  • Combine inputs. Research several keywords and Pages in one run.
  • Reduce setup. You do not need to set up proxies or supply a Facebook login.

How much does it cost to scrape Facebook Ad Library?

The Actor uses pay-per-event pricing. Platform usage is included in these prices.

Apify planStart eventPrice per rowPrice per 1,000 rows
Free$0.005$0.002$2.00
Starter$0.005$0.002$2.00
Scale$0.005$0.002$2.00
Business$0.005$0.002$2.00

The start charge counts one event per GB of memory, with a minimum of one event. At the default 512 MB, starting a run costs $0.005.

  • maxResults applies to each input, with a default of 70. Larger requests are collected in parts of 70; expanded variants count toward the same limit.
  • country: "ALL" caps each input at 50 rows regardless of a larger requested limit.
  • Free Apify plan runs are capped at 200 rows, with 10 total runs of this Actor.
  • The whole run stops at Maximum cost per run, set through maxTotalChargeUsd in the API. Available matches and this cap may reduce the number delivered.

Example: at 512 MB, three keywords delivering 5 rows each produce 15 rows. On the Free plan, the cost is 15 × $0.002 + $0.005 = $0.035. A run that delivers no rows has no row charge, but its start event can still be charged.

What happens when the run timeout is too short

Some searches, such as several searchQueries or pageUrls with enrichDetails: true or a large maxResults, can take longer than the run timeout you chose. In that case the run does not fail. It ends early with the status message "Queued on the collection backend; this run will resume automatically when results are ready (about N s)." and shows as ABORTED for a while.

When the results are ready, the same run starts again by itself, reports "Resumed: delivering N rows.", writes the rows to the same dataset and finishes as SUCCEEDED. Rows that were already delivered are skipped, so no row is delivered or charged twice. You do not need to start another run.

  • This can happen at most 3 times per run. To avoid it, choose a longer run timeout for larger searches rather than a very short one. A manual abort or an unrelated failure is not the same as this automatic pause.
  • The synchronous API endpoints (run-sync, run-sync-get-dataset-items) wait at most 300 seconds and can return an empty dataset while the run is paused. For larger jobs, start the run asynchronously and read the dataset after the run reaches SUCCEEDED, or use a webhook on the "succeeded" event.

Use with AI agents and the API

Apify MCP server

Add this remote tool in a compatible client, such as Claude, ChatGPT, Cursor or VS Code:

https://mcp.apify.com?tools=lentic_clockss/facebook-ad-library-scraper

Sign in with Apify through OAuth when prompted, or send Authorization: Bearer <YOUR_APIFY_TOKEN>. The tool starts a run and returns run and dataset IDs; the agent can read rows with get-dataset-items.

Clients without remote support can use npx @apify/actors-mcp-server --tools lentic_clockss/facebook-ad-library-scraper with APIFY_TOKEN set.

Example prompt: “Find up to 3 active US ads matching shopify and show their headlines and destination links.”

Apify API

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("lentic_clockss/facebook-ad-library-scraper").call(
run_input={"searchQuery": "shopify", "country": "US", "maxResults": 3}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row)

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('lentic_clockss/facebook-ad-library-scraper').call({
searchQuery: 'shopify', country: 'US', maxResults: 3,
});
const { items: rows } = await client.dataset(run.defaultDatasetId).listItems();
console.log(rows);

For HTTP, send the input as JSON to POST https://api.apify.com/v2/acts/lentic_clockss~facebook-ad-library-scraper/runs with an Authorization: Bearer <YOUR_APIFY_TOKEN> header. After completion, read GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json.

Integrations

Use Apify integrations with Google Sheets, Make, Zapier, n8n, Slack, Airtable or webhooks. Set recurring collection through Apify Schedules.

FAQ

This Actor collects public data, not private account content. You are responsible for complying with applicable terms and data-protection law. Publicly visible personal data still requires a lawful basis for your intended use. This is not legal advice.

Why did my run end as ABORTED?

The run stopped before normal completion. Check its status message and log for the specific reason, including whether it was cancelled. Do not assume it will restart automatically. Inspect the dataset before starting another run; rows already delivered remain available.

How many results can I get?

maxResults accepts up to 5000 per keyword or Page, not a guaranteed number of matches. Worldwide searches allow at most 50 per input. Free-plan limits, available matches and your maximum cost can reduce the total.

Why are some fields empty?

Meta does not disclose every field for every ad. Contact details vary by advertiser; enrichment may be unavailable or stop before completion. leadAbsences explains missing contact data. A missing active-status flag remains null.

Does this return ad performance metrics?

It returns disclosed spend and impression ranges when available, commonly for political or issue ads. It does not provide private Ads Manager metrics such as click-through rate or conversions. An active ad is not proof that it performs well.

Can I monitor only new ads?

Set incremental to true. History is shared across matching keywords, Pages, country, adType and activeStatus in facebook-ad-library-checkpoints. Only delivered ads are marked seen. History retains the latest 10,000 IDs per search scope, so this is not an unlimited archive.

Can I save images and videos?

Set downloadAssets to true. The Actor attempts to save the first image and video per ad in the run's key-value store and lists successful keys in assetKeys. Files over 9 MB are skipped. Download failures do not mean the ad row is missing.

What does an empty successful run mean?

RUN_SUMMARY.emptyReason distinguishes NO_MATCH from NO_NEW_ADS for incremental searches. Neither creates a billed ad row. Check your keyword, Page, country and filters before widening the search.

Limitations

  • This Actor collects Ad Library ads, not Facebook posts, groups, comments or private profiles. Non-Page target links are rejected.
  • Results reflect available public disclosures, not a complete historical archive or guaranteed market coverage.
  • Contact enrichment is enabled by default but does not guarantee phones, emails or addresses. Current extraction does not populate geo or person.
  • Source restrictions can reduce results or prevent collection. Disclosed spend and reach are not available for every ad.
  • Creative lists are capped at 50 entries; fields such as cardsCount, imageUrlsCount and videoUrlsCount retain the original count when truncated.
  • Date filters exclude ads with no start date. Carousel is not a mediaType option; inspect displayFormat after collection.

More ad library and ads intelligence scrapers from the same publisher:

Browse all of our scrapers at apify.com/lentic_clockss.

Support

Report a problem or request a field through the Issues tab of this Actor's page. Include the run ID and the input you used.