General

Ad Library API: Search Meta, Google, LinkedIn, and TikTok Ads (2026)

Pull live competitor ads from four public ad libraries through one API: Meta Ad Library, Google Ads Transparency, LinkedIn Ad Library, and TikTok. Filters, response fields, and the resolve-then-fetch pattern.

Social FetchUpdated

Four platforms publish a public archive of the ads running on them: Meta, Google, LinkedIn, and TikTok. None of them require an ad account to read. All of them are awkward to read at scale: different URL structures, different filter vocabularies, different ideas of what an "advertiser" is, and no bulk export.

This guide covers all four through Social Fetch's /v1/**/ad-library/** routes: what each library exposes, the resolve-then-fetch pattern that most integrations get wrong, and how to turn the four into one competitor-tracking pipeline.

You'll need an API key and curl or the TypeScript SDK. New to the API? Start with the Quickstart.

Why four ad libraries exist

They are compliance artifacts, not developer products.

The EU Digital Services Act obliges very large platforms to keep a public repository of the ads they serve. Political-advertising rules in the US, EU, UK, Canada, and elsewhere add stricter disclosure (funder, spend, reach) for election and issue ads. Each platform shipped the minimum viable public interface that satisfies its obligations.

That origin explains almost every rough edge you will hit:

Coverage is uneven. Political ads get spend and impression ranges; commercial ads often get neither. Retention is uneven too, with political archives running for years while commercial creatives frequently disappear once they stop running.

The interface is the product. These are search pages built for journalists and regulators, not endpoints built for pipelines, and there is no "download all ads for this brand" button anywhere.

Nothing is normalized across them. Meta calls it a page, Google calls it an advertiser, LinkedIn calls it a company, and TikTok calls it an advertiser but splits results across two different surfaces.

The data is genuinely public and genuinely useful. Getting it into a table is the work.

What each library actually exposes

MetaGoogleLinkedInTikTok
Surfaces coveredFacebook, Instagram, Messenger, Audience NetworkSearch, YouTube, Shopping, Maps, PlayLinkedIn feed and message adsTikTok
Free-text keyword searchYes (required)No, advertiser or domain onlyYes (keyword)Yes (Top Ads only)
Impressions disclosedPolitical and issue ads onlyNoYes: banded, plus per-country shareRelative metrics only
Spend disclosedPolitical and issue ads onlyNoNoNo
Targeting disclosedPolitical and issue ads onlyNoOften: language, included and excluded locationsNo
Creative mediaImage, video, memeText, image, videoImage, video, carousel, documentVideo
Date filteringstartDate / endDatestartDate / endDatestartDate / endDateperiod (7/30/180 days)
Political-ad filteradType=political-and-issuetopic=political (needs region)NoneNone

The practical read: LinkedIn is the richest for B2B competitive work, because it is the only one that routinely hands you an impressions band and a country-level split on ordinary commercial ads. Meta is the broadest for consumer brands. Google is the only one that tells you which Google surface an ad ran on. TikTok is the only one that ranks creatives by performance.

Resolve the advertiser before you fetch ads

This is the step that breaks naive integrations, and it is worth doing once properly.

Every one of these libraries matches company names by fuzzy substring, not by entity. Search a brand and you get everything containing that string. Here is a real Google Ads Transparency advertiser search:

Request
bash
Request
json

Ten advertisers, one of which is the company you meant. Notion Labs, Inc with adsEstimate: 200 is the real one; Hit Notion, LLC with 93 ads is a different business entirely. A pipeline that searches by name on every run will silently blend them.

Resolve once, then query by id

Run the name search a single time, have a human confirm the match, and store the stable id: advertiserId on Google, pageId on Meta, companyId on LinkedIn. Every subsequent call should use the id. Name-based lookups are for discovery, not for scheduled jobs.

The same trap exists on LinkedIn. Searching company=Notion returns ads from both Notion (company 30898036) and an unrelated agency called Epic Notion (company 2076480). The advertiser.pageUrl field on each ad carries the company id, so you can resolve it from a first search and pin it thereafter.

Google's response also hands you a websites array. When two advertisers share a name, the domain is usually the fastest disambiguator: notion.so belongs to the company you want, epicnotion.com does not.

Meta (Facebook and Instagram) Ad Library

Meta's library covers Facebook, Instagram, Messenger, and Audience Network. Keyword search is the primary entry point and query is required.

Request
bash

Useful parameters:

  • searchType: keyword-unordered (default behaviour, words in any order) or exact-phrase. Use exact-phrase when you are tracking a specific claim or slogan.
  • adType: all, or political-and-issue to restrict to the disclosure-heavy subset that carries spend and impression ranges.
  • status: active, inactive, or all. Active-only is what you want for "what are they running right now".
  • mediaType: image, video, meme, image-and-meme, or none.
  • country: a country code, or ALL to search every country at once.
  • trim: returns a smaller payload with fewer fields.

To follow one brand rather than a keyword, resolve the page first and then list its ads:

Request
bash

Single-ad detail lives at GET /v1/facebook/ad-library/ads by adId or public url. It accepts includeTranscript=true, which returns plain text for video creatives, useful when you want to analyse messaging rather than eyeball thumbnails.

Meta's own API is narrower than it looks

Meta publishes an official Ad Library API, but it needs an approved app, and identity verification for political ads. For non-political ads its search is largely limited to the EU. The public library pages themselves are worldwide. That gap is why most teams read the public surface instead.

Google has no free-text creative search. You cannot ask "which ads mention pricing"; you can only ask "what is this advertiser running". So resolution is mandatory, not optional.

Request
bash

The platform filter is what makes Google worth pulling. It splits an advertiser's spend across google_search, youtube, google_shopping, google_maps, and google_play. Running the same query five times, once per surface, gives you a rough channel-mix picture that no other library offers: whether a competitor is a search-first advertiser who dabbles in YouTube, or the reverse.

format narrows to text, image, or video. topic=political restricts to election and issue ads, and requires region to be set.

Single creatives resolve by their public Ad Transparency URL at GET /v1/google/ad-library/ads.

LinkedIn Ad Library

For B2B competitive research this is the highest-value library of the four, because LinkedIn discloses reach and targeting on ordinary commercial ads.

Request
bash

Search by company name, companyId (preferred, see above), or keyword for free-text across ad copy. countries takes a comma-separated list. A trimmed real response:

Request
json

Three fields there are hard to get anywhere else:

  1. impressions.total: a banded reach figure (20k-30k, 50k-100k) on a normal commercial ad.
  2. impressions.byCountry: where those impressions actually landed, as percentage shares. The ad above is nominally targeted at several regions but 85% of delivery is Spanish-speaking Latin America and Spain. That is a market-priority signal you will not find in a press release.
  3. targeting: the advertiser's own selections, sometimes including exclusions.

adType is also worth storing: Single Image Ad, Video Ad, Carousel Ad, Document Ad, and Message Ad are meaningfully different plays. A jump in Document Ads usually means a new gated asset and a lead-gen push.

Note that impressions and duration are populated on some ads and null on others. LinkedIn only discloses them once an ad has finished or crossed a reporting threshold. Branch on null rather than assuming presence.

TikTok — Top Ads vs the Ads Library

TikTok is the one that surprises people, because GET /v1/tiktok/ad-library/ads/search fronts two different data sources depending on which parameter you set.

Set advertiserName and you query the public Ads Library: the compliance surface, comparable to the other three:

Request
bash

Omit it and you query Top Ads: TikTok's curated collection of high-performing creatives, which is a creative-research tool rather than a transparency archive:

Request
bash

Top Ads filters have no equivalent on the other platforms:

  • orderBy: ctr, cvr, impression, like, play-2s-rate, play-6s-rate, or for-you. Sorting by play-6s-rate surfaces creatives that hold attention past the scroll-away point.
  • industry: 21 verticals from beauty-personal-care to financial-services.
  • objective: conversions, lead-generation, app-installs, traffic, reach, product-sales, video-views.
  • adFormat: spark-ads (boosted from an organic post) versus non-spark-ads (uploaded as pure ad creative). The ratio tells you whether a category leans on creator partnerships.
  • duration, likes, adLanguage, period (7, 30, or 180 days).

Use Top Ads to answer "what creative patterns work in this vertical right now". Use advertiserName to answer "what is this specific company running". They are not interchangeable, and mixing them in one table will produce nonsense.

Building competitor ad tracking

The four libraries share an envelope, so one worker handles all of them. The shape that works:

Request
typescript

Four rules that matter more than the fetching code:

Dedupe on the platform ad id, never on the creative. The same creative is republished under new ids constantly: the LinkedIn response above contains four separate ids for one "AI Can't Replace Teamwork" video, each a different delivery variant. Counting creatives instead of ids will make a single campaign look like a blitz.

Store first_seen and last_seen yourself. Retention is a rolling window on every platform. An ad that vanishes from the library has stopped running, but you only know that if you recorded it while it was there. This is the single highest-value thing your pipeline does, because it turns four ephemeral search pages into a real time series.

Snapshot, do not overwrite. impressions.total moves as an ad accumulates delivery. Append rows rather than updating in place, or you lose the growth curve.

Fan out, then merge. Run the four platforms in parallel and normalize into one row shape: platform, ad_id, advertiser_id, ad_type, body_text, media_url, started_at, ended_at, impressions_band, first_seen, last_seen. The per-platform extras go in a JSON column.

For scheduled runs, monitors and webhooks will push changes to you instead of you polling on a cron.

The weekly report this makes possible

Weekly, per competitor: new creatives launched, creatives retired, share of Document or lead-gen formats, and country mix shift from LinkedIn's byCountry split. That last one is often the earliest public signal that a competitor is opening a new market, usually weeks before an announcement.

What ad libraries will not tell you

Being straight about the ceiling here saves you from over-promising internally.

  • No spend, outside political ads. Meta discloses spend ranges for political and issue advertising. For everything else, nobody publishes budget. Anyone selling you competitor ad spend is modelling an estimate, not reading a number.
  • No conversions, and no funnel. You see creative and, on LinkedIn, banded reach. Whether it worked is invisible.
  • No guaranteed completeness. Libraries omit ads under review, some formats, and some regions. Absence is not proof an advertiser is dark.
  • Impressions are bands, not counts. 50k-100k is the disclosure. Do not average the band and present it as a figure.
  • Targeting text is prose, not structure. LinkedIn's targeting.location is a human-readable string with truncation ("and 3 others"). Parse it defensively.
  • Ads disappear. Retention differs by platform and ad type. Your own store is the archive.

None of that undercuts the use case. Creative, cadence, format mix, market focus, and messaging shifts are all readable, and all genuinely hard for a competitor to hide.

FAQ

Do I need an ad account to use an ad library API?

No. All four libraries are public transparency surfaces, published because of regulation such as the EU Digital Services Act and various political-advertising rules. You are reading disclosure pages any logged-out visitor can open, not your own campaign reporting. You never touch Meta Ads Manager, Google Ads, or LinkedIn Campaign Manager.

Is this the same as Meta's official Ad Library API?

Meta's own Ad Library API requires an approved developer app and, for political and issue ads, identity verification, and it limits most non-political ad search to the EU. Social Fetch reads the same public library pages and returns them as JSON under /v1/facebook/ad-library/**, with no app review. The underlying data is Meta's; the access path is different.

Which ad library gives the most useful targeting data?

LinkedIn. Its detail pages disclose an impressions band (for example 50k-100k) plus a per-country impression share breakdown, and often the targeting the advertiser selected: language, locations included and excluded. Meta discloses impressions and spend ranges mainly for political and issue ads. Google gives you format, surface, and date range but no impression counts.

Can I search all four ad libraries with one query?

Not in a single request: each platform has its own route and its own filter vocabulary. What is shared is the auth header, the data + meta envelope, and cursor pagination, so one client and one set of response-handling code covers all four. Fan out four calls in parallel and merge on your side.

How far back does ad library data go?

It varies by platform and ad type, and none of them promise a complete archive. Meta keeps political and issue ads for seven years and commercial ads only while they are active or recently inactive. Google and LinkedIn expose roughly the last year for most commercial creatives. Treat every library as a rolling window. If you need history, store what you pull.

Why does searching a brand name return other companies?

Because name search is fuzzy substring matching, not entity resolution. Searching Notion in Google Ads Transparency returns Notion Labs, Inc alongside Epic Notion, Quiet Notion, and Hit Notion, LLC. Always resolve to a stable id (advertiserId, pageId, or companyId) once, store it, then query by id afterwards. See Resolve the advertiser before you fetch ads.

How are ad library lookups billed?

Per completed lookup, like every other route. Read meta.creditsCharged on each response rather than assuming a fixed number, and reconcile against it in your pipeline. Search routes that return a page of results are metered separately from single-ad detail fetches. Check the operation page before you wire a loop.

These are public transparency archives that platforms are required to publish, which puts them on firmer ground than most public-web collection. You remain responsible for each platform's terms, applicable privacy law, and your own contracts. Ad creatives are copyrighted works, so republishing them is a different question from analysing them. This is a technical guide, not legal advice.

How does this compare to other providers?

See the side-by-side comparisons: vs Apify, vs Bright Data, vs ScrapeCreators, and the full compare hub.


Next steps: Facebook ad search · Google advertiser search · LinkedIn ad search · TikTok ad search · Quickstart · Pricing