For AI

How-to guides

How to search the Meta Ad Library and follow an advertiser

Three endpoints, in this order: Meta Ad Library search to find ads by keyword, Meta advertiser ads to list what one Facebook page runs, and Meta Ad Library ad detail to re-check single ads later. The worked example is 7 calls and costs $0.028; a failed call is not charged.

Updated

The job: you are entering a product category and want to see how the brands already in it advertise on Facebook and Instagram. Which hooks do they use, which offers, which landing pages, and how long do their ads keep running? Search the library by keyword to see who advertises, open the most active advertiser's full list, and save a shortlist of ads to check again later. You end with three tables: ads for the keyword, one advertiser's ads, and the status of your shortlist a week on.

No Meta developer app, access token or Facebook login is involved. Each call is an HTTPS request with your key.

Step by step

Step 1: search ads by keyword

Call Meta Ad Library search with query. Four filters narrow it:

  • country: an ISO code such as US or DE; all countries when left out.
  • status: active (the default, ads running now), inactive (stopped ads) or all.
  • media: all (the default), image or video.
  • sort: impressions (the default, most impressions first) or newest.

One call returns up to 30 ads for $0.004. Each ad has id (the library ID), url, advertiser (the Facebook page's id, name and url), title, the copy in text, format (image, video, carousel, text or dynamic), images, videos, landing_url, cta, platforms (such as facebook and instagram), active and first_shown_at.

curl -G "https://api.okdata.online/v1/meta/ads/search" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'query=electrolyte powder' \
  -d country=US -d status=active -d media=video -d sort=impressions

For the second page, send page.next_cursor back as cursor, unchanged. Then count the rows by advertiser.id to see who spends the most attention on the keyword.

Step 2: list one advertiser's ads

Pass the page ID from step 1 to Meta advertiser ads as id, or the brand's name as it appears on its Facebook page as name. Give one, not both; both or neither is invalid_params, which is not charged. The same country, status, media and sort filters apply, and each page holds up to 30 ads for $0.004.

curl -G "https://api.okdata.online/v1/meta/advertisers/ads/list" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  -d id=107364829105372 -d country=US -d status=active -d sort=newest

sort=newest puts the ads the brand launched most recently on top, which is what you want for a weekly look. The ID is safer than the name: several pages can share a name, and the ID points at exactly one.

Step 3: re-check single ads

Meta Ad Library ad detail takes a library id or the ad's link as url and returns one ad for $0.004, with active, first_shown_at and last_shown_at. Save the IDs of the ads you shortlist; a week later, three detail calls tell you which of them still run and for how long they have run. An ad that has been running for months is usually one that works.

curl -G "https://api.okdata.online/v1/meta/ads/get" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  -d id=1290374658821904 \
  -d fields=id,active,first_shown_at,last_shown_at,landing_url

Step 4: in Python

import collections
import os
import requests

API = "https://api.okdata.online"
HEADERS = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}


def pages(path, n, **params):
    cursor = None
    for _ in range(n):
        body = requests.get(API + path, headers=HEADERS, params={**params, **({"cursor": cursor} if cursor else {})}, timeout=60).json()
        if body["code"] != "ok":
            raise RuntimeError(f"{body['code']}: {body['message']} (charged: {body['charged']})")
        yield from body["data"]["items"]
        if not body["page"]["has_more"]:
            return
        cursor = body["page"]["next_cursor"]


ads = list(pages("/v1/meta/ads/search", 2, query="electrolyte powder", country="US", status="active", media="video"))
top_page = collections.Counter(a["advertiser"]["id"] for a in ads if a["advertiser"]["id"]).most_common(1)[0][0]
for a in pages("/v1/meta/advertisers/ads/list", 2, id=top_page, country="US", status="active", sort="newest"):
    print(a["first_shown_at"], a["format"], a["landing_url"], (a["text"] or "")[:80])

Good to know

  • What Meta's own API returns. Meta's Ads Archive reference says ads that did not reach any location in the EU only come back if they are about social issues, elections or politics. For political ad research, or EU ads with Meta's own breakdowns, its API is the right tool. The endpoints here read the public library pages, so ordinary commercial ads in the US or Asia come back too.
  • Spend and reach. The library publishes no spend or reach for commercial ads outside the EU, so reach is null there. For EU-delivered ads it carries Meta's EU reach figure.
  • Stopped ads. status=inactive returns only the stopped ads the public library still shows, and for commercial ads outside the EU that is often few. If you want a brand's history, save each week's rows yourself.
  • Dynamic ads. Catalog ads assembled per viewer have format set to dynamic and often no copy, because the library shows a template instead of text.
  • Extras. view=full adds ext.variants (how many versions of the ad the library groups together), ext.page_likes, ext.categories and, for EU ads, ext.eu_payer and ext.eu_beneficiary.
  • Save creatives you keep. Image and video links point at Meta's servers and can expire.
  • Retries without paying twice. Send an Idempotency-Key header with each call; the same request with the same key within 24 hours returns the stored answer and no new charge.

For what the official API costs and requires, see the Meta Ad Library API answer. To track one competitor on Meta, Google and TikTok together, see competitor ads on three libraries.

What the example costs

Two pages of active US video ads for electrolyte powder, two pages of one advertiser's active ads, then three shortlisted ads checked again a week later

EndpointCallsPriceSubtotal
Meta Ad Library search2$0.004$0.008
Meta advertiser ads2$0.004$0.008
Meta Ad Library ad detail3$0.004$0.012
Total7$0.028

Prices in force when this page was built. A failed call costs nothing.

In your AI (MCP)

Connect the MCP server once, then say what you want. The agent finds these endpoints, reads their prices and calls them on your balance.

SaySearch the Meta Ad Library for active video ads about electrolyte powder shown in the US, most impressions first, two pages. Tell me which advertisers appear most, then list two pages of active ads from the top one with copy, landing page and start date.

What the agent sends to the call tool first
{
  "endpoint": "meta.ads.search",
  "params": {
    "query": "portable espresso"
  },
  "idempotency_key": "<a new UUID>"
}

Set up the MCP server →

Sources

  1. Meta Graph API reference: Ads Archivedevelopers.facebook.com · read

Connect once, then just ask.

Every new key comes with $0.10 to try it. One sentence connects your agent.

Start free
Connect your AI

Paste this into your agent

Read https://okdata.online/agents.md and set up okdata for me; my key is in the OKDATA_API_KEY environment variable.

Claude Code, Cursor, Codex and other agents that can open a link set themselves up from it.

MCP serverhttps://api.okdata.online/mcp