---
title: "TikTok Creative Center Top Ads API"
method: GET
path: "/v1/ad-library/tiktok/top-ads"
tags: ["TikTok Ad Library"]
---

# TikTok Creative Center Top Ads API

`GET /v1/ad-library/tiktok/top-ads`

## Request

- Base URL: `https://api.captapi.com`
- URL: `https://api.captapi.com/v1/ad-library/tiktok/top-ads`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

TikTok Creative Center Top Ads — one ~20-row leaderboard page, not a library search (flat 2; ~1/ad on the fallback path).

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 literal hit includes matchedFrom (field names that matched) and the envelope reports candidatesScanned/filteredOut/literalMatches (null when q is omitted)/matchBasis/truncatedReason. When no title/brand whole-word hits, ads[] is still TikTok's keyword-ranked page (matchBasis=ranked, literalMatches=0) — the same list Creative Center shows — not an empty miss. 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 native path; the fallback path bills ~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. Pass cache=true for a 24h hit (0 credits).

Docs: https://captapi.com/apis/tiktok-ad-library-top-ads

## Query parameters

- `q` string
- `match` string
- `country` string
- `period` integer
- `orderBy` string
- `industry` string
- `objective` string
- `adFormat` string
- `limit` integer
- `cache` boolean

## Response `200`

Success. The data object for this endpoint.

- object
  - `success` unknown, required
  - `data` object, required
    - `query` unknown
    - `country` string: Country 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).
    - `period` integer: Lookback window in days used for the ranking: 7, 30, or 180.
    - `orderBy` string: Sort you asked for: for_you, likes, ctr, impressions, or cost.
    - `totalReturned` integer: Number of items returned in this response.
    - `datesPresent` integer: Dates present. Example: 1.
    - `match` string: Echo of the match query param ("any" or "all") — the mode you asked for.
    - `matchedFrom` integer: Per-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.
    - `filteredOut` integer: Rows dropped by the local whole-word keyword filter (0 when matchBasis is ranked).
    - `literalMatches` integer: Always keyed. Count of rows that passed local whole-word matching when q is set; null when q is omitted (no filter ran). 0 with ads present means matchBasis=ranked.
    - `matchBasis` string: Mode actually applied: any|all when whole-word hits exist; ranked when q was set and TikTok's keyword page is returned without a whole-word hit; none when q is omitted.
    - `ads` object[]
      - `platform` string: Platform identifier for this response (matches the endpoint's platform).
      - `id` string: Id of this ads item.
      - `url` string: Canonical URL of the item.
      - `title` string: Title of this ads item.
      - `brandName` string: Same as advertiser.name when present. Spark Ads with "Not Mention" fall back to the organic creator. Omitted when no name exists.
      - `advertiser` object: Grouping 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.
        - `id` string: Id of this ads item.
        - `name` string
      - `firstSeen` string, nullable: First seen. Example: "2026-01-10T00:00:00.000Z".
      - `lastSeen` unknown
      - `likes` integer: Like count (number).
      - `likesIsApproximate` boolean: true when likes looks like a rounded Creative Center bucket (e.g. multiples of 1k/100k); false when the integer looks exact.
      - `ctr` number: Click-through rate signal from Creative Center (typically 0–1).
      - `ctrTier` string: Present only when Creative Center ships a CTR bucket. Omitted (not null) when withheld.
      - `costTier` integer: Creative Center cost bucket when present.
      - `isSparkAd` boolean: Present only when upstream sets Spark/non-Spark. Omitted when withheld. adFormat is omitted when it would only repeat Spark/Non-Spark.
      - `industry` string: Industry. Example: "Charity & Public Welfare".
      - `industryKey` string: Creative Center industry key / label id.
      - `objective` string: Objective. Example: "Reach".
      - `video` object: Object with id, url, urlHd, cover, durationSeconds, width.
        - `id` string: Id of this ads item.
        - `url` string: Canonical URL of the item.
        - `urlHd` string
        - `cover` string
        - `durationSeconds` integer
        - `width` integer
        - `height` integer

## Other responses

- `400`: Bad request: wrong platform URL, unknown endpoint, or an invalid parameter value. Not billed.
- `401`: Missing, invalid or revoked API key. Not billed.
- `402`: Not enough credits for this request. Not billed.
- `404`: The resource does not exist or is not public. Not billed.
- `422`: A required parameter is missing or has the wrong type. Not billed.
- `429`: Rate limit reached. Wait for Retry-After seconds. Not billed.
- `502`: The platform could not be reached or returned nothing usable. Retryable, not billed. 503 and 504 use the same envelope.

---

[API](https://skmtc.dev/captapi/apis/captapi-api.md) · [All operations](https://skmtc.dev/captapi/apis/captapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/captapi/apis/captapi-api/revisions/c9b9ac5ff1bd?raw)
