Ad library aggregation
Pull the ads a brand is running on Meta, LinkedIn and TikTok in one parallel fan-out and flatten them into one table. 150 to 270 credits per brand.
You will build a competitive-intelligence view of every ad a company is running on Meta (Facebook and Instagram), LinkedIn and TikTok, flattened into one table. Useful for sales-call prep, market research and creative benchmarking.
Cost per run
150 to 270 credits per brand: Meta ad search (50), LinkedIn ad search (50) and TikTok ad search (metered, 50–170). Auditing a 25-company competitive set costs 3,750 to 6,750 credits. Repeating the same search is charged again, so store the results.
How do you list every ad one advertiser has live?
Query each network's public ad library in parallel with the brand name. All three have a search endpoint that takes a name, and the three calls finish together.
Every major ad network publishes a transparency library, but each has its own interface, its own query model and its own response shape, and none of the official interfaces export data.
What you need
| Endpoint | Network | Parameters | Credits |
|---|---|---|---|
GET /v1/facebook/adlibrary/search/ads | Meta Ad Library | query, optional country, status, media_type, start_date, end_date | 50 |
GET /v1/linkedin/ads/search | LinkedIn Ad Library | company, keyword or companyId, optional countries, startDate, endDate | 50 |
GET /v1/tiktok/adlibrary/search | TikTok Ad Library | query or advertiser_name | 50–170 |
Three networks, three parameter names
Meta takes query. LinkedIn takes company (or keyword, or companyId) and spells its dates startDate and endDate. TikTok takes query or advertiser_name. A parameter an endpoint does not know is either ignored or rejected with a 400, which is not charged. Check each endpoint's parameters in GET /v1/endpoints before you generalise the call.
The code
TikTok's ad search returns ads as posts in the standard shape (data.items[].post). The Meta and LinkedIn ad searches are beta endpoints: data.items is a list of each network's own ad records, with our conventions applied (snake_case keys, string ids). The script reads the few fields an audit needs from each and flattens them into one row type: {network, id, advertiser, text, url}.
# ad_audit.py
# Pulls the ads a brand is running on three networks in parallel.
# Run with: INSIGHTSOCIAL_API_KEY=isk_live_... python ad_audit.py
import os
from collections import Counter
from concurrent.futures import ThreadPoolExecutor
import requests
KEY = os.environ["INSIGHTSOCIAL_API_KEY"]
BASE = "https://api.insightsocial.app/v1"
BRAND = "Duolingo"
def get(path, **params):
res = requests.get(f"{BASE}/{path}", params=params,
headers={"x-api-key": KEY}, timeout=120)
return res.json()
LEGS = {
"meta": ("facebook/adlibrary/search/ads", {"query": BRAND}),
"linkedin": ("linkedin/ads/search", {"company": BRAND}),
"tiktok": ("tiktok/adlibrary/search", {"advertiser_name": BRAND}),
}
with ThreadPoolExecutor(max_workers=3) as pool:
futures = {net: pool.submit(get, path, **params) for net, (path, params) in LEGS.items()}
results = {net: f.result() for net, f in futures.items()}
def flatten(network, item):
if network == "meta": # beta: Meta Ad Library records
snap = item.get("snapshot") or {}
return {"id": item.get("ad_archive_id"), "advertiser": item.get("page_name"),
"text": (snap.get("body") or {}).get("text"), "url": item.get("url")}
if network == "linkedin": # beta: LinkedIn Ad Library records
return {"id": item.get("id"), "advertiser": item.get("advertiser"),
"text": item.get("description"), "url": item.get("url")}
post = item["post"] # TikTok: the standard post shape
return {"id": post["id"], "advertiser": post["author"]["display_name"],
"text": post["content"]["text"], "url": post["url"]}
ads, spent = [], 0
for network, body in results.items():
spent += body.get("credits_used", 0)
if not body["success"]:
print(f"{network}: {body['error']['type']} (not charged)")
continue
for item in body["data"].get("items", []):
ads.append({"network": network, **flatten(network, item)})
print(f'{len(ads)} ads found for "{BRAND}"')
print(dict(Counter(row["network"] for row in ads)))
for row in ads[:5]:
print(f'[{row["network"]}] {row["advertiser"]}: {(row["text"] or "")[:80]}')
print(f"credits used: {spent}")What you get back
66 ads found for "Duolingo"
{'meta': 30, 'linkedin': 24, 'tiktok': 12}
[meta] Duolingo: Learn a language for free with fun lessons designed to keep you motivated!
[meta] Duolingo: ...
...
credits used: 150The figures are illustrative. The flattened row keeps only what the three networks share. The full records carry more: Meta ads the creative, images, running status (is_active) and the platforms they run on; LinkedIn ads the targeting, run dates and impression range; TikTok ads the creative, advertiser and first-shown date. On LinkedIn, advertiser is who paid for the ad; poster can be a person, when the brand promotes an employee's or a creator's post. Beta endpoints keep each network's structure and may change shape, so read their fields defensively, as the code does with .get().
What to change
- Widen the Meta leg.
GET /v1/facebook/adlibrary/search/companies(50) resolves a brand name to its advertiser pages and theirpageId.GET /v1/facebook/adlibrary/company/ads(50–350) then returns one page's full run, which is more precise than a keyword search.GET /v1/facebook/adlibrary/ad/transcript(100) returns what a video ad says out loud. - Read one ad in full.
GET /v1/facebook/adlibrary/ad,GET /v1/linkedin/adandGET /v1/tiktok/adlibrary/adare 50 credits each. - Richer TikTok rows.
include=adon the TikTok search adds the brand name, landing page and advertiser profile link to every row, underpost.ext.ad. - What actually performs.
GET /v1/tiktok/ads/top(100–1000) returns TikTok's leaderboard of top ads for a market and time window, with click-through rate and rank. Filter it withkeywordto see a category's best creative. - Scope by market and date. Add
countryandstart_date/end_dateon Meta, andcountriesandstartDate/endDateon LinkedIn. - Page deeper. All three return
pagination.next_cursor. Send it back ascursor, with the same parameters, to get the next page. See Pagination.
Related
Video transcription
One transcribe() function that returns the spoken words of a video on YouTube, TikTok, Instagram, Facebook, X, Reddit or LinkedIn. 30 credits on YouTube, 100 on the others.
Music trend detection
Score how fast a sound is spreading on TikTok and Instagram Reels with a log-weighted heat score you can track day over day. 20 credits per song.