{
  "openapi": "3.0.1",
  "info": {
    "title": "TikTok Ad Library Scraper",
    "description": "Scrape every ad an advertiser runs on TikTok from the official Commercial Content Library. Extract ad IDs, advertiser names, first & last shown dates, unique reach and direct downloadable video and image URLs. Search by advertiser or keyword across 32 countries. No login or API key.",
    "version": "0.1",
    "x-build-id": "LFBgd9uCgi0qLu1yc"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/jmlp~tiktok-ad-library-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-jmlp-tiktok-ad-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/jmlp~tiktok-ad-library-scraper/runs": {
      "post": {
        "operationId": "runs-sync-jmlp-tiktok-ad-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/jmlp~tiktok-ad-library-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-jmlp-tiktok-ad-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "searchTerms": {
            "title": "Advertiser names",
            "type": "array",
            "description": "Advertiser names to look up, e.g. 'Nike' or 'Booking.com'. Matches the advertiser as registered with TikTok, which is usually the legal entity ('NIKE Retail B.V.') rather than the brand, and partial names work. Each name is searched in every region below.",
            "items": {
              "type": "string"
            }
          },
          "searchTerm": {
            "title": "Advertiser name (single)",
            "type": "string",
            "description": "A single advertiser name, for convenience when you only have one."
          },
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Search the ad CONTENT rather than the advertiser name, e.g. 'running shoes' or 'black friday'. Use this to find every advertiser talking about a theme, instead of every ad from one company.",
            "items": {
              "type": "string"
            }
          },
          "advertiserBusinessIds": {
            "title": "Advertiser business IDs",
            "type": "array",
            "description": "TikTok business ids, if you already have them. The most precise input: nothing has to be matched by name, so nothing can match the wrong company.",
            "items": {
              "type": "string"
            }
          },
          "regions": {
            "title": "Countries",
            "type": "array",
            "description": "2-letter country codes, e.g. GB, DE, FR. TikTok's Commercial Content Library exists to satisfy the EU Digital Services Act, so it covers the EU/EEA plus the UK and Switzerland ONLY - there is no US, Canadian or APAC data in it. Every country is a separate job, which is also how this actor parallelises. Use 'all' to cover all 32.",
            "items": {
              "type": "string"
            }
          },
          "region": {
            "title": "Country (single)",
            "type": "string",
            "description": "A single 2-letter country code, used alongside or instead of the list above."
          },
          "minDate": {
            "title": "Last shown on or after",
            "type": "string",
            "description": "YYYY-MM-DD. TikTok's window filters on the date an ad was LAST shown, server-side. Leave both dates empty to cover roughly the last three years, which is everything the library holds - note the website itself defaults to 30 days and quietly hides the rest."
          },
          "maxDate": {
            "title": "Last shown on or before",
            "type": "string",
            "description": "YYYY-MM-DD. Combined with the field above it selects ads whose last-shown date falls in the window."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "REQUIRED, and it must be RESIDENTIAL. Measured: TikTok's search endpoint refuses every datacenter address tried - including Apify's own platform IP and both datacenter pools - while still completing the handshake, so a datacenter run looks like a broken session rather than a blocked IP.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "maxAds": {
            "title": "Max ads",
            "minimum": 1,
            "type": "integer",
            "description": "Stop after this many unique ads, counted across every advertiser and country. Caps runtime and cost. Prefilled so a first run finishes in well under a minute - clear it to scrape everything."
          },
          "maxPages": {
            "title": "Max pages per job",
            "minimum": 1,
            "type": "integer",
            "description": "Safety cap while testing, applied to each country/search job separately. One page is up to 100 ads. Empty = all."
          },
          "adType": {
            "title": "Ad format",
            "enum": [
              "all",
              "video",
              "image",
              "text"
            ],
            "type": "string",
            "description": "Limit to one creative format.",
            "default": "all"
          },
          "adStatus": {
            "title": "Ad status",
            "enum": [
              "all",
              "active",
              "inactive"
            ],
            "type": "string",
            "description": "Active = running right now. Inactive = stopped. All = the advertiser's whole history in this country.",
            "default": "all"
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "last_shown_date,desc",
              "last_shown_date,asc",
              "create_time,desc",
              "create_time,asc",
              "impression,desc",
              "impression,asc"
            ],
            "type": "string",
            "description": "The order TikTok returns ads in. Only affects which ads you get first when you set a Max ads limit.",
            "default": "last_shown_date,desc"
          },
          "gender": {
            "title": "Targeted gender",
            "enum": [
              "ALL",
              "FEMALE",
              "MALE"
            ],
            "type": "string",
            "description": "Keep only ads targeted at this gender, as declared in the advertiser's own targeting.",
            "default": "ALL"
          },
          "ages": {
            "title": "Targeted age bands",
            "type": "array",
            "description": "Keep only ads targeted at these age bands. Values are exactly: all, 13,17 / 18,24 / 25,34 / 35,44 / 45,54 / 55,100. Leave empty for all.",
            "items": {
              "type": "string"
            }
          },
          "adReach": {
            "title": "Unique reach bands",
            "type": "array",
            "description": "Keep only ads in these reach bands. Values are exactly: all, 0-10K, 10K-100K, 100K+. Leave empty for all.",
            "items": {
              "type": "string"
            }
          },
          "pageSize": {
            "title": "Page size",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Ads per request. 12 is what the website itself uses and the value this was measured against; larger values are accepted by the schema but unverified.",
            "default": 12
          },
          "delayMs": {
            "title": "Delay between pages (ms)",
            "minimum": 0,
            "type": "integer",
            "description": "Milliseconds to sleep between result pages. TikTok throttles hard, and a refused exit has to be replaced with a whole new browser session, so this is worth keeping generous.",
            "default": 500
          },
          "raw": {
            "title": "Raw output",
            "type": "boolean",
            "description": "Push TikTok's records untouched, without the flattening, date conversion and CDN-URL decoding of the fixed output schema.",
            "default": false
          },
          "proxyRotations": {
            "title": "Proxy rotation attempts",
            "minimum": 1,
            "maximum": 6,
            "type": "integer",
            "description": "If a job is throttled, the actor mints a new proxy session AND a new session token, then retries this many times.",
            "default": 3
          },
          "resume": {
            "title": "Checkpoint progress",
            "type": "boolean",
            "description": "Save progress every ~30s so a run that gets migrated or restarted by the platform picks up where it stopped, without duplicating anything. No effect on fresh runs.",
            "default": true
          },
          "continueFromLastRun": {
            "title": "Continue from last run",
            "type": "boolean",
            "description": "If your previous run with the same input was interrupted, throttled, or stopped because it hit Max ads, scrape only what it missed. Note the earlier ads stay in THAT run's dataset, so this run's dataset contains only the remainder.",
            "default": false
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}