TikTok Ad Library
GET /v1/ad-library/tiktok/top-ads

TikTok Creative Center Top Ads API

TikTok Creative Center Top Ads — one ~20-row leaderboard page, not a library search (flat 2 / ~1 Apify).

2 credits per request
TL;DR
TikTok Creative Center Top Ads — one ~20-row leaderboard page, not a library search (flat 2 / ~1 Apify). The TikTok Creative Center Top Ads API (TikTok Ad Library) is a single authenticated GET request to /v1/ad-library/tiktok/top-ads that responds with clean JSON and costs 2 credits. Pass cache=true for a free 24h cache hit; default is always fresh. Start with 100 free credits — no credit card.

What is the TikTok Creative Center Top Ads API?

q filters the top-N Creative Center leaderboard; it is not a library search. To find a known advertiser's ads, use /v1/ad-library/tiktok/ad-details by ad id. Pull high-performing auction ads from one signed top_ads/v2/list page (~20 rows) as clean JSON: id, url (per-ad detail page), title, brandName (= advertiser.name when present), advertiser{id,name}, likes + likesIsApproximate, ctr, costTier when present, resolved industry/industryKey, objective, and video{} (urlHd only when a distinct HD rendition exists). limit (default 20, max 20) only trims that page — it cannot grow the pool. Creative Center does not expose ad run dates on the list surface — use /tiktok/ad-details (DSA) for firstShown/lastShown (search omits them). Optional ctrTier/isSparkAd appear only when upstream ships them (never null-padded). Keyword q is case-insensitive whole-word match=any|all on title/brandName/industry/objective (hair ≠ wheelchair). There is no tags field. advertiser.name is often null in the default US market, so brand search cannot match there. Each hit includes matchedFrom (field names that matched) and the envelope reports candidatesScanned/filteredOut/literalMatches (null when q is omitted)/matchBasis/truncatedReason — zero literal hits return empty ads[], never the unfiltered leaderboard. Empty results and upstream timeouts are never charged. A real browser is required — Creative Center HTML is an empty shell and the list API needs page-signed requests. We intercept the signed list XHR and exit when that JSON arrives (typically 30-60 seconds; not networkidle). Flat 2 credits on the browser path; Apify fallback ~1 credit per returned ad (min 2; ~20 at default limit). truncatedReason is limit (your cap trimmed the page) or leaderboard-page (the page was short and Creative Center still had more); null when truncated is false, including empty after filter. Pass cache=true for a 24h hit (0 credits).

What you get

  • advertiser{id,name} for grouping + Spark author fallback
  • Honest keyword filter — per-ad matchedFrom + candidatesScanned envelope
  • No always-null date/flag fields (CC list has no run dates)
  • Signed list XHR early-exit (30–60s typical); empty/timeout free

Try it

Open in Playground

Fill in the parameters below and copy a ready-to-run request, or open the live Playground to run it against your account (no API key paste).

Parameters

Sign in to run live
curl "https://api.captapi.com/v1/ad-library/tiktok/top-ads" \
  -H "Authorization: Bearer capt_live_..."
# or: -H "x-api-key: capt_live_..."

Edit the parameters and the code updates instantly. Switch languages and hit copy.

Example response

{
  "success": true,
  "data": {
    "query": null,
    "country": "US",
    "period": 30,
    "orderBy": "ctr",
    "totalReturned": 2,
    "datesPresent": 1,
    "match": "any",
    "matchedFrom": 2,
    "filteredOut": 0,
    "literalMatches": 2,
    "matchBasis": "none",
    "ads": [
      {
        "platform": "tiktok_creative_center",
        "id": "7662489073849090066",
        "url": "https://ads.tiktok.com/business/creativecenter/topads/7662489073849090066/pc/en",
        "title": "Nuuly loves a woman in a suit ! #ad #nuulypartner #nuuly #frthoidolovenuuly",
        "brandName": "nuuly",
        "advertiser": {
          "id": "brand_nuuly",
          "name": "nuuly"
        },
        "firstSeen": "2026-01-10T00:00:00.000Z",
        "lastSeen": null,
        "likes": 620,
        "likesIsApproximate": false,
        "ctr": 0.17,
        "ctrTier": "below_50%",
        "costTier": 1,
        "isSparkAd": false,
        "industry": "Charity & Public Welfare",
        "industryKey": "label_23105000000",
        "objective": "Reach",
        "video": {
          "id": "v10033g50000example",
          "url": "https://v16m-default.tiktokcdn.com/example.mp4",
          "urlHd": "https://v16m-default.tiktokcdn.com/example-hd.mp4",
          "cover": "https://p16-common-sign.tiktokcdn.com/example~tplv-noop.image",
          "durationSeconds": 15,
          "width": 720,
          "height": 1280
        }
      },
      {
        "platform": "tiktok_creative_center",
        "id": "7662938725836324871",
        "url": "https://ads.tiktok.com/business/creativecenter/topads/7662938725836324871/pc/en",
        "title": "How I fix my hair EASILY on the go #hair #hairhack",
        "brandName": "Creator X",
        "advertiser": {
          "id": "uid42",
          "name": "Creator X"
        },
        "firstSeen": null,
        "lastSeen": null,
        "likes": 5,
        "likesIsApproximate": false,
        "ctr": 0.62,
        "ctrTier": "top_25%",
        "costTier": 0,
        "isSparkAd": true,
        "industry": "Charity & Public Welfare",
        "industryKey": "label_23105000000",
        "objective": "Product Sales",
        "video": {
          "id": "v10033g50000example",
          "url": "https://v16m-default.tiktokcdn.com/example.mp4",
          "cover": "https://p16-common-sign.tiktokcdn.com/example~tplv-noop.image",
          "durationSeconds": 15,
          "width": 720,
          "height": 1280
        }
      }
    ]
  }
}

Billing metadata is returned in response headers: X-Captapi-Credits (credits charged), X-Captapi-Cache (hit or miss), and X-Captapi-Source. Failed requests (4xx/5xx) are never charged. See the full list of error codes in the error reference.

Response structure

A successful call returns success and a data object with the following fields:

Top-level fields

  • queryThe search query you sent.
  • countryCountry for the request context. On popular-creators top-level: ISO feed market you queried (e.g. US) — not each creator's home country (see region).
  • periodLookback window in days used for the ranking: 7, 30, or 180.
  • orderBySort you asked for: for_you, likes, ctr, impressions, or cost.
  • totalReturnedNumber of items returned in this response.
  • datesPresentDates present. Example: 1.
  • matchEcho of the match query param ("any" or "all") — the mode you asked for.
  • matchedFromPer-ad only, and only when q is set: string[] of fields that matched (title, brandName, industry, objective). There is no tags field. Never the envelope scan count.
  • filteredOutRows dropped by the local whole-word keyword filter.
  • literalMatchesAlways keyed. Count of rows that passed local whole-word matching when q is set; null when q is omitted (no filter ran).
  • matchBasisMode actually applied: any|all when q was set; none when q was omitted (no keyword filter). match and matchBasis differ only when q is empty — they are the same value when a filter ran.

Ads

Each item in ads contains:

  • platformPlatform identifier for this response (matches the endpoint's platform).
  • idId of this ads item.
  • urlCanonical URL of the item.
  • titleTitle of this ads item.
  • brandNameSame as advertiser.name when present. Spark Ads with "Not Mention" fall back to the organic creator. Omitted when no name exists.
  • advertiserGrouping axis {id,name}. id may be brand_id or Spark author uid; null when Creative Center withholds it. name mirrors brandName when present — often null on every US row (the default market), so brand matching cannot fire there. Spark falls back to the creator nickname.
  • firstSeenFirst seen. Example: "2026-01-10T00:00:00.000Z".
  • lastSeenLast seen.
  • likesLike count (number).
  • likesIsApproximatetrue when likes looks like a rounded Creative Center bucket (e.g. multiples of 1k/100k); false when the integer looks exact.
  • ctrClick-through rate signal from Creative Center (typically 0–1).
  • ctrTierPresent only when Creative Center ships a CTR bucket. Omitted (not null) when withheld.
  • costTierCreative Center cost bucket when present.
  • isSparkAdPresent only when upstream sets Spark/non-Spark. Omitted when withheld. adFormat is omitted when it would only repeat Spark/Non-Spark.
  • industryIndustry. Example: "Charity & Public Welfare".
  • industryKeyCreative Center industry key / label id.
  • objectiveObjective. Example: "Reach".
  • videoObject with id, url, urlHd, cover, durationSeconds, width.

Parameters

NameTypeRequiredDescription
qstringNoOptional keyword that filters the one ~20-row leaderboard page — not a library search. Case-insensitive whole-word match on title/brandName/industry/objective (hair ≠ wheelchair). There is no tags field. advertiser.name is often null in the default US market. Envelope candidatesScanned is the pre-filter pool size. For a known advertiser, use /tiktok/ad-details by ad id.
matchstringNoKeyword token mode: "any" (default, OR) or "all" (AND). Zero literal hits → empty ads[] (never an unfiltered soft list).
countrystringNoTwo-letter ISO country code. Default US.
periodnumberNoLookback window in days: 7, 30, or 180. Default 30.
orderBystringNoSort: for_you, likes, ctr, impressions, or cost. Default for_you.
industrystringNoOptional industry key or label from Creative Center.
objectivestringNoOptional campaign objective (e.g. Traffic, Conversion, Reach).
adFormatstringNoOptional format filter: spark or non_spark.
limitintegerNoMax items to return (default 20, max 20). One Creative Center leaderboard page is ~20 rows; limit only trims that pool — it cannot scan more candidates. Flat 2 credits on Decodo-native; Apify ~1 credit per returned ad (min 2).
cachebooleanNoSet true to serve from the 24h response cache (0 credits on hit). Default false — always fetch fresh.

Authentication: send your key as Authorization: Bearer capt_live_.... A typical call costs 2 credits. Pass cache=true for a free 24h cache hit; default is always fresh.

Using an AI agent? This endpoint is the MCP tool tiktok_ad_library_top_ads via @captapi/mcp. Set it up →

How it works

  1. 1. Sign up — get 100 free credits, no card required.
  2. 2. Create a key from your dashboard.
  3. 3. Send one request to /v1/ad-library/tiktok/top-ads and parse the JSON response.

Use cases

Trend Discovery

Find trending content by keyword or hashtag.

Content Sourcing

Build feeds and playlists programmatically.

Monitoring

Track topics, brands, and competitors.

Research

Sample large sets of content for analysis.

Frequently asked questions

What does the TikTok Creative Center Top Ads API do?+

The TikTok Creative Center Top Ads API lets you search and return matching results from a public TikTok Ad Library query using one GET request to /v1/ad-library/tiktok/top-ads. It returns clean JSON — no OAuth or infrastructure setup required.

How many credits does the TikTok Creative Center Top Ads API cost?+

Each successful call costs 2 credits. Pass cache=true to serve from the 24h cache (0 credits on hit); default is always fresh. Selected profile endpoints also accept cacheMaxAge=1d|3d|7d|14d|30d. Failed or empty results are never charged.

Do I need a TikTok Ad Library API key or OAuth?+

No. A single Captapi key works across every platform Captapi supports — YouTube, TikTok, Instagram, Facebook, Twitter/X, Reddit, Threads, Bluesky, Pinterest, LinkedIn, Rumble, Spotify, Kwai, and more. We handle proxies, rate limits, retries, and authentication for you.

How is this different from TikTok Ad Library Search?+

q filters the top-N Creative Center leaderboard; it is not a library search. To find a known advertiser's ads, use /tiktok/ad-details by ad id. Top Ads is Creative Center performance inspiration (CTR tiers, likes, industry/objective, Spark Ads, video renditions) from one ~20-row page. Ad Library Search is the EU Commercial Content Library (first/last shown, reach bands). Different TikTok products — pick Top Ads for creative intel, Search for DSA transparency.

How many credits does Top Ads cost?+

Flat 2 credits on Decodo-native when ads are returned. Apify fallback bills ~1 credit per returned ad (min 2) — about 20 credits at the default limit of 20. Empty results and upstream timeouts are never charged. cache=true hits are free.

Why is this endpoint so slow — and what timeout should I set?+

Creative Center HTML is an empty shell — ads arrive only via a signed list XHR. We open the page in a browser, intercept that response, and exit when the JSON arrives (typically 30–60 seconds — not networkidle). Set your HTTP client timeout to at least 120 seconds. nginx/ALB default to 60s and Heroku caps at 30s — those cut the connection on your side. On timeout we return 503 upstream_timeout (not billed). If truncated is true, read truncatedReason: limit means your cap trimmed the one page; leaderboard-page means that page was short and Creative Center still had more (we do not paginate).

Why did my keyword return zero ads?+

q filters the top-N leaderboard; it is not a library search. q=vinted&country=US asks "is Vinted in the US top 20 right now?" — not "find Vinted's ads." Raising limit cannot grow the pool (max 20). Read candidatesScanned, filteredOut, literalMatches, and matchBasis. match is the mode you asked for; matchBasis is the mode we applied (none when q is omitted — that is when the two differ). match=any keeps rows with any whole-word token; match=all requires every token. Matching runs on title/brandName/industry/objective — there is no tags field, and advertiser.name is often null in the default US market so brand search cannot fire there. If candidatesScanned>0 and totalReturned=0, the leaderboard had rows and local filter dropped them (empty is free; truncated is false). For a known advertiser, use /tiktok/ad-details by ad id.

What does ctr mean, and where are ad dates?+

ctr is TikTok's normalized 0–1 Creative Center score (not a raw click-through percent). ctrTier/isSparkAd appear only when Creative Center ships them. The list surface does not expose ad run dates — firstSeen/lastSeen are not returned. The period param is only the lookback window for the ranking. For DSA firstShown/lastShown use /tiktok/ad-details (search omits them).

How do I group ads by advertiser?+

Use advertiser.id when present, else advertiser.name (same value as brandName). Spark Ads that ship "Not Mention" fall back to the organic creator nickname and author id. Creative Center often omits both — in the default US market advertiser.name is typically null on every row, so brand matching cannot fire. null advertiser.id is expected on some rows.

Why did Top Ads return 502 with industry set?+

The Apify fallback only accepts its fixed industry enum (All Industries, Gaming, E-commerce & Shopping, Beauty & Personal Care, …). We now map TikTok keys/aliases (label_25000000000, Games→Gaming) before the actor call; unsupported values return HTTP 400 with the allowed list — not upstream_actor_error 502. Omit industry or use Gaming / All Industries to unblock.

Is the TikTok Creative Center Top Ads API suitable for production use?+

Yes. It is a stable REST endpoint with predictable JSON and automatic retries. Pass cache=true to serve from the 24h cache (0 credits on hit); default is always fresh. Selected profile endpoints also accept cacheMaxAge=1d|3d|7d|14d|30d. Use it for analytics, monitoring, and content automation.

More TikTok Ad Library APIs

Ready to use the TikTok Creative Center Top Ads API?

Sign up, grab your key, and make your first call in 60 seconds.

TikTok Creative Center Top Ads API | Captapi — Captapi