Meta Ad Library Scraper avatar

Meta Ad Library Scraper

Pricing

from $0.50 / 1,000 ads

Go to Apify Store
Meta Ad Library Scraper

Meta Ad Library Scraper

Scrape Facebook and Instagram ads from the Meta Ad Library by keyword or page URL, no login needed. Extract ad creatives, images, videos, carousel cards, copy, CTA, landing pages, advertiser details, dates and platforms. Track competitor ads, build swipe files and analyze ad strategy at scale.

Pricing

from $0.50 / 1,000 ads

Rating

0.0

(0)

Developer

SilentFlow

SilentFlow

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Turn the Meta Ad Library into clean, structured ad data you can actually work with. Every active and inactive ad from any advertiser or keyword, with the full creative, in seconds.

Scrape Facebook and Instagram ads straight from Meta's public Ad Library. Search by keyword, pull every ad a page is running, or paste an Ad Library URL. Get the headline, body, call to action, landing page, images, videos, carousel cards, advertiser identity, run dates, and platform spread for each ad. No login, no API key, no cookies.

How it works

How the Meta Ad Library Scraper works

  1. Drop in a keyword search URL, a Facebook Page URL, or an Ad Library URL.
  2. Set how many ads you want.
  3. Get back a clean row per ad, with the full creative and advertiser data, ready for export.

โœจ Why teams choose this over other Meta Ad Library scrapers

Spending hours scrolling the Ad Library and screenshotting competitor ads? Running scrapers that choke after a few hundred results? Tired of getting back a headline and nothing else?

  • ๐Ÿ’ฐ Pay per result, not per minute. No compute costs, proxies included. You pay for ads delivered, period. A run that returns nothing costs nothing.
  • ๐Ÿ” Drop-in compatible, plus extras. Same inputs and the same output structure as the most popular Ad Library scraper, so you can switch your pipeline over with zero rewrites, and get cleaner fields on top.
  • ๐Ÿงน Flat, analysis-ready output. Other scrapers hand you the raw nested object and leave you to dig through snapshot.cards[].video_hd_url. We pull the essentials up to the top level: cta, landing_url, title, body, plus image_urls and video_urls as flat lists. Open the CSV and the columns you need are right there.
  • ๐Ÿ–ผ๏ธ Every creative URL in one list. All images and all videos across single ads and carousels are flattened into image_urls and video_urls. Build a swipe file with one column, not a JSON crawl.
  • โณ Spot winning ads instantly. Each ad carries days_running, how long it has actually been live. Long-running ads are the ones that work, sorted in seconds.
  • ๐Ÿงฑ The full creative, not just the caption. Every image, every video, and every carousel card comes through with its own link, call to action, and copy. Nothing is dropped.
  • ๐Ÿ†” No login, no account, no API key. This reads the public Ad Library directly. Nothing to authenticate, nothing to get rate limited on your own account.
  • ๐ŸŒ Any country, Facebook and Instagram. Pull ads targeted to any market and see exactly which platforms each ad runs on, from one input.
  • ๐Ÿท๏ธ Advertiser intelligence built in. Every ad carries the advertiser's page likes. Turn on ad details and each ad also gets advertiser_name, advertiser_ig_followers, advertiser_likes, advertiser_category, and EU reach as flat columns. Size up who is spending in one glance.
  • ๐Ÿ“Š Reliable at volume. No login means no account to get rate limited, and the scraper recovers from hiccups on its own. In testing it held a perfect success rate across dozens of parallel runs in 10+ countries.
  • ๐Ÿ“ฆ 60+ fields per ad. The fields other scrapers skip, like the carousel breakdown, the collation of duplicate ads, total active time, and the advertiser profile, are often the ones that tell you what is actually working.

๐ŸŽฏ What you can do with Meta Ad Library data

TeamWhat they build
Performance marketingA live feed of every competitor ad by keyword and country, refreshed before each campaign sprint
Creative strategyA searchable swipe file of winning images, videos, and carousels pulled from the top spenders in a niche
Brand and commsA monitor that flags when a competitor launches a new campaign or kills an old one
AgenciesClient pitch decks backed by the actual ads competitors are running, not guesses
Ecommerce and DTCA catalog of product ads and landing pages across an entire category to spot pricing and offer angles
Market researchA cross-country comparison of how the same brand advertises in different regions and languages
Affiliate and dropshippingA scan of which products and creatives are scaling, by how many active ad variants a page is running

๐Ÿ“ฅ Input parameters

Sources

FieldTypeDescription
urlsarrayOne or more Ad Library search URLs or advertiser page URLs. This is the only required field.

A search URL looks like https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all. An advertiser page URL can be a simple https://www.facebook.com/nike or the Ad Library URL that contains view_all_page_id. Page URLs return every ad that advertiser is running. You can mix both in one run.

Limits

FieldTypeDefaultDescription
countinteger100Total ads to collect across all URLs. Leave empty for no cap.
limitPerSourceinteger(none)Maximum ads to collect per input URL.

Page URL filters

These apply when an input is an advertiser page URL.

FieldTypeDefaultDescription
scrapePageAds.activeStatusselectAllAll, active only, or inactive only.
scrapePageAds.countryCodestringALLTwo letter country code, or ALL.

Options

FieldTypeDefaultDescription
scrapeAdDetailsbooleanfalseAlso fetch the advertiser profile (followers, likes, page spend) and EU reach breakdown for each ad.
cleanOutputbooleanfalseReturn only the flat, analysis-ready fields instead of the full raw object. Best for tidy CSV.
runTagstring(none)A label written into every output row, handy for tracking which run produced which data.
debugModebooleanfalseVerbose logs for troubleshooting.

๐Ÿ“Š Output data

Each ad is one row. Example of a keyword search result:

{
"ad_archive_id": "1869276447125570",
"ad_library_url": "https://www.facebook.com/ads/library/?id=1869276447125570",
"page_id": "15087023444",
"page_name": "Nike",
"is_active": true,
"start_date": 1744675200,
"start_date_formatted": "2025-04-15",
"end_date": 1763712000,
"end_date_formatted": "2025-11-21",
"currency": "USD",
"publisher_platform": ["FACEBOOK", "INSTAGRAM"],
"collation_count": 2,
"total_active_time": 1209600,
"cta": "Shop Now",
"landing_url": "https://www.nike.com/",
"title": "Nike Air Monarch IV",
"body": "Get the gear not afraid to put in the work.",
"image_urls": ["https://scontent.xx.fbcdn.net/v/t45.1600-4/..."],
"video_urls": [],
"days_running": 135,
"total_variants": 2,
"snapshot": {
"body": { "text": "Get the gear not afraid to put in the work." },
"title": "Nike Air Monarch IV",
"caption": "nike.com",
"cta_text": "Shop Now",
"cta_type": "SHOP_NOW",
"link_url": "https://www.nike.com/",
"link_description": "Nike delivers innovative products, experiences and services.",
"page_profile_picture_url": "https://scontent.xx.fbcdn.net/...",
"page_like_count": 39000000,
"display_format": "IMAGE",
"images": [{ "original_image_url": "https://scontent.xx.fbcdn.net/..." }],
"videos": [],
"cards": []
},
"runTag": "competitor-scan"
}

Example of a video ad with a carousel:

{
"ad_archive_id": "1191898553123641",
"ad_library_url": "https://www.facebook.com/ads/library/?id=1191898553123641",
"page_name": "Whatnot",
"is_active": true,
"publisher_platform": ["FACEBOOK", "INSTAGRAM", "MESSENGER"],
"snapshot": {
"display_format": "DCO",
"cta_text": "Install Now",
"cta_type": "INSTALL_MOBILE_APP",
"cards": [
{
"title": "Whatnot",
"body": "Live shopping for the things you love.",
"cta_text": "Install Now",
"link_url": "https://itunes.apple.com/app/id1093315431",
"video_hd_url": "https://video.xx.fbcdn.net/...",
"video_preview_image_url": "https://scontent.xx.fbcdn.net/...",
"resized_image_url": "https://scontent.xx.fbcdn.net/..."
}
]
}
}

With scrapeAdDetails enabled, each ad also carries an advertiser block (and aaa_info EU reach for EU and political ads):

{
"page_name": "Nike",
"advertiser": {
"ad_library_page_info": {
"page_info": {
"page_name": "Nike",
"ig_username": "nike",
"ig_followers": 291936445,
"likes": 39000000,
"page_category": "Sportswear store",
"page_profile_uri": "https://www.facebook.com/nike/"
},
"page_spend": {
"is_political_page": false,
"lifetime_by_disclaimer": []
}
},
"page": { "about": { "text": "Just Do It." } }
},
"aaa_info": {
"eu_total_reach": 1840000,
"age_audience": { "min": 18, "max": 65 },
"gender_audience": "ALL",
"age_country_gender_reach_breakdown": [
{ "country": "DE", "age_gender_breakdowns": [ { "age_range": "18-24", "male": 12000, "female": 9000 } ] }
]
}
}

๐Ÿ—‚๏ธ Data fields

CategoryFields
Quick fields (flat)cta, cta_type, landing_url, title, body, caption, display_format, image_urls, video_urls, days_running, total_variants, page_likes, advertiser_logo
Advertiser (flat, with scrapeAdDetails)advertiser_name, advertiser_category, advertiser_ig_followers, advertiser_likes, advertiser_ig_username, advertiser_page_url, advertiser_about, eu_total_reach
Identityad_archive_id, ad_library_url, page_id, page_name, runTag
Status and timingis_active, start_date, end_date, start_date_formatted, end_date_formatted, total_active_time
Reach and groupingpublisher_platform, collation_count, collation_id, currency, categories
Creative copysnapshot.body.text, snapshot.title, snapshot.caption, snapshot.cta_text, snapshot.cta_type
Landing pagesnapshot.link_url, snapshot.link_description
Mediasnapshot.images, snapshot.videos, snapshot.cards, snapshot.display_format
Advertisersnapshot.page_profile_picture_url, snapshot.page_profile_uri, snapshot.page_like_count, snapshot.page_categories
Transparencyregional_regulation_data, targeted_or_reached_countries, contains_sensitive_content, contains_digital_created_media
Ad details (when scrapeAdDetails on)advertiser.ad_library_page_info.page_info (followers, likes, category), advertiser.ad_library_page_info.page_spend, aaa_info (EU age, gender, country reach)

๐Ÿš€ Examples

Get the latest Nike ads in the US

{
"urls": [
{ "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all" }
],
"count": 50
}

Pull every ad a specific advertiser is running

{
"urls": [{ "url": "https://www.facebook.com/nike" }],
"scrapePageAds.activeStatus": "active"
}

Scan a whole niche for video ads only

{
"urls": [
{ "url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=protein%20powder&media_type=video&search_type=keyword_unordered" }
],
"count": 200
}

Compare one brand across two countries

{
"urls": [
{ "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&q=adidas&search_type=keyword_unordered&media_type=all" },
{ "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=GB&q=adidas&search_type=keyword_unordered&media_type=all" }
],
"count": 300,
"runTag": "adidas-us-vs-uk"
}

Get only the active ads from one advertiser

{
"urls": [{ "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&view_all_page_id=15087023444" }],
"scrapePageAds.activeStatus": "active",
"scrapePageAds.countryCode": "US",
"limitPerSource": 100
}

Add advertiser profiles and EU reach

{
"urls": [
{ "url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=DE&q=insurance&search_type=keyword_unordered&media_type=all" }
],
"count": 50,
"scrapeAdDetails": true
}

๐Ÿค– Copy to your AI assistant

Paste this block into Claude, ChatGPT, or Cursor to give it full context about this scraper:

You have access to the Meta Ad Library Scraper on Apify: silentflow/meta-ad-library-scraper
It scrapes Facebook and Instagram ads from the public Meta Ad Library. No login required.
Input schema:
- urls (required, array of {url}): Ad Library search URLs or advertiser page URLs (with view_all_page_id)
- count (integer, default 100): total ads across all URLs, empty = unlimited
- limitPerSource (integer): max ads per input URL
- scrapeAdDetails (boolean, default false): add advertiser profile + EU reach per ad
- cleanOutput (boolean, default false): return only the flat fields, no raw nested object
- scrapePageAds.activeStatus (string, default all): all, active, inactive (Page URLs)
- scrapePageAds.period (string): "", last24h, last7d, last14d, last30d (Page URLs)
- scrapePageAds.sortBy (string, default impressions_desc): impressions_desc, most_recent (Page URLs)
- scrapePageAds.countryCode (string, default ALL): 2-letter country code or ALL (Page URLs)
- runTag (string): label written into every output row
Output per ad (60+ fields). Flat quick fields: cta, cta_type, landing_url, title, body,
caption, display_format, image_urls[], video_urls[], days_running, total_variants,
page_likes, advertiser_logo. Plus ad_archive_id, ad_library_url, page_id, page_name,
is_active, start_date_formatted, end_date_formatted, publisher_platform, runTag, and the
full raw object including a nested snapshot (cards[], images[], videos[], etc.).
With scrapeAdDetails: flat advertiser_name, advertiser_ig_followers, advertiser_likes,
advertiser_category, advertiser_about, eu_total_reach. Set cleanOutput to drop the raw object.
Pay per result. Proxies included. Use apify-client for Python or JS.

๐Ÿ’ป Integrations

Build a competitor ad monitor in Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("silentflow/meta-ad-library-scraper").call(run_input={
"urls": [{"url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=nike&search_type=keyword_unordered&media_type=all"}],
"count": 200,
})
# Flat fields make this trivial: list live ads, their CTA, landing page and how long they have run
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
if ad.get("is_active"):
print(ad["page_name"], "|", ad["cta"], "->", ad["landing_url"], "|", ad["days_running"], "days")

Build a creative swipe file in JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('silentflow/meta-ad-library-scraper').call({
urls: [{ url: 'https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=US&view_all_page_id=15087023444' }],
count: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
// image_urls and video_urls are already flattened across single ads and carousels
const images = items.flatMap(ad => ad.image_urls || []);
const videos = items.flatMap(ad => ad.video_urls || []);
console.log(`Swipe file: ${images.length} images, ${videos.length} videos`);

Export to CSV from the command line

$curl "https://api.apify.com/v2/datasets/YOUR_DATASET_ID/items?format=csv&token=YOUR_APIFY_TOKEN" -o meta_ads.csv

๐Ÿ“ˆ Performance

MetricValue
Login requiredNone
Platforms coveredFacebook, Instagram, Messenger, Audience Network
Ads per page requestStreamed continuously with automatic pagination
Typical runA few hundred ads in well under a minute
Output formatOne clean row per ad

๐Ÿ’พ Data export

Results land in an Apify dataset with a clean table view (advertiser, active, days live, CTA, landing page, images, videos) so you can scan ads without leaving the console. Export from the dataset tab as JSON, CSV, Excel, HTML, RSS, or XML. To pull data programmatically, use the dataset API:

https://api.apify.com/v2/datasets/YOUR_DATASET_ID/items?format=csv&token=YOUR_APIFY_TOKEN

๐Ÿ’ก Tips for best results

  • Build your search URL on the Ad Library website first, then paste it in. Whatever filters you set there, country, keyword, media type, active status, carry straight into the scraper.
  • Use count for a quick sample and limitPerSource when you want an even number of ads from each of several URLs.
  • To track a single advertiser over time, run the same Page URL on a schedule and compare is_active and start_date between runs.
  • Sort the dataset by days_running to surface the longest running ads first. Those are usually the winners worth copying.
  • image_urls and video_urls give you every creative as a flat list, so a swipe file is one column away in CSV.
  • total_variants tells you how many near duplicate variants an ad has. A high number is a strong signal a creative is scaling.
  • Set a runTag per project so you can tell campaigns apart when you merge several runs into one dataset.

โ“ FAQ

What exactly does this scrape? Public ads from the Meta Ad Library: the creative (images, videos, carousel cards), the copy, the call to action, the landing page link, the advertiser page, run dates, active status, and the platforms each ad runs on.

Can I search by keyword and by advertiser? Yes. Paste a keyword search URL to scan everything matching a term, or an advertiser page URL like facebook.com/nike to pull every ad that advertiser is running. You can mix both in one run.

Do I need a Facebook account or API key? No. The Ad Library is public. There is no login, no API key, and no cookies to manage.

Which countries and platforms are covered? Any country supported by the Ad Library, and ads across Facebook, Instagram, Messenger, and Audience Network. The platform list comes through on every ad.

How fresh is the data? It is pulled live from the Ad Library at the moment you run the scraper, so it reflects what is showing right now, including ads that went live today.

How many ads can I pull? As many as the Ad Library returns for your URL. Use count and limitPerSource to cap the total when you only need a sample.

Can I scrape several searches at once? Yes. Put as many search URLs and Page URLs as you want in the urls list and they are processed in one run.

Do I have to dig through nested JSON? No. The fields most people need, the CTA, landing page, headline, body, and every image and video URL, are pulled up to the top level as cta, landing_url, title, body, image_urls, and video_urls. Open the CSV and the columns are right there. The full raw object is still included if you want it.

What does Scrape ad details add? With it on, each ad also gets an advertiser block (page followers, likes, page spend) and, for EU and political ads, an aaa_info block with the EU age, gender, and country reach breakdown. It is off by default because it makes one extra request per ad.

Why are spend and impression numbers sometimes empty? Meta only publishes spend, impression, and audience reach figures for ads about social issues, elections, or politics, and for EU transparency. Commercial ads do not carry those numbers, so those fields are empty for them. Everything else, the creative and advertiser data, is always there.

This Actor extracts publicly available data from the Meta Ad Library. It does not bypass any login, paywall, or CAPTCHA. Users are responsible for complying with Meta's terms of service and applicable laws in their jurisdiction. The data returned is informational; verify accuracy for regulated use cases.

๐Ÿ“ฌ Support

Need something this scraper doesn't do yet? We ship features fast.

  • Feature requests go straight to our backlog
  • Enterprise needs? We do custom integrations and high-volume plans
  • Pricing questions? Check the Monetization tab on the actor page

Response time: usually under 24 hours.

Check out our other scrapers: silentflow on Apify