API reference

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.

Ads a pageup to 30One page per call; next_cursor for more.
Credits1 credit a pageOnly when the page has ads. Empty pages, errors and the sandbox are free.
CoversEvery country Meta runs ads inSearch by 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.

Authorizationstringheaderrequired
Bearer <key>. Keys starting pads_test_ get the sandbox (sample ads, never charged); keys starting pads_live_ read the platform and use credits.
qstringquerysend one of q, page_id
A keyword, matched against the ad's text as Meta's own search box does. Also accepted as query or keyword.
Example: q=running shoes
page_idstringquerysend one of q, page_id
One advertiser's ads: its Facebook page id, the advertiser.id of any of its Meta ads.
Example: page_id=100000000000001
exactbooleanquery
true matches q as a whole phrase. Default false.
countrystringquery
Where the ad was shown: an ISO 3166-1 alpha-2 code such as GB, US or DE, or ALL. Two letters that are no country (ZZ) are refused. Default ALL. Also accepted as country_code.
Example: country=GB
activebooleanquery
true: only ads running now. false: only ads that have stopped. Left out: both.
formatstringquery
Meta's media filter. none is ads with no image or video. Left out: every format. One of: image, video, meme, none. Also accepted as media_type.
placementscomma-separatedquery
Comma-separated: ads that ran on any of these. Left out: every placement. Values: facebook, instagram, messenger, audience_network, threads.
Example: placements=facebook,instagram
categorystringquery
Meta's ad category. political_and_issue ads carry spend and impressions ranges. One of: all, political_and_issue, housing, employment, financial. Default all.
languagestringquery
The ad's language, ISO 639-1 such as en. Left out: every language.
Example: language=en
sortstringquery
impressions: most seen first, as Meta ranks them. newest: most recently started first. One of: impressions, newest. Default impressions.
date_fromYYYY-MM-DDquery
Ads shown on or after this day, YYYY-MM-DD.
Example: date_from=2026-01-01
date_toYYYY-MM-DDquery
Ads shown on or before this day, YYYY-MM-DD. Not before date_from.
Example: date_to=2026-10-21
cursorstringquery
The next_cursor of the page before. Send it with exactly the same other parameters: a cursor from a different search is 400 INVALID_INPUT.
includecomma-separatedquery
raw adds each ad's own record from the platform as raw, for fields we don't map. Values: raw.
Example: include=raw

Response

200 OK (sandbox; the first ad of the page)
{
  "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.id is the Facebook page id: pass it as page_id for every ad that page runs.
  • status is active or inactive. first_shown and last_shown are 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) or text. placements lists where it ran.
  • variants is 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 is null. The EU's reach figures for any ad delivered in the EU are in its detail.
  • total_estimate is 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=false finds 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.