{
  "openapi": "3.0.1",
  "info": {
    "title": "TikTok Scraper API — Video, Profile, Hashtag & Search",
    "description": "Public TikTok video, profile, hashtag, and search scraper with explicit request requirements and failure rules. HTTP-first with US residential recovery. $0.50 per 1,000 results.",
    "version": "1.0",
    "x-build-id": "asMUiJrjAIdt7Q02w"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/funny_ground~tiktok-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-funny_ground-tiktok-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/funny_ground~tiktok-scraper/runs": {
      "post": {
        "operationId": "runs-sync-funny_ground-tiktok-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/funny_ground~tiktok-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-funny_ground-tiktok-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": {
          "startUrls": {
            "title": "TikTok URLs — auto-detect",
            "uniqueItems": true,
            "type": "array",
            "description": "Supported routes only: TikTok profile; hashtag; search URL with a non-empty q parameter; video/photo detail; or vm.tiktok.com, vt.tiktok.com, and /t/ short-share links. Non-TikTok hosts, lookalike hosts, the TikTok home page, search URLs without q, and unsupported TikTok routes are ignored. If no other usable input remains, the run is FAILED.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "profiles": {
            "title": "Profiles",
            "uniqueItems": true,
            "type": "array",
            "description": "TikTok usernames (without @) or full profile URLs. The account must exist and expose at least one public video. Private, suspended, nonexistent, or public-but-empty accounts produce no rows.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "hashtags": {
            "title": "Hashtags",
            "uniqueItems": true,
            "type": "array",
            "description": "Hashtags without #. The tag feed must expose at least one public video. A mathematically empty date window (postedAfter >= postedBefore) guarantees zero rows for this input.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "hashtagPostedAfter": {
            "title": "Hashtag: posted after",
            "type": "string",
            "description": "Only return hashtag videos posted on or after this date/time (inclusive). Accepts ISO 8601 — date-only (e.g. 2026-05-01) is anchored to 00:00:00 UTC; date-time is used as-is. Leave empty to disable. An invalid API-supplied value logs a warning and is ignored. Only applies to hashtags. CONDITION: if this valid value is equal to or later than hashtagPostedBefore, the interval is empty and the hashtag necessarily returns zero rows."
          },
          "hashtagPostedBefore": {
            "title": "Hashtag: posted before",
            "type": "string",
            "description": "Only return hashtag videos posted strictly before this date/time (exclusive). Same format as hashtagPostedAfter. Leave empty for no upper bound; an invalid API-supplied value logs a warning and is ignored. CONDITION: a valid value must be later than hashtagPostedAfter. With a date filter, resultsPerInput is also the candidate scan budget; set it ~3-5× the desired returned count because out-of-window candidates are discarded."
          },
          "searchKeywords": {
            "title": "Search keywords",
            "uniqueItems": true,
            "type": "array",
            "description": "Non-empty free-text queries. TikTok must expose anonymous public video results in the execution region; empty/no-result/login-gated searches produce no rows. HTTP runs first, then recoverable failures rotate through small fresh-browser batches in Auto mode.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "videoUrls": {
            "title": "Video URLs",
            "uniqueItems": true,
            "type": "array",
            "description": "Direct TikTok video/photo or TikTok short-share URLs. The post must exist, be public, and expose a numeric play count. Deleted, private, nonexistent, unavailable, or permission-gated posts produce no row. Exact returns unrounded counts; Auto can recover through native HTML and mark the row rounded; Fast favors throughput and may return rounded web counters.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "dataSource": {
            "title": "Data source",
            "enum": [
              "auto",
              "tikwm",
              "browser"
            ],
            "type": "string",
            "description": "Auto (recommended) tries lightweight HTTP for every input. If TikWM rejects datacenter egress with 401/403, Auto retries only that small JSON request through the proxy below, gives direct videos a native-HTML chance, then starts a browser only for remaining recoverable failures. After browser exhaustion, one final exact HTTP retry runs. The tikwm option guarantees no browser or proxy. Browser starts with the fallback path and uses the proxy configuration below.",
            "default": "auto"
          },
          "statsPrecision": {
            "title": "Engagement count precision",
            "enum": [
              "exact",
              "fast"
            ],
            "type": "string",
            "description": "Exact (recommended) requests the rate-limited detail/list source so engagement counters are unrounded. In Auto mode, a transient exact-source failure on a direct URL may recover through native HTML and is clearly marked rounded instead of failing. Fast always sends direct URLs to parallel TikTok HTML; popular-video counters can be rounded (for example 2,012,616 to 2,000,000).",
            "default": "exact"
          },
          "failOnPartialFailure": {
            "title": "Fail when any input is empty",
            "type": "boolean",
            "description": "False (recommended): if at least one valid row exists, the run succeeds while RUN_SUMMARY reports SUCCEEDED_WITH_WARNINGS, failedInputs, and inputSuccessRate for private/deleted/empty/blocked inputs. True: any one input with no valid data makes the entire run FAILED, even when other inputs returned rows. A run with zero valid rows always fails in either mode.",
            "default": false
          },
          "resultsPerInput": {
            "title": "Results per input",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "Max videos to return for each profile / hashtag / keyword. With a hashtag date filter, this is the maximum number of feed candidates scanned and the returned count may be lower. Set to 0 for unlimited (until end of feed). For Apify Free-plan users, a separate global limit of 50 dataset rows per run applies regardless of this field. Paid-plan users are not subject to that developer-set 50-row limit.",
            "default": 50
          },
          "shouldDownloadVideos": {
            "title": "Download video files",
            "type": "boolean",
            "description": "If true, store video MP4 files in Apify Key-Value Store. WARNING: significantly increases cost & runtime.",
            "default": false
          },
          "shouldDownloadCovers": {
            "title": "Download cover images",
            "type": "boolean",
            "description": "If true, store video thumbnail JPGs in Apify Key-Value Store.",
            "default": false
          },
          "proxy": {
            "title": "Browser fallback proxy",
            "type": "object",
            "description": "Reliability default: US RESIDENTIAL for browser fallback and a low-bandwidth TikWM 401/403 retry in Auto mode; normal HTTP uses no proxy. Residential traffic costs extra only when access-block or browser recovery runs. Explicit proxy groups, custom URLs, and disabled proxy settings are honored."
          },
          "fallbackToResidential": {
            "title": "Deprecated: automatic residential fallback",
            "type": "boolean",
            "description": "Deprecated and ignored. Browser fallback now uses the proxy configuration above; when that object is omitted, the reliability default is US RESIDENTIAL.",
            "default": false
          },
          "blockImages": {
            "title": "Block images (saves bandwidth)",
            "type": "boolean",
            "description": "Abort image requests to cut browser bandwidth and speed up page loads. Turn off only if your target route starts returning 0 results.",
            "default": true
          },
          "headless": {
            "title": "Headless browser",
            "type": "boolean",
            "description": "Run Playwright in headless mode. Set false only when debugging locally.",
            "default": true
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Range 1–30. Controls HTTP/Fast-direct tasks and downloads. Exact profile/hashtag/search calls remain globally spaced by about 2.2 seconds for upstream reliability. Browser recovery is capped separately for memory safety: one page at the default 1,024 MB, or at most two pages when the run has at least 2,048 MB. RUN_SUMMARY reports the effective browserFallbackConcurrency.",
            "default": 4
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (s)",
            "minimum": 10,
            "maximum": 300,
            "type": "integer",
            "description": "Page load timeout in seconds.",
            "default": 45
          },
          "maxAttemptsPerSeed": {
            "title": "Max attempts per seed",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Maximum browser attempts for each profile / hashtag / direct URL before giving up. Keep this low on non-residential egress; an explicitly selected residential proxy generally needs fewer retries on blocked targets.",
            "default": 2
          },
          "maxSearchAttempts": {
            "title": "Max search attempts",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Maximum browser-fallback attempts for each search keyword after the exact HTTP path fails. Each retry now uses a fresh page/session instead of repeating on the same blocked page.",
            "default": 2
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}