Skip to content

TikTok Ad Library Search API

Ads in TikTok's public Commercial Content Library, by keyword (query) or by advertiser (advertiser_name). An advertiser name is resolved through TikTok's own typeahead first, then searched as an entity, so it matches the registered legal name ("NIKE Retail B.V.") rather than a brand. Results are NOT global: TikTok publishes this archive per market and refuses a search without one, so region is required, validated against the market list the library itself publishes rather than a fixed list here, and every result ran in that market, which is what each ad's countries reports. TikTok returns its own relevance ranking; we ask for the most recently shown first, but that is only a tiebreak within it, so results are not ordered by date. Cursor-paginated 12 at a time, each ad carrying its public library.tiktok.com detail URL. Pages are not guaranteed disjoint: the archive re-ranks live, so an ad can repeat across pages. Political and election ads are outside the archive. Reach is published as a band and is not impressions, so it stays in raw.estimated_audience rather than the impressions fields. Calls cost 1 credit each. A cache hit is free, and a failed or empty response is never charged.

Try it

Prefilled with the request that produced the example below. No key yet? Get a free key.

Request

GET/v1/tiktok/ad-library/search
ParameterTypeRequiredDescription
querystringnoKeyword, matched against ad text and advertiser name
advertiser_namestringnoAdvertiser name, resolved through TikTok's typeahead to one advertiser entity
regionstringyesMarket to search. TikTok publishes this archive per market; one of AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FR, GB, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR.
cursorstringnopagination.cursor from a previous response

Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).

curl
curl "$API/v1/tiktok/ad-library/search?query=nike&region=FR&cache_max_age=7d" \
  -H "x-api-key: $KEY"
JavaScript
const query = new URLSearchParams({
  query: 'nike',
  region: 'FR',
  cache_max_age: '7d',
});

const response = await fetch(`${API}/v1/tiktok/ad-library/search?${query}`, {
  headers: { 'x-api-key': KEY },
});

const body = await response.json();
if (!body.success) throw new Error(body.error.code);

// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);
Python
import os, httpx

r = httpx.get(
    f"{os.environ['API']}/v1/tiktok/ad-library/search",
    params={
        "query": "nike",
        "region": "FR",
        "cache_max_age": "7d",
    },
    headers={"x-api-key": os.environ["KEY"]},
    timeout=30,
)

body = r.json()
if not body["success"]:
    raise RuntimeError(body["error"]["code"])

print(body["data"], body["meta"]["creditsCharged"])

Example response

Captured on , with raw removed and lists cut to two items. A live call returns current data.

response
{
  "success": true,
  "data": {
    "items": [
      {
        "platform": "tiktok",
        "id": "1873863495056546",
        "advertiserId": null,
        "advertiserName": "NIKE Retail B.V.",
        "url": "https://library.tiktok.com/ads/detail?ad_id=1873863495056546",
        "headline": "Une rentrée signée Nike",
        "body": null,
        "ctaText": null,
        "linkUrl": null,
        "creativeType": "video",
        "imageUrls": [
          "https://p19-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/o45YWEpAPPkA1b7rAaQtUzIUwB1TiinKIZB1r~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=56408ff2&x-expires=1792566000&x-signature=bpArQLFRGi%2F1ZCTSpSQZL0I1x0M%3D&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1"
        ],
        "videoUrls": [
          "https://library.tiktok.com/api/v1/cdn/1792547647/video/aHR0cHM6Ly92MTZtLnRpa3Rva2Nkbi5jb20vNzQ1YjZmNmFmMGE3M2VjOTVhY2JkZGZkODczZmEyODgvNmFkODZmYTUvdmlkZW8vdG9zL2FsaXNnL3Rvcy1hbGlzZy12ZS0wMDUxYzAwMS1zZy9vb3c3UGkxVWF6WnJrWUlqQVVBYmlYRkVxTkJpUG4xMVhUQVdJLw==/203dc710-1bfa-4780-b236-eff52a471005?a=475769&bt=1148&btag=e000b0000&bti=PDU2NmYwMy86&ft=.NpOcInz7Th97AFGXq8Zmo&l=20261021095407E26D22DF4D901A2D758E&mime_type=video_mp4&rc=OGk0PDNkaDw4ZTQ5aWk1PEBpMzR4PHg5cjM3ZDMzODYzNEBeYzMwMDAvNmExLl8uYy01YSMyNmwxMmRzby9hLS1kMDFzcw%3D%3D&signature=DbVPcJP42U4e%2BuTWDu2U3aiPYDCaMZM7MVd%2FAVZpZ5U%3D&vvpl=1"
        ],
        "platforms": [
          "tiktok"
        ],
        "countries": [
          "FR"
        ],
        "languages": [],
        "startedAt": "2026-08-20T00:00:00.000Z",
        "endedAt": "2026-09-13T00:00:00.000Z",
        "isActive": null,
        "impressionsLower": null,
        "impressionsUpper": null,
        "spendLower": null,
        "spendUpper": null,
        "currency": null,
        "fetchedAt": "2026-10-21T01:54:08.307Z"
      },
      {
        "platform": "tiktok",
        "id": "1873877803725954",
        "advertiserId": null,
        "advertiserName": "NIKE Retail B.V.",
        "url": "https://library.tiktok.com/ads/detail?ad_id=1873877803725954",
        "headline": "Une rentrée signée Nike",
        "body": null,
        "ctaText": null,
        "linkUrl": null,
        "creativeType": "video",
        "imageUrls": [
          "https://p16-common-sign.tiktokcdn.com/tos-alisg-p-0051c001-sg/osADB1e1IhUIeCi59JGyXEhZg6kbIaLAYuQGei~tplv-tiktokx-origin.jpeg?dr=14582&refresh_token=ab072649&x-expires=1792566000&x-signature=TQnYVtgVRVGHPhZM9NZ9pr%2B90tY%3D&t=4d5b0474&ps=13740610&shp=0c75dd76&shcp=9b759fb9&idc=sg1"
        ],
        "videoUrls": [
          "https://library.tiktok.com/api/v1/cdn/1792547647/video/aHR0cHM6Ly92MTZtLnRpa3Rva2Nkbi5jb20vMGEwMGI1YTNjM2NmMzQ1YzVjNDc2OGNjOWMwNjM0NmEvNmFkODZmYTUvdmlkZW8vdG9zL2FsaXNnL3Rvcy1hbGlzZy12ZS0wMDUxYzAwMS1zZy9vMGQ2Z0loRUdRWGF5Q2tlQUllMUFZS3ZYTGhpaVVER1I5ZWJwMS8=/dd58a11c-f187-4ab9-ac6c-77d74b5756d4?a=475769&bt=893&btag=e000b0000&bti=PDU2NmYwMy86&ft=.NpOcInz7Th97AFGXq8Zmo&l=20261021095407E26D22DF4D901A2D758E&mime_type=video_mp4&rc=ZmU0ZjM1aTY3OjtlNjY4N0BpanNsPHg5cmo7ZDMzODYzNEAuM140YTU0NmExLTYzMF5eYSMzYW0xMmQ0NS9hLS1kMDFzcw%3D%3D&signature=c2TMv%2B6QfRfCKX1klpBEoKM3okIJWE25jsSv%2BvaFV10%3D&vvpl=1"
        ],
        "platforms": [
          "tiktok"
        ],
        "countries": [
          "FR"
        ],
        "languages": [],
        "startedAt": "2026-08-20T00:00:00.000Z",
        "endedAt": "2026-09-13T00:00:00.000Z",
        "isActive": null,
        "impressionsLower": null,
        "impressionsUpper": null,
        "spendLower": null,
        "spendUpper": null,
        "currency": null,
        "fetchedAt": "2026-10-21T01:54:08.307Z"
      }
    ]
  },
  "pagination": {
    "cursor": "eyJzIjoiZXlKc1lYTjBYM052Y25RaU9sc3lOeTR4TWpNeU1Td3hOemc1TWpVM05qQXdNREF3WFN3aWJtVjRkRjlqZFhKemIzSWlPakV5ZlE9PSIsIm8iOjF9",
    "hasMore": true,
    "count": 12
  },
  "meta": {
    "platform": "tiktok",
    "endpoint": "tiktok.adLibrarySearch",
    "creditsCharged": 1,
    "cached": false,
    "cacheAgeSeconds": null,
    "durationMs": 9348,
    "requestId": "req_r9c9rqr0hzgl42o52jyl"
  }
}

Returns

Returns a list of Ad in data.items.

Cost and behaviour

Credits1 per live request, 0 on a cache hit
Cacheableyes: cache_max_age accepts a cached copy
Batchableno
Subscribableyes: as often as every 3600 seconds, firing a webhook only on a change

Other TikTok endpoints