Meta Ad Library: GET /v1/meta/ads
Search Facebook, Instagram, Messenger, Audience Network and Threads ads in the Meta Ad Library by keyword or by advertiser, with Meta's own filters: country, active status, media, placements, category, language and sort.
next_cursor for more.q or page_id.Request
curl "https://api.publicadsapi.com/v1/meta/ads?q=running+shoes&country=GB" \ -H "authorization: Bearer $PADS_API_KEY"
Parameters
Every filter here is the library's own, run by the platform, so pages are full and total_estimate counts what matches. Anything else is 400 INVALID_INPUT naming it.
Bearer <key>. Keys starting pads_test_ get the sandbox (sample ads, never charged); keys starting pads_live_ read the platform and use credits.query or keyword.q=running shoesadvertiser.id of any of its Meta ads.page_id=100000000000001true matches q as a whole phrase. Default false.GB, US or DE, or ALL. Two letters that are no country (ZZ) are refused. Default ALL. Also accepted as country_code.country=GBtrue: only ads running now. false: only ads that have stopped. Left out: both.none is ads with no image or video. Left out: every format. One of: image, video, meme, none. Also accepted as media_type.facebook, instagram, messenger, audience_network, threads.placements=facebook,instagrampolitical_and_issue ads carry spend and impressions ranges. One of: all, political_and_issue, housing, employment, financial. Default all.en. Left out: every language.language=enimpressions: most seen first, as Meta ranks them. newest: most recently started first. One of: impressions, newest. Default impressions.YYYY-MM-DD.date_from=2026-01-01YYYY-MM-DD. Not before date_from.date_to=2026-10-21next_cursor of the page before. Send it with exactly the same other parameters: a cursor from a different search is 400 INVALID_INPUT.raw adds each ad's own record from the platform as raw, for fields we don't map. Values: raw.include=rawResponse
{
"platform": "meta",
"query": {
"q": "running shoes",
"page_id": null,
"exact": false,
"country": "GB",
"active": null,
"format": null,
"placements": null,
"category": "all",
"language": null,
"sort": "impressions",
"date_from": null,
"date_to": null
},
"ads": [
{
"id": "meta_900000000000001",
"platform": "meta",
"platform_ad_id": "900000000000001",
"library_url": "https://www.facebook.com/ads/library/?id=900000000000001",
"advertiser": {
"id": "100000000000001",
"name": "Northwind Running Co",
"domain": null,
"library_url": "https://www.facebook.com/ads/library/?view_all_page_id=100000000000001"
},
"status": "active",
"first_shown": "2026-08-04T07:00:00Z",
"last_shown": "2026-10-18T07:00:00Z",
"format": "image",
"text": {
"headline": "Trail shoes, half price this week",
"body": "Grip that holds on wet rock. Free returns for 60 days.",
"description": null,
"cta": "Shop now"
},
"text_source": "platform",
"link_url": "https://northwind-running.example/trail",
"media": [
{
"type": "image",
"url": "https://example.com/sandbox-media/meta-trail.jpg",
"preview_url": null,
"width": 1080,
"height": 1080
}
],
"placements": [
"facebook",
"instagram",
"audience_network",
"messenger"
],
"regions": null,
"metrics": {
"impressions": null,
"reach": null,
"spend": null
},
"variants": 1
}
],
"total_estimate": 5,
"has_more": true,
"next_cursor": "eyJwIjoibWV0YSIsImMiOiIzIiwicSI6IldZZVBvV0xGd1Bkei1OejUifQ",
"credits_used": 0,
"credits_remaining": null
}What Meta ads carry
advertiser.idis the Facebook page id: pass it aspage_idfor every ad that page runs.statusisactiveorinactive.first_shownandlast_shownare the days Meta says the ad started and stopped (the latest day seen, for an ad still running).format:image,video,carousel,dynamic(catalogue ads) ortext.placementslists where it ran.variantsis how many versions of the ad Meta groups under it.metrics(spend, impressions and reach ranges) is filled only for political and issue ads; for others it isnull. The EU's reach figures for any ad delivered in the EU are in its detail.total_estimateis Meta's own count, which Meta caps at 50,000.
Limits to know
- Meta keeps ads that ran in the EU or UK for a year after they stop, political and issue ads for seven years, and other ads (in the US, for example) only while they run. Outside the EU and UK,
active=falsefinds political and issue ads only. - The first page is the quickest. Later pages are fetched by scrolling Meta's page, so each takes longer than the first; a pull of a few hundred ads takes about a minute in all.
- An empty page is checked against a search that always has ads before we answer, so a silent block by Meta is never passed off as "no ads".
- Media addresses are Meta's and expire within days: download what you keep.
One ad with its detail
GET /v1/ads/{id} with an id from this search (1 credit). For an ad delivered in the EU: the total EU reach, reach by country, age and gender, the ages, genders and places targeted, and who paid and who benefited (the EU's Digital Services Act data). For a political or issue ad: spend and impressions. For other ads, in the US for example: the ad itself, with no reach or targeting. See One ad.