Meta (Facebook & Instagram) Ads Library Scraper
Pricing
from $0.14 / 1,000 results
Meta (Facebook & Instagram) Ads Library Scraper
Scrape all Facebook & Instagram ads of any page from the Meta Ad Library. Extract ad creatives, texts, titles, CTAs, image & HD video URLs, spend, reach and dates. Fast parallel scraping, multiple pages per run, date filters, no login or API key. Daily checks to ensure quality!
Pricing
from $0.14 / 1,000 results
Rating
5.0
(10)
Developer
Mary Lou
Maintained by CommunityActor stats
6
Bookmarked
610
Total users
415
Monthly active users
2 days ago
Last modified
Categories
Share
See every ad your competitors are running — or every ad mentioning your keyword — and download it all as a spreadsheet.
Facebook's Ad Library shows every ad any page is running on Facebook and Instagram. It's public, but you can only scroll it one ad at a time in a browser, and you can't export anything.
This scraper does that scrolling for you. Give it a page (or ten), or just a keyword to search across every advertiser, press start, and you get a clean table of every ad: the ad copy, the headline, the button, the landing page link, and direct links to every image and video — ready to open in Excel, Google Sheets, or push into your own tools.
No Facebook account. No API key. No coding.
What you can use it for
- 🔍 Competitor research — see exactly which ads a competitor is running right now, and which ones they've been running for months (long-running ads are usually their winners)
- 🎨 Creative inspiration — download competitor images and videos to study hooks, formats and angles before your next campaign
- 📈 Track over time — run it on a schedule and watch when competitors launch, pause, or scale creatives
- 📊 Market research — search a keyword and pull ads from an entire industry at once, whoever is running them, and analyse messaging trends
- 🧲 Find advertisers you don't know yet — a keyword search surfaces every page advertising on that topic, not just the brands you already track
- 🕵️ Ad spying at scale — thousands of ads across many brands in one run, instead of endless manual scrolling
How to use it — step by step
1. Find the brand in the Ad Library
Go to facebook.com/ads/library, pick your country, choose All ads, and search for the brand name. Click the brand to open its page of ads.
2. Copy the URL from your browser's address bar
It will look something like this:
https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&search_type=page&view_all_page_id=116700222203350
3. Paste it into the "Ad Library or Facebook page URLs" field
That's the only thing you have to fill in. You can paste several URLs — one per
line — to scrape multiple brands in the same run. Already on the brand's
Facebook page? Its ordinary link works here too, like
https://www.facebook.com/zara.
4. (Optional) Raise or remove the limit
Max ads comes prefilled with 100 so your first run finishes in seconds and
costs almost nothing. Raise it once the output looks right, or clear the field
to scrape everything.
5. Click Start
Results appear in the Storage → Dataset tab as they're scraped. When it's finished, use the Export button for CSV, Excel, JSON, or copy the API link.
Don't want to bother with URLs? Just type the brand's name —
ZARA,nike— into the Page IDs or names field. The scraper looks it up the same way the Ad Library's own search box does. The numeric page ID (theview_all_page_id=number in the Ad Library URL), an@usernameor the brand's facebook.com link work too.
Searching by keyword instead of by page
Don't have a specific brand in mind? Type a word or phrase into the Keyword
field (or several into Keywords) and the scraper searches the whole Ad
Library, returning matching ads from every advertiser — exactly like typing it
into the Ad Library search box. Pasting a keyword search URL from your browser
(the ones with q= in them) works too.
Two match types, set with Keyword match type:
- Any order (default) — the words can appear anywhere in the ad, in any order. Same as the Ad Library's own default.
- Exact phrase — the words must appear together, in that order.
Keyword searches can match tens of thousands of ads, so set Max ads and narrow the Country and dates on your first run. And clear the Page ID field if it's prefilled — otherwise that page gets scraped as well.
Input options
Everything is optional except telling it what to scrape — a page or a keyword. Leave that out and the run ends straight away, with the log saying what to fill in.
| Setting | What it does |
|---|---|
| Ad Library or Facebook page URLs | Paste one or more URLs copied from your browser — Ad Library page URLs (view_all_page_id=), keyword search URLs (q=), a single ad's link (?id=), or simply a brand's Facebook page link (facebook.com/zara). A brand's Instagram profile or website works too (instagram.com/zara, zara.com). Each Ad Library page or keyword URL keeps its own filters (country, dates, active status). This is the easiest way to use the scraper. |
| Ad Library or Facebook page URL | Same thing, for a single URL. |
| Page IDs or names | Pages instead of full URLs: numeric page IDs, or simply the advertisers' names (ZARA), @usernames or facebook.com page links. |
| Page ID or name | A single page, any of those ways. Clear it if you're searching by keyword. |
| Keyword | Search every advertiser's ads for this word or phrase, instead of scraping one page. |
| Keywords | Several keywords in one run, all using the settings below. |
| Keyword match type | Any order (default) or Exact phrase. Applies to keyword searches only. Typed spellings like exact work too; anything else means any order. |
| Active status | All ads = the page's entire history (often far more than the Ad Library shows by default). Active only = ads running right now. Inactive only = ads that have stopped. Typed spellings like Active or running work too; anything else means all ads. |
| Country | Limit to ads shown in one country — every country the Ad Library lists — or ALL for everywhere. You can also type a country's name or code; one the scraper can't place is searched as ALL, never a failed run. |
| Start date from / to | Only ads that were running during this window. Note this is not "created in" — an ad that started last year and is still running today will show up in a window covering today. |
| Max ads | Stop after this many ads in total. Prefilled with 100 for a quick, cheap first run — raise it or leave it empty to get everything. |
| Max concurrency | How many pages/date-ranges to scrape at the same time. Default 4, roughly 4× faster than one at a time for big brands. Drop it to 1 if you ever see captcha warnings, or need results in strict impression-ranking order. |
| Delay between pages (ms) | Politeness pause between requests. Default 300 works well. Increase to 1000+ if you ever see captcha warnings in the log. |
| Raw output | Off by default. Turn on only if you want Facebook's untouched raw data structure. |
| Proxy | Leave on Residential — this is required for reliable results. |
Calling it from code, an AI agent or another tool? Field names and
values are read forgivingly. pageId or page_id work as well as pageID,
and so do the names other scrapers use: startUrls, urls and url for
URLs, and maxItems or resultsLimit for the ad limit. A country can be
Italy or it, an active status Active or running, a date 20/11/2025
or Nov 20 2025. A number outside a field's range is brought into it (a
concurrency of 10 runs at 6), and null means the default. A link
or name the scraper can't use is skipped with a warning rather than failing
the run. The run log says how each field was read.
Example: one competitor, everything they've ever run
{"adLibraryUrls": ["https://www.facebook.com/ads/library/?active_status=all&ad_type=all&country=ALL&search_type=page&view_all_page_id=116700222203350"]}
Example: three competitors' currently-active ads, fast
{"adLibraryUrls": ["https://www.facebook.com/ads/library/?active_status=active&country=ALL&search_type=page&view_all_page_id=116700222203350","https://www.facebook.com/ads/library/?active_status=active&country=ALL&search_type=page&view_all_page_id=102921707941613","https://www.facebook.com/ads/library/?active_status=active&country=US&search_type=page&view_all_page_id=688155977722463"],"maxConcurrency": 3}
Example: every advertiser running ads about a topic
{"keyword": "running shoes","searchType": "keyword_unordered","country": "US","activeStatus": "active","maxAds": 500}
Example: several keywords, exact phrases only
{"keywords": ["free trial", "money back guarantee"],"searchType": "keyword_exact_phrase","country": "GB","maxAds": 1000,"maxConcurrency": 3}
Example: brands by name, no URLs or IDs
{"pageIDs": ["ZARA", "nike"],"country": "IT","activeStatus": "active","maxAds": 200}
Each name is looked up the way the Ad Library's search box does it. A verified page wins; if several unverified pages share the name, all of them are scraped, the most-liked first; and a name no page has is searched as a keyword instead.
Example: quick, cheap test run
{"pageIDs": ["116700222203350"],"activeStatus": "active","maxAds": 50}
What you get
One row per ad. Here's a real (shortened) example:
{"ad_archive_id": "1227225301509075","page_id": "116700222203350","page_name": "BetterMe","is_active": true,"start_date": 1723359600,"end_date": 1787468400,"publisher_platform": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER"],"collation_count": 1,"snapshot": {"title": "Entrenador personal 24/7 en la aplicación","body": { "text": "Plan de 28 Días para lograr un peso saludable en casa." },"caption": "itunes.apple.com","cta_text": "Install now","cta_type": "INSTALL_MOBILE_APP","link_url": "http://itunes.apple.com/app/id1264546236","display_format": "VIDEO","videos": [{ "video_hd_url": "https://...", "video_preview_image_url": "https://..." }],"images": [],"page_like_count": 6197887,"page_categories": ["Health/beauty"]}}
The fields you'll care about most:
| Field | What it is |
|---|---|
snapshot.body.text | The main ad copy |
snapshot.title | The headline |
snapshot.cta_text / cta_type | The button ("Shop now", "Install now"…) |
snapshot.link_url | Where the ad sends people |
snapshot.images[] | Direct image URLs (full resolution) |
snapshot.videos[] | Direct video URLs (HD, SD, and thumbnail) |
snapshot.display_format | VIDEO, IMAGE, DCO, carousel… |
is_active | Is it still running right now |
start_date / end_date | When it ran (Unix timestamps) |
publisher_platform | Facebook, Instagram, Messenger, Threads… |
collation_count | How many variants of this ad exist |
page_name, snapshot.page_like_count | Who's running it, and how big they are |
spend, currency, reach_estimate | Only filled for political/social-issue ads, where Meta discloses it. Blank for normal commercial ads — that's a Facebook limitation, not a scraper one. |
Every row has the same columns, so nothing breaks when you open it in a spreadsheet. Fields Facebook doesn't provide come back empty rather than missing.
Export: CSV, Excel, JSON, XML, or an API endpoint — from the Export button on the run's Dataset tab.
Speed and limits
Facebook hands out ads in small batches, so time scales with the number of ads:
| Ads on the page | Roughly how long |
|---|---|
| 200 | ~30 seconds |
| 1,000 | ~2–3 minutes |
| 10,000 | ~10 minutes at Max concurrency 3 |
Max concurrency (4 by default) is what makes big brands fast — the scraper automatically splits their history into date ranges and works on several at once.
If a run is interrupted (you abort it, the platform restarts it, or Facebook rate-limits part of it), progress is saved automatically. A platform restart resumes by itself. If you start a new run afterwards, it scrapes fresh by default so your dataset is always complete in one place — or turn on Continue from last run to fetch only what the interrupted run missed (its ads stay in that run's dataset).
Cost
From $0.14 per 1,000 ads, plus Apify platform usage. No scraper charge for runs that find nothing.
$0.15 per 1,000 on the Free and Bronze tiers, $0.14 on Silver and above.
Most Ad Library scrapers roll infrastructure into one flat per-result price, with a markup baked in. This one keeps the two separate: you pay per ad for the scraping itself, and Apify bills the compute and proxy traffic at your plan's own rate — the same credits your subscription already includes.
| What you scrape | Scraper charge | + Platform usage | Roughly |
|---|---|---|---|
| 200 ads (one brand's active ads) | $0.03 | ~$0.02 | ~$0.05 |
| 1,000 ads | $0.15 | ~$0.10 | ~$0.25 |
| 10,000 ads | $1.50 | ~$1.00 | ~$2.50 |
| 100,000 ads | $15.00 | ~$10.00 | ~$25.00 |
Both columns are quoted at the Free plan rate, which is the most expensive this gets — see below.
Usage figures are measured from real runs on the Free plan rate and rounded up. Expect roughly $0.06–$0.12 per 1,000 ads depending on run shape — long history scrapes split into more parallel sessions and use a little more proxy traffic than a quick active-ads snapshot. Looking a brand up by name, fetching a single ad from its link, or checking a brand's regional pages when its own page has nothing matching each add an Ad Library page load or two to the run — a fraction of a cent.
It gets cheaper as your plan goes up
Both halves are discounted at higher tiers, so the same scrape costs less on a bigger plan:
| Tier | Scraper charge | Compute | Residential proxy |
|---|---|---|---|
| Free / Bronze | $0.15 / 1,000 ads | $0.20 / CU | $8.00 / GB |
| Silver | $0.14 / 1,000 ads | $0.16 / CU | $7.50 / GB |
| Gold and above | $0.14 / 1,000 ads | $0.13 / CU | $7.00 / GB |
Platform usage is drawn from the prepaid usage credit your plan already includes, so on a paid plan a good part of it is money you've spent regardless. See Apify pricing for the full rate card.
Keeping it predictable
- Set
Max ads. The scraper stops exactly there. Perfect for testing, and for putting a hard ceiling on any single run. - Set a maximum cost per run (in the run options). The scraper checks this before it starts and stops as soon as it has delivered what your budget covers — it will never quietly keep scraping past what you're paying for.
A whole-archive scrape of a very large advertiser can be tens of thousands of ads,
so start with Active status: Active only or a Max ads limit if you just want a
snapshot of what's running now.
Frequently asked questions
Do I need a Facebook account or login? No. The Ad Library is public information, and the scraper needs no account, password, cookies, or API token.
Do I need the official Meta Ad Library API? No — and it wouldn't help you anyway. Meta's official API only covers political and social-issue ads in most countries. This scraper returns all ad categories, with the full creatives and media URLs.
Is this legal? The Ad Library is Meta's own public ad-transparency tool, published deliberately so anyone can inspect advertising. This scraper only collects what's shown there — no private data, no logged-in data, no personal information. As with any scraping, you're responsible for how you use the data in your own jurisdiction.
Why do I get way more ads than the Ad Library page showed me?
The Ad Library UI usually shows active ads by default. The scraper defaults to
All ads, which includes everything the page has ever run — often 10–100× more.
Set Active status to Active only if you want to match what you saw on screen.
I set a date range but I'm getting ads that started before it. Why? Facebook's date filter means "was this ad running during this window", not "did it start in this window". A long-running evergreen ad legitimately matches every window it was live in. This is Facebook's behaviour, and the same thing happens in the Ad Library UI.
What about spend and reach?
Meta only discloses spend and reach for political and social-issue ads. For normal
commercial ads those fields come back empty — nobody can scrape numbers Facebook
doesn't publish.
Can I scrape several competitors at once? Yes. Paste several URLs into Ad Library or Facebook page URLs, or several names or IDs into Page IDs or names. They're scraped in parallel (Max concurrency, 4 by default) into one dataset, and Max ads applies across all of them combined — the first pages to answer fill it, so set it high enough to cover every page.
Can I run this automatically every day/week? Yes — use Apify Schedules on this Actor. A common setup is a daily run per competitor, so you can diff the results and spot new creatives.
How do I get the images and videos themselves? The dataset gives you direct URLs. Open them in a browser, or feed the column to any bulk downloader. The scraper doesn't re-host media files.
What happens if one of my pages won't load? The rest of the run carries on. A page or date range that Facebook blocks or that won't load is tried again once the rest are done: one at a time, after a short pause, as a different browser. If it still fails, it is left out with a warning, the run finishes with everything else, and its progress is saved: run again with Continue from last run to retry just what was missed. If Facebook blocks everything, the run ends without ads and its status message says why. It is not marked as failed.
The log shows a captcha warning — what do I do? That means Facebook rate-limited part of the run. The scraper retries those parts at the end of the run, and their progress is saved, so a re-run continues where it stopped. To avoid it, lower Max concurrency or raise Delay between pages.
Can it search by keyword instead of by page?
Yes. Put a word or phrase in the Keyword field (or paste a keyword search URL
with q= in it) and it returns matching ads from every advertiser, with the same
output columns as a page scrape. Choose Any order or Exact phrase with
Keyword match type. Keyword searches can match tens of thousands of ads, so
set Max ads and narrow the country and dates first.
Can I just type the brand's name instead of finding its page ID?
Yes. Put it in Page IDs or names — ZARA, nike, @zarahome, or the
brand's facebook.com link. The scraper looks it up in the Ad Library's own
advertiser search and uses the page whose name or username matches exactly.
A verified page always wins. If several unverified pages share the name, it
scrapes all of them, the most-liked first, so nothing is missed — the run log
lists each one with its ID, and you can give a single ID next time to scrape
just that page. If no page has that exact name, the scraper searches every
advertiser's ads for the name as a keyword instead. That search stops at 1,000
ads if you haven't set Max ads. The log lists the closest pages it found, so
you can give one's ID next time.
My run finished without any ads. Why? Usually one of two things, and the run log says which:
- Nothing to scrape was given. If the page, keyword and URL fields are all empty, the run ends straight away. The log and the run's status say what to fill in.
- The page has no ads matching your filters. A brand can advertise heavily
and still have nothing in one country. Gymshark had about 4,100 active ads
worldwide but none shown in Italy. Try Country
ALL, or Active statusAll ads. The scraper already checks the brand's regional pages for you (see below), and it double-checks an empty result on a fresh connection before believing it.
If you gave a brand's name rather than a page ID, and none of the pages with that name has matching ads, the scraper searches every advertiser's ads for the name instead (the exact phrase first, then the words in any order), so you still get the ads that mention it. The log says when it does this. A page ID is taken as your choice: if it is empty, that is the answer.
Why did I get ads from a page I didn't ask for?
Some brands advertise from a separate page in each country. Gymshark, for
example, has its main page plus Gymshark Germany and Gymshark France. When a
page you asked for has no ads matching your filters, the scraper also checks
the brand's regional page for the country you picked, with the same filters,
or every regional page when Country is ALL. The run log names each page
it adds, or which countries the brand's other pages cover. Every ad carries
its own page_id and page name, so you can tell them apart.
Can I scrape one specific ad?
Yes. Paste the ad's own link — the one with ?id= in it, like
https://www.facebook.com/ads/library/?id=3666222156864560 — into Ad Library
or Facebook page URLs. You get that single ad, with the same columns as
everything else. The
country, date and active-status settings don't apply to it, so they can't hide
the ad you asked for.
Can I mix pages and keywords in one run? Yes — fill in both, and every target is scraped in the same run (in parallel when Max concurrency is above 1). Max ads counts across all of them together.
Support
Found a bug, need a field that isn't there, or want a custom scraping setup? Open an issue on the Actor's Issues tab and I'll take a look.