agenttoolworks

Guide, measured 2026-10-02

How to scrape the Facebook Ad Library

Meta shows every active ad to anyone who opens the Ad Library, without an account. Getting them out in bulk is another matter: a plain request is refused, a browser gets 30 results, and the button for more answers "Rate limit exceeded". Here is what the page actually returns, and how to read 1,000 ads anyway.

Why the ad libraries are public

Since the EU's Digital Services Act, very large online platforms and search engines that show ads must keep a public repository of them, "through a searchable and reliable tool that allows multicriteria queries and through application programming interfaces", for as long as an ad runs and one year after (Regulation (EU) 2022/2065, Article 39). Each entry must give at least the content of the ad, the person it was presented for, the person who paid if different, the period, whether it targeted particular groups and with which main parameters, and the recipients reached, broken down by Member State for targeted groups.

That is why Meta, Google and Microsoft all run one. They do not publish the same things, and they do not open them the same way.

LibraryAccessWhat it coversWhat it does not give
Meta Ad Library (website)Logged out, in a real browser (JavaScript challenge); 30 results per searchEvery active ad, any country; stopped EU ads for a year; political ads for seven yearsReach, payer and targeting of commercial ads
Meta Ad Library APIFacebook account, authorized users onlyPolitical and issue ads worldwide; other ads only when they reached the EUCommercial ads that never ran in the EU; creatives only behind a snapshot URL
Google Ads Transparency CenterNo official API; public pages, and a free bulk dataset in BigQueryAds on Search, YouTube, Display, Shopping; reach and targeting for the EEAThe bulk dataset has no ad text, image or landing URL
Microsoft Ad Library APIOfficial, public, no key needed (24 ads per request unauthenticated)Bing ads served in the European Economic AreaAnything outside the EEA

Sources: Meta's Ad Library tools page and the ads_archiveAPI reference for Meta; the Transparency Center's terms and the README of its public dataset for Google; Microsoft's Ad Library API guide for Microsoft. Read 2026-10-01.

The website or the API?

Meta's Ad Library API looks like the obvious route until you read its scope: it returns ads about social issues, elections or politics worldwide, and other ads only when they reached the EU. A US-only commercial campaign is on the website and not in the API. The API is also reserved for authorized users, with a Facebook account behind the token.

The website has no such limit: search a keyword in any country and it lists every active ad that matches. For competitor research, that is the useful source, and it is the one the rest of this guide reads.

A plain request gets a 403

Fetch a search URL with curl, even with a current Chrome user agent, and Meta answers HTTP 403 with a 481-byte body and the header x-fb-rd: 1(re-checked on 2026-10-02). The body is a small script that posts to a __rd_verify path and reloads the page. A real browser runs it and gets the results; an HTTP client does not. So whatever you build, it starts with a headless browser: Playwright or Puppeteer with a fresh profile is enough, no account and no cookies.

The 30-result wall

Logged out, the first page of a search holds 30 ads. Scrolling makes the page send a request for the next ones, and that request answered "Rate limit exceeded" to every logged-out attempt we made: from a laptop, from Apify's datacenter proxies with five rotated sessions, and from residential proxies, in headless and headful browsers. A scraper that scrolls and stops when nothing comes back will report 30 ads and call it a day, which is exactly the bug our first version had.

The way through is not to ask for page two at all, but to ask for many different first pages. The page's own filters make that possible.

Walking back through start dates

The Ad Library has a "Most recent" order (newest start date first) and a start-date filter, both in the URL. Combine them and each page load returns the 30 newest ads that started before a given day. Read the oldest start day on that page, move the filter to it, load again, and repeat:

  1. Load the default order once: the top 30 by impressions.
  2. Load "Most recent" with start_date[max] set to today.
  3. Take the oldest start day on the page. If the page spans several days, the next filter is the day after the oldest, so the rest of that day comes next; nothing is skipped.
  4. Union the results by library ID, and stop at your cap or when a page comes back empty.

This loads one such page and prints what came back:

node 22, playwrightrun as printed
import { chromium } from "playwright";

const url = new URL("https://www.facebook.com/ads/library/");
url.search = new URLSearchParams({
  active_status: "active",
  ad_type: "all",
  country: "FR",
  q: "nike",
  search_type: "keyword_unordered",
  media_type: "all",
  "sort_data[mode]": "relevancy_monthly_grouped", // "Most recent"
  "sort_data[direction]": "desc",
  "start_date[min]": "2018-01-01",
  "start_date[max]": "2026-09-20", // only ads that started before this day
}).toString();

const browser = await chromium.launch();
const page = await browser.newPage({ locale: "en-US" });
await page.goto(url.toString());
await page.getByText("Library ID").first().waitFor({ timeout: 30_000 });
const text = await page.locator("body").innerText();
const ids = [...text.matchAll(/Library ID: (\d+)/g)].map((m) => m[1]);
const starts = [...text.matchAll(/Started running on (.+)/g)].map((m) => m[1]);
console.log(`${ids.length} ads on the page`);
console.log(`newest: ${starts[0]}, oldest: ${starts.at(-1)}`);
await browser.close();

On 2026-10-02 it printed 29 ads, the newest started Sep 19, 2026 and the oldest Sep 18: the filter keeps ads that started strictly before the day you give it. Reading the page text is the simplest demonstration; the page also embeds its results as JSON, which is what a production scraper should parse.

Measured with our Actor in Apify's cloud, no proxy, Nike in France:

Ads readPage loadsRun timeApify usage
100430.4 s$0.0023
5002069.1 s$0.0066
1,00042139.0 s$0.0130

Each load brought 24 to 30 new ads. The same walk through residential proxies read 500 ads at about 12 times the cost, for no measurable gain; splitting the search by media type, platform and language instead brought only about 7 new ads per load.

The traps

Google and Bing, beside it

The Google Ads Transparency Center has no official API, but its pages call public endpoints that answer without a key, and Google publishes a free bulk dataset in BigQuery. The dataset has dates, regions and impressions, but no ad text, image or landing URL; those are only on the Transparency Center pages. Microsoft is the simple one: its Ad Library API is official and public, needs no sign-up, and returns Bing ads served in the European Economic Area, 24 per request without a key, with per-country impressions and targeting.

And the terms?

Meta's terms restrict automated collection. In Meta v. Bright Data (N.D. Cal.), the court held in January 2024 that Meta's terms did not reach logged-off scraping of public data, and Meta then dropped its remaining claim; that is one district court's view, not settled law. Google's Transparency Center terms restrict selling its content. Read the terms of every library you use, collect no personal data, and decide with your own counsel. This guide is not legal advice.

Or skip the plumbing

Our Facebook Ad Library scraper does all of the above, reads the Google Ads Transparency Center and the Microsoft Ad Library in the same run, returns one row format for the three platforms with reach and targeting where they are published, and reports a partial result instead of a silent short one. It costs $0.50 per 1,000 ads on the Apify Store.

Questions

Can you scrape the Facebook Ad Library without logging in?

Yes. The Ad Library search page shows every active ad to a logged-out visitor. A plain HTTP client gets a 403 and a JavaScript challenge; a real browser runs the challenge and gets the results, 30 per search.

Why does the Facebook Ad Library stop at 30 ads?

Logged out, the first page of a search holds 30 results, and the request the page sends for more answered "Rate limit exceeded" to every attempt we made, from a laptop, from Apify's datacenter proxies and from residential proxies. Reading further means asking different first pages, for example by moving the start-date filter back.

Does the Facebook Ad Library API return all ads?

No. Meta's Ad Library API returns ads about social issues, elections or politics worldwide, and other ads only when they reached the EU. It is reserved for authorized users with a Facebook account. The public website shows every active ad, wherever it runs.

Does the logged-out page show reach and spend?

Not for commercial ads. Reach, payer and beneficiary for EU ads sit behind Meta's EU transparency details, which the logged-out results do not include. Political ads with a "Paid for by" disclaimer carry the payer.

How long does Meta keep ads in the Ad Library?

According to Meta: active ads are visible while they run, ads delivered in the EU are kept for one year after their last impression, and ads about social issues, elections or politics for seven years.

Not affiliated with Meta, Google or Microsoft.