Facebook Ad Library Scraper: What Works, What Breaks

A Facebook Ad Library scraper is a script that pulls ad data out of facebook.com/ads/library instead of clicking through it by hand. Most of them break, and they break for a predictable reason: the Ad Library is a React application that lazy-loads results, so there is no static HTML to parse.
If you are deciding whether to build one, this page covers what actually works, what fails, and when a scraper is the wrong tool for the job.
Why does a simple scraper return nothing?
Fetch the Ad Library URL with requests or curl and you get an application shell. No ads.
The results are fetched by JavaScript after the page loads, then rendered into the DOM, then extended as you scroll. Three separate obstacles for a plain HTTP client:
- Client-side rendering — the markup you want does not exist in the initial response.
- Infinite scroll — only the first batch loads; the rest arrives on scroll events.
- Obfuscated class names — the CSS classes are generated and change between deploys, so selectors rot.
This is the point where most people discover the official API and assume it solves everything.
The Ad Library API page covers exactly what fields you do get and the access process.
What approaches actually work?
Three, with different costs.
| Approach | Gets commercial ads | Breaks when | Effort |
|---|---|---|---|
| HTTP + HTML parse | No | Immediately | Low, wasted |
| Official Ad Library API | No (political/EU only) | Rarely | Medium |
| Headless browser (Playwright/Puppeteer) | Yes | Meta ships a layout change | High, ongoing |
| Browser extension | Yes | Rarely | None |
Headless browser automation is the only scripted route to commercial ads. You drive a real browser, let the page render, scroll to trigger loading, and read the DOM. Playwright and Puppeteer both do this well.
It works. It also means you now own a maintenance job. Meta changes the Ad Library layout regularly, and every change is a chance your selectors return empty lists silently.
What breaks a working scraper?
Four things, roughly in the order you meet them.
Layout changes. Generated class names shift. Anchor on stable text and structure — the "Started running on" label, the Library ID line — rather than on CSS classes.
Rate limiting. Aggressive scrolling and rapid repeat requests get throttled and then blocked. Pace requests, randomise delays, and do not run twenty workers against the same search.
Media URLs that expire. The video and image URLs on the cards are signed and time-limited. Grabbing the URL is not the same as grabbing the file. Download immediately, and expect requests without the right headers to return 403.
Carousels. A carousel card shows one image in the DOM until you interact with it. Scrapers that read the first frame quietly lose every card after the first, and you do not notice until you review the export.
Is scraping the Ad Library legal?
The Ad Library is public and requires no login for basic search, which is why it is routinely used for competitive research and academic work. Downloading public ads to study them is standard industry practice.
Two lines worth respecting regardless. Meta's terms restrict automated collection, so heavy scraping can get an IP or account blocked. And whatever you collect, copy the angle, not the asset — reusing someone else's creative in your own commercial ads is a different problem entirely, and a reportable one.
This is not legal advice. If you are building something at scale or commercial, take actual advice.
When is a scraper the right tool?
When you need structured data across many advertisers, repeatedly, into a database. Academic research, market-wide trend tracking, an internal dashboard covering hundreds of brands. Those justify the maintenance.
When you need to study competitors' creative, a scraper is usually overkill. The job is: find the ads still running after 60 or 90 days, save the files, and read the hooks. You do not need a pipeline for that; you need a save button.
That is the honest gap in the Ad Library. It shows every active ad from any advertiser worldwide, free, with a start date on each card. It has no download button, no way to keep an ad once it is paused, and clunky exact-match search. The full guide to the Meta Ad Library covers those limits.
A browser extension closes the gap without any of the scraper problems. A free Meta Ad Library Downloader adds a Download button to every ad inside the library — HD video with no watermark, images, and full carousels rather than just the first card. Bulk mode scrolls a whole search, collects every running ad and packs it into one ZIP with a CSV and a searchable swipe board. It runs in your browser on your own connection. Disclosure: Klipio makes it, it is free, and it needs no account.
The trade-off is real and worth stating: an extension gives you files and a swipe board, not rows in your own database. If you need the rows, build the scraper.
What about Python specifically?
Playwright's Python bindings are the practical choice, and the detailed Python walkthrough covers the code patterns and the specific headers media downloads need.
The short version: requests plus BeautifulSoup will not work, playwright will, and you should budget maintenance time rather than treating it as a one-off script.
What fields are worth extracting?
If you do build one, decide the schema before you write selectors. The fields that stay useful:
- Advertiser Page name and Page ID — the join key for everything else
- Library ID — the only stable per-ad identifier
- Started running on — the longevity signal, and the reason to run this at all
- Ad copy — primary text, headline, description, and the call-to-action label
- Format — image, video, carousel, and card count for carousels
- Media URLs — grabbed and downloaded in the same pass
- Landing URL — often a redirect, so resolve it to the real destination
- First seen and last seen in your data — so you can detect when an ad disappears
That last pair matters more than people expect. The library shows only what is live now, so the record of when an ad stopped only exists if you were collecting when it did.
FAQ
Can you scrape the Facebook Ad Library?
Technically yes, with a headless browser like Playwright or Puppeteer that renders the page and scrolls to load results. Plain HTTP requests return an empty application shell because the ads are rendered client-side.
Does the Meta Ad Library API return competitor ads?
No. The official API returns political and social-issue ads, plus EU ads under the DSA. Normal commercial ecommerce ads are not available through it.
Why does my Ad Library scraper return empty results?
Most often the page has not finished rendering, or Meta changed the layout and your selectors no longer match. Wait for network idle after scrolling, and anchor on stable text rather than generated class names.
Is it legal to scrape the Facebook Ad Library?
The library is public and researching it is standard practice, but Meta's terms restrict automated collection and heavy scraping can get you blocked. Copy the angle from what you find, never the asset. Not legal advice.
Why can't I download the video files my scraper found?
The media URLs are signed and expire, and requests without the right headers are often rejected. Download the file at the moment you extract the URL rather than saving the link for later.
Is there an alternative to building a scraper?
For creative research, a browser extension does the same practical job with no maintenance — it adds a download button inside the library and can bulk-collect a whole search into a ZIP. Build a scraper only if you need structured rows in your own database.
The Klipio extension adds a download button to every ad in the Meta Ad Library: one click per ad, or bulk-save a whole search as a ZIP with a searchable swipe file inside. Free, no sign-up.
Get the free extensionKlipio reads a competitor's live Meta ads, ranks them by how long they have been running — the honest signal that an ad is profitable — and turns the winning angle into on-brand creative for your own brand. 3-day free trial.
Start free — 3-day trial →

