{
  "openapi": "3.0.1",
  "info": {
    "title": "Tiktok Trending Hashtags Analytics Scraper & Top Videos",
    "description": "TikTok Trending Hashtags Analytics Scraper — Scrape trending TikTok hashtags with views, growth metrics, engagement data, and top videos. Analyze hashtag performance, discover viral content, track trends, and identify high-performing videos and creators.",
    "version": "0.1",
    "x-build-id": "3hqLSQoGB9x6cj2ZX"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapio~tiktok-trending-hashtags-analytics-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapio-tiktok-trending-hashtags-analytics-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/scrapio~tiktok-trending-hashtags-analytics-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapio-tiktok-trending-hashtags-analytics-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/scrapio~tiktok-trending-hashtags-analytics-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapio-tiktok-trending-hashtags-analytics-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": {
          "result_type": {
            "title": "🎛️ Result type",
            "enum": [
              "top100",
              "top100_with_analytics",
              "analytics"
            ],
            "type": "string",
            "description": "top100 = ranking only (analytics is an empty object, exactly like the classic actor). top100_with_analytics = ranking + trend curve + top creators. analytics = analytics for the hashtag names you supply in hashtag_list. Every mode emits the same column set, so your downstream schema never changes.",
            "default": "top100_with_analytics"
          },
          "country": {
            "title": "🌍 Country / region",
            "enum": [
              "ALL",
              "AL",
              "AR",
              "AT",
              "AU",
              "BD",
              "BE",
              "BG",
              "BH",
              "BR",
              "BY",
              "CA",
              "CH",
              "CL",
              "CN",
              "CO",
              "CZ",
              "DE",
              "DK",
              "EE",
              "EG",
              "ES",
              "FI",
              "FR",
              "GB",
              "GR",
              "HK",
              "HR",
              "HU",
              "ID",
              "IE",
              "IL",
              "IN",
              "IQ",
              "IS",
              "IT",
              "JO",
              "JP",
              "KH",
              "KR",
              "KW",
              "KZ",
              "LB",
              "LT",
              "LU",
              "LV",
              "MA",
              "MN",
              "MO",
              "MX",
              "MY",
              "NG",
              "NL",
              "NO",
              "NZ",
              "OM",
              "PE",
              "PH",
              "PK",
              "PL",
              "PT",
              "QA",
              "RO",
              "SA",
              "SE",
              "SG",
              "SK",
              "TH",
              "TR",
              "TW",
              "UA",
              "AE",
              "US",
              "UZ",
              "VN",
              "ZA"
            ],
            "type": "string",
            "description": "The country board to read. TikTok only publishes 27 country boards: US FR DE IT ES GB AR AU BR CA CO EG ID IL JP KR MY MX PH SA SG ZA TW TH TR AE VN. Every other code (and ALL) silently returns the United States board — this actor does not hide that, it sets countrySupported=false and countryFallbackApplied=true on the row.",
            "default": "US"
          },
          "top100_period": {
            "title": "📅 Ranking window (days)",
            "enum": [
              "7",
              "30",
              "90",
              "120"
            ],
            "type": "string",
            "description": "Real upstream windows are 7, 30 and 90 days. 90 is new here — TikTok serves it (90-point curve, a genuinely different tag set) and no other actor exposes it. 120 is still accepted for backward compatibility, but TikTok silently serves the 7-day board for it; the row then carries periodAliasApplied=true and periodDays=7.",
            "default": "7"
          },
          "analytics_period": {
            "title": "📊 Analytics period (legacy, no upstream effect)",
            "enum": [
              "7",
              "30",
              "90",
              "120",
              "365",
              "1095"
            ],
            "type": "string",
            "description": "Kept so older run configurations keep working. TikTok's trends surface has no separate analytics window — curve length is set by the ranking window above. Whatever you pick is echoed on the row as analyticsPeriodRequested and flagged analyticsPeriodIgnored=true. 365 and 1095 do not exist upstream at all.",
            "default": "30"
          },
          "top100_industry": {
            "title": "🏷️ Industry filter (applied client-side)",
            "enum": [
              "",
              "Apparel & Accessories",
              "Baby, Kids & Maternity",
              "Beauty & Personal Care",
              "Business Services",
              "Education",
              "Financial Services",
              "Food & Beverage",
              "Games",
              "Healthcare",
              "Home Improvement",
              "Household Products",
              "Life Services",
              "News & Entertainment",
              "Pets",
              "Real Estate",
              "Software & Apps",
              "Sports & Outdoor",
              "Tech & Electronics",
              "Travel",
              "Vehicle & Transportation"
            ],
            "type": "string",
            "description": "TikTok's server ignores every industry parameter (19 spellings tested, zero effect), so this actor filters after fetching, using the industry IDs TikTok stamps on each row. 9 industries are ID-mapped and really filterable: Apparel & Accessories, Beauty & Personal Care, Education, Food & Beverage, Games, News & Entertainment, Pets, Sports & Outdoor, Travel. Pick anything else and the run warns and keeps all rows rather than returning nothing.",
            "default": ""
          },
          "top100_new_on_board": {
            "title": "✨ New to the board only (no upstream effect)",
            "type": "boolean",
            "description": "Kept for backward compatibility. TikTok ignores every new-on-board parameter (4 spellings tested, byte-identical rows) and the payload carries no rank-change marker at all. Switching this on changes nothing except the newOnBoardIgnored=true flag on the row — this actor will not fabricate a 'new' badge.",
            "default": false
          },
          "hashtag_list": {
            "title": "📝 Custom hashtag list",
            "type": "array",
            "description": "Hashtag names without the #. Used by result_type=analytics. Names on the live board keep their rank and trend curve; names that are not on today's board are still resolved through TikTok's public hashtag embed (exact lifetime views, exact post count and top videos) when 'Resolve off-board hashtags' is on — the classic actor simply dropped them.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "total_hashtags": {
            "title": "🔢 Max hashtags to save",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Upper bound on saved hashtag rows. TikTok's board hard-caps at 3 hashtags per country+window (totalCount:3, hasMore:false on every slice tested) — a higher number cannot conjure more board rows, it only raises the ceiling for custom hashtags in analytics mode.",
            "default": 10
          },
          "include_top_videos": {
            "title": "🎬 Fetch top videos per hashtag",
            "type": "boolean",
            "description": "Adds topVideos[] to every hashtag row: video ID, URL, caption, play count, author handle, cover images and the direct media URL. Also fills the exact lifetime viewCountExact / videoCountExact for the hashtag. Costs one extra request per hashtag.",
            "default": true
          },
          "videos_per_hashtag": {
            "title": "🔢 Max videos per hashtag",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Cap on topVideos[] per hashtag. TikTok returns at most 10 and often fewer (measured 4–10), so values above 10 have no effect.",
            "default": 10
          },
          "fetch_video_details": {
            "title": "📊 Fetch full engagement per video",
            "type": "boolean",
            "description": "One extra request per video to add likes, comments, shares, posted-at, duration, isAd, filming country, the sound behind the clip, every co-occurring hashtag, the creator's follower/like/video counts, and a derived engagementRate. Measured 87/87 success in 5.4 s at 8-way concurrency with no proxy.",
            "default": true
          },
          "min_plays": {
            "title": "🔥 Minimum plays per video",
            "minimum": 0,
            "type": "integer",
            "description": "Drops topVideos below this play count. Applied after fetching — TikTok accepts no server-side play filter — so it trims output, it does not reduce request count.",
            "default": 0
          },
          "video_concurrency": {
            "title": "⚡ Video request concurrency",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "Parallel embed requests. 8 was measured clean with zero blocks and zero rate limiting; raise only if you are on a residential proxy.",
            "default": 8
          },
          "video_child_dataset": {
            "title": "🗂️ Also write a flat video dataset",
            "type": "boolean",
            "description": "Writes every video to a second named dataset 'top-videos' as one flat row per video (CSV/Excel friendly), in addition to the nested topVideos[] on the hashtag row. Child rows are never charged.",
            "default": true
          },
          "resolve_custom_hashtags": {
            "title": "🔎 Resolve off-board hashtags",
            "type": "boolean",
            "description": "In analytics mode, resolve hashtag_list names that are not on today's board through TikTok's public hashtag embed instead of dropping them. You get the challenge ID, exact lifetime views, exact post count and top videos; rank and the trend curve stay null because only the board publishes those.",
            "default": true
          },
          "proxyConfiguration": {
            "title": "🛡️ Proxy configuration",
            "type": "object",
            "description": "Optional. Leave Apify Proxy on as a safety net; it is used only after a proven block. Residential is the best escalation tier for TikTok.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}