Facebook Ad Library API: which ads you get, which you don't
Meta's API returns political ads from everywhere and every kind of ad shown in the UK or the EU. An ad shown only in the US for running shoes is not in it. What each way into the Ad Library gives you, and how to keep the ads the API leaves out.
Meta keeps the ads running on Facebook, Instagram and its other apps in a public Ad Library. There are three ways in: the Ad Library website, the Ad Library report and the Ad Library API. They do not hold the same ads, and the difference decides which one you can use.
We read all three on 25 October 2026. What follows comes from Meta's own pages that day and from searches we ran on the website.
The short version#
- Website: every ad running now. You need a browser. No export.
- Report: political and issue ads since 2019. You need a browser. A download.
- API: political and issue ads, and any ad shown in the UK or the EU. You need an ID check, an app and a token. JSON.
What the API leaves out#
Meta's API page lists two kinds of ads the API searches: ads about social issues, elections or politics delivered anywhere in the world in the past seven years, and ads of any type delivered to the UK or the European Union in the past year. For every ad running now, the same page sends you back to the Ad Library website.
So an ordinary commercial ad that only ran in the US, a shoe brand selling running shoes for example, is not in the API. It is on the website: a search there for "running shoes", country United States, active ads only, said "~45,000 results".
The report does not close the gap either. Its page offers to explore, filter and download data for ads about social issues, elections or politics.
What the API gives you#
When the ad is in it, the API is the cleanest source. Each ad comes as an ArchivedAd with id, page_id, page_name, ad_creation_time, ad_delivery_start_time, ad_delivery_stop_time, ad_creative_bodies, ad_creative_link_titles, ad_creative_link_descriptions, ad_creative_link_captions, ad_snapshot_url, publisher_platforms and languages.
The numbers depend on the kind of ad:
- Political and issue ads add
spend,impressionsandcurrency(as ranges),demographic_distribution,delivery_by_region,estimated_audience_sizeandbylines. - UK and EU ads add
eu_total_reach,age_country_gender_reach_breakdownand the targeting fieldstarget_ages,target_genderandtarget_locations.beneficiary_payersis for EU ads. - Other ads come with no spend or reach numbers in the API.
Getting a key takes three steps on Meta's page. You confirm your identity and location at facebook.com/ID, the same check Meta asks of political advertisers, and it can take a few days. Then you create a Meta for Developers account, agreeing to the Platform Policy, and add an app. The app gives you the access token.
The request has this shape. We did not run it, because it needs your token. The field names are from Meta's reference.
curl -G "https://graph.facebook.com/v26.0/ads_archive" \
--data-urlencode 'search_terms=running shoes' \
--data-urlencode 'ad_reached_countries=["DE"]' \
--data-urlencode 'ad_type=ALL' \
--data-urlencode 'fields=id,page_name,ad_delivery_start_time,ad_creative_bodies,ad_snapshot_url,eu_total_reach' \
--data-urlencode "access_token=$META_TOKEN"search_terms takes up to 100 characters, and search_page_ids takes up to 10 Page IDs in one request.
The website, and the catch with its pictures and videos#
The website needs nothing and shows everything that is running. You can filter by country, active or stopped, ad category, media type and dates, and every search is a link you can keep:
https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=running%20shoes&search_type=keyword_unorderedAn advertiser's ads are the same kind of link with view_all_page_id= and the Page ID.
The website has no export. It shows about 30 ads at first and loads more as you scroll.
The images and videos have a catch. Their links on fbcdn.net carry their own expiry time. The oe= part of the link is a Unix time written in hex. On the links we read on 25 October it pointed four days ahead:
from datetime import datetime, timezone
from urllib.parse import parse_qs, urlparse
def expires(url):
"""Meta's media links carry their own expiry time: oe= is a Unix time written in hex."""
oe = parse_qs(urlparse(url).query).get("oe")
return datetime.fromtimestamp(int(oe[0], 16), timezone.utc) if oe else Noneexpires("https://video-man2-1.xx.fbcdn.net/o1/v/t2/f2/m69/file.mp4?...&oe=6AE3B70D")
# datetime(2026, 10, 29, 21, 13, 49, tzinfo=timezone.utc)So a list of ad video links is a list that goes stale within days. If you want the creatives, save the files the same week, not just the links.
Every running ad, as rows you can export#
That is the job of our Facebook Ad Library Scraper on Apify. It reads the public Ad Library website, so it has every running ad, not only the political or European ones. No login and no Meta account are needed. You give it search words, advertiser Page IDs or Ad Library links you copied from the browser, with a country, a status, a category and a media type:
{
"searchTerms": ["running shoes"],
"country": "US",
"activeStatus": "active",
"mediaType": "video",
"maxAdsPerSearch": 100,
"maxItems": 100
}One thing to know first. The robots.txt of facebook.com closes the whole site to any crawler it does not name, the Ad Library included. Reading the public Ad Library is one of two exceptions we made to our own robots.txt rule, and it is kept narrow: Ad Library pages only, an ordinary browser, no login, no captcha solving, and the run stops at the first block. The scrapers page says where it ends.
Each ad comes back as one row: the advertiser and its Page, start and end dates, platforms, ad text, headline, button, landing page, format, image and video links, how many versions of the ad run (collationCount), and the spend, impressions and reach ranges where Meta publishes them. A run takes up to 25 searches and up to 1,000 ads a search, and you can export it as JSON, CSV or Excel or schedule it.
To keep the pictures and videos before their links run out, give the imageUrls and videoUrls to our Bulk File and Image Downloader. It stores each file with a link you can open, plus its type, size and a SHA-256 checksum, and duplicates are not charged.
Both are billed per result. The scraper is not affiliated with Meta, and it reads only what the Ad Library shows anyone who opens it.
written
6 min readFree exchange rate API with no key: ECB rates in Python
The European Central Bank publishes its daily euro rates as plain files: no key, no sign-up. What is in them, the three things that trip people up (weekends, holidays, retired currencies) and about forty lines of Python that handle all three.
6 min readWebsite to LLM text: a site into clean pages with Python
For search over your docs or a chat with a site, a model needs the words of each page, not its menus. About seventy lines of standard-library Python do it for a small site. We ran them on this one: 46 pages, 33,009 words, 132 chunks.
7 min readGreenhouse, Lever, Ashby and Workday job board APIs
Four hiring systems publish their open jobs as JSON you can read without a key. What each answer holds, the catch in each one, and about forty lines of Python that put all four into one shape.