Ad Library
Search Meta's public ad archive: what your competitors are running, with the customer's own token
Ad Library
GET /v1/ads/library searches Meta's public Ad Library (/ads_archive) with the token of a connected facebook, instagram or metaads account. No extra scope, no reconnect: the same Facebook Login token that runs ads can read the archive.
An Instagram account connected through Instagram Login has no Facebook Login token, so it cannot search on its own. Passing one returns 422 linked_account_required; connect a Facebook Page or Meta Ads account on the same profile and pass that accountId instead.
Rows come back in Meta's raw ArchivedAd shape under data, and paging.after is Meta's cursor (null on the last page).
const { data } = await zernio.adlibrary.searchAdLibrary({
query: {
accountId: 'ACCOUNT_ID',
q: 'espresso machine',
countries: 'ES,FR',
status: 'ACTIVE',
platforms: 'INSTAGRAM',
limit: 25,
},
});
for (const ad of data.data) {
console.log(ad.page_name, ad.ad_creative_bodies?.[0], ad.ad_snapshot_url);
}page = client.ad_library.search_ad_library(
account_id="ACCOUNT_ID",
q="espresso machine",
countries="ES,FR",
status="ACTIVE",
platforms="INSTAGRAM",
limit=25,
)
for ad in page.data:
print(ad.page_name, ad.ad_creative_bodies[0], ad.ad_snapshot_url)curl "https://zernio.com/api/v1/ads/library?accountId=ACCOUNT_ID&q=espresso%20machine&countries=ES,FR&status=ACTIVE&platforms=INSTAGRAM&limit=25" \
-H "Authorization: Bearer YOUR_API_KEY"What is in the archive
Meta's coverage is the part to set expectations on before you build a "competitor ads" screen:
| Ads | Searchable |
|---|---|
| Political and social-issue ads | Worldwide, seven years back |
| Every other ad | Only if it was delivered to the EU or UK, for one year after it ran |
A US-only commercial advertiser is therefore invisible, no matter what you pass in countries. EU and UK ads carry the DSA transparency fields (eu_total_reach, beneficiary_payers, target_ages, target_gender, target_locations, age_country_gender_reach_breakdown, total_reach_by_location).
spend, impressions, demographic_distribution, delivery_by_region, estimated_audience_size, bylines and currency exist only on political ads. They are left out of the default projection; add them with fields when you search with adType=POLITICAL_AND_ISSUE_ADS.
Identity confirmation
Meta serves the archive only to people who confirmed their identity and location at facebook.com/ID, the same check it requires to run political ads. It is a property of the Facebook user behind the connection, not of the token or the app, and it takes Meta a few days to approve.
Until that user has completed it, every search fails with:
{
"error": "Meta only serves the Ad Library to people who confirmed their identity and location. The Facebook account behind this connection must complete https://www.facebook.com/ID, then retry.",
"type": "permission_error",
"code": "meta_identity_confirmation_required",
"platform": "meta"
}Surface that message to the account owner as a one-time setup step. Nothing on the Zernio side can bypass it, and reconnecting the account does not help.
Searching
| Param | Notes |
|---|---|
q | Keyword. Meta does not translate it, so write it in the language of the ads you want. searchType=KEYWORD_EXACT_PHRASE matches a phrase instead of the words in any order. |
pageIds | Up to 10 Facebook Page ids, comma-separated. Use it instead of q to list everything one advertiser runs. |
countries | ISO alpha-2 codes the ads reached, comma-separated. Defaults to ALL. |
adType | ALL (default), POLITICAL_AND_ISSUE_ADS, HOUSING_ADS, EMPLOYMENT_ADS, FINANCIAL_PRODUCTS_AND_SERVICES_ADS. |
status | ACTIVE (default, eligible for delivery right now), INACTIVE, ALL. |
platforms | FACEBOOK, INSTAGRAM, AUDIENCE_NETWORK, MESSENGER, WHATSAPP, OCULUS, THREADS, STREAMING_SERVICES. |
mediaType | IMAGE, VIDEO, MEME, NONE, ALL. |
languages | ISO 639-1 codes of the ad text. |
since / until | Delivery date window, YYYY-MM-DD. |
fields | Raw Graph projection override. |
limit / after | Up to 100 rows per page; pass paging.after back for the next one. |
ad_snapshot_url renders the full creative (uncompressed image or video) and needs the same access token appended, so open it server-side or proxy it. Meta's terms allow downloading an individual ad's creative for analysis only.
Rate limits
Meta meters the Ad Library API per token, so each customer's searches count against their own budget. A 429 from Zernio means Meta asked that account to slow down; retry after a minute.