{
  "openapi": "3.0.1",
  "info": {
    "title": "TikTok Comments Scraper API - Replies, Handles, No Login ✅",
    "description": "Scrape TikTok video comments AND their threaded replies in one Actor. Get text, like counts, reply counts, commenter handles, timestamps. Built for sentiment analysis, customer voice research, brand monitoring, and creator engagement audits. No login, no API key.",
    "version": "0.0",
    "x-build-id": "A0Ql8oGwshIK5tgxa"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/unseenuser~tiktok-comments-replies-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-unseenuser-tiktok-comments-replies-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/unseenuser~tiktok-comments-replies-scraper/runs": {
      "post": {
        "operationId": "runs-sync-unseenuser-tiktok-comments-replies-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/unseenuser~tiktok-comments-replies-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-unseenuser-tiktok-comments-replies-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": {
          "video_urls": {
            "title": "TikTok video URLs",
            "type": "array",
            "description": "One TikTok video URL per line. Example: https://www.tiktok.com/@username/video/7480123456789012345. Advanced: to fetch replies under one specific comment only, add ::commentId after the URL (for example, https://www.tiktok.com/@user/video/7458970460613004574::7458975511234567890).",
            "items": {
              "type": "string",
              "pattern": "^https?://(www\\.|m\\.|vm\\.|vt\\.)?tiktok\\.com/.+"
            },
            "default": [
              "https://www.tiktok.com/@lycomps2/video/7665012083515378947"
            ]
          },
          "max_comment_pages": {
            "title": "Comment batches to fetch (0 = all comments)",
            "minimum": 0,
            "type": "integer",
            "description": "Each batch is one request to TikTok that returns about 20 to 50 comments. Leave 0 to keep fetching until every comment on the video has been pulled. If you enter a specific number, the safety cap is 50000 batches (about 1,000,000 to 2,500,000 comments) to catch a mis-typed run before it consumes an unexpected amount of your budget - it is not a technical limit.",
            "default": 0
          },
          "auto_fetch_replies": {
            "title": "Auto-fetch replies",
            "type": "boolean",
            "description": "When on, replies are automatically fetched for top-level comments that meet the threshold below.",
            "default": false
          },
          "min_replies_threshold": {
            "title": "Only expand comments with at least this many replies (0 = every comment)",
            "minimum": 0,
            "type": "integer",
            "description": "Skip fetching the reply thread for comments that already have fewer than this many replies. Leave 0 to fetch replies for every comment, no matter how few. This is a filter, so a higher value means fewer requests - there is no cap.",
            "default": 0
          },
          "max_reply_pages_per_comment": {
            "title": "Reply batches per comment (0 = all replies)",
            "minimum": 0,
            "type": "integer",
            "description": "Each batch is one request to TikTok that returns about 20 to 50 replies. Leave 0 to keep fetching until every reply under the comment has been pulled. If you enter a specific number, the safety cap is 50000 batches (about 1,000,000 to 2,500,000 replies) to catch a mis-typed run before it consumes an unexpected amount of your budget - it is not a technical limit.",
            "default": 0
          },
          "include_video_metadata": {
            "title": "Include video metadata + engagement flags",
            "type": "boolean",
            "description": "Adds video_id, video_url, is_pinned, is_author_liked, language, share_url, sort_tags, is_translatable, and (for replies) is_high_purchase_intent, reply_to_reply_id, thread_id.",
            "default": false
          },
          "include_author_details": {
            "title": "Include author verification + secure IDs",
            "type": "boolean",
            "description": "Adds user.verified (bool) + user.verify_reason (string) + user.sec_uid (stable secure ID useful for cross-run linking).",
            "default": false
          },
          "include_parsed_text": {
            "title": "Include parsed mentions + hashtags",
            "type": "boolean",
            "description": "Adds mentions[] and hashtags[] arrays parsed from the comment text_extra structure.",
            "default": false
          },
          "include_algorithm_scores": {
            "title": "Include TikTok's own algorithm scores",
            "type": "boolean",
            "description": "Adds algorithm_score (reply_score + show_more_score) - the ranking numbers TikTok itself computes for each comment. Useful for filtering to top-ranked comments.",
            "default": false
          },
          "include_experimental_fields": {
            "title": "Include experimental fields",
            "type": "boolean",
            "description": "Adds user.predicted_age_group - TikTok's own age-bucket estimate as a raw string (values like '3', '4'). TikTok does not publish the value-to-age mapping, so treat this as experimental. Consider your obligations under minor-protection laws before using it as a filter.",
            "default": false
          },
          "anthropic_api_key": {
            "title": "Anthropic API key",
            "type": "string",
            "description": "Your Anthropic API key (starts with sk-ant-). Required only when any enable_sentiment / enable_intent_classification / enable_audience_summary is on. Stored as a secret - never logged or written to output."
          },
          "enable_sentiment": {
            "title": "Enable sentiment classification",
            "type": "boolean",
            "description": "Adds sentiment_score (-1 to 1) and sentiment_label (positive|neutral|negative) to every comment and reply row. Batched to keep cost low. Requires an Anthropic API key above.",
            "default": false
          },
          "enable_intent_classification": {
            "title": "Enable intent classification",
            "type": "boolean",
            "description": "Adds intent (question|complaint|praise|spam|purchase_intent|mention|other) to every comment and reply row. Batched with sentiment when both are on.",
            "default": false
          },
          "enable_audience_summary": {
            "title": "Enable per-video audience summary",
            "type": "boolean",
            "description": "Writes ONE video_summary row per video with themes[], top_questions[], sentiment_breakdown{positive,neutral,negative}, and buyer_intent_count. Uses the top 200 comments by likes to control cost on huge videos.",
            "default": false
          },
          "enable_translation": {
            "title": "Enable translation",
            "type": "boolean",
            "description": "Adds translated_text to every comment and reply row (translated to the target language below). Batched together with sentiment / intent / bot detection - if any of those are on, translation piggybacks on the same LLM call at no extra event cost.",
            "default": false
          },
          "translation_target_language": {
            "title": "Translation target language",
            "enum": [
              "af",
              "ar",
              "bn",
              "bg",
              "my",
              "zh",
              "hr",
              "cs",
              "da",
              "nl",
              "en",
              "fil",
              "fi",
              "fr",
              "de",
              "el",
              "gu",
              "he",
              "hi",
              "hu",
              "id",
              "it",
              "ja",
              "kn",
              "km",
              "ko",
              "ms",
              "ml",
              "mr",
              "ne",
              "no",
              "fa",
              "pl",
              "pt",
              "pa",
              "ro",
              "ru",
              "sr",
              "si",
              "sk",
              "es",
              "sw",
              "sv",
              "ta",
              "te",
              "th",
              "tr",
              "uk",
              "ur",
              "vi"
            ],
            "type": "string",
            "description": "Language to translate comments into. Ignored when enable_translation is off. Defaults to English. Chinese defaults to Simplified. If you need a language not listed here, tell the Actor developer via Apify contact.",
            "default": "en"
          },
          "enable_bot_detection": {
            "title": "Enable bot / spam detection",
            "type": "boolean",
            "description": "Adds is_bot_likely (boolean) + bot_confidence (0-1) to every comment and reply row. Piggybacks on the same LLM call as sentiment / intent / translation - no extra event cost when any of those is also on.",
            "default": false
          },
          "exclude_pinned": {
            "title": "Exclude pinned comments",
            "type": "boolean",
            "description": "If true, drops the video creator's pinned comment(s) from the output. Uses TikTok's author_pin flag. Default false.",
            "default": false
          },
          "date_from": {
            "title": "Only include comments from this date onward",
            "type": "string",
            "description": "Drops any comment or reply older than this date. Leave empty for no lower bound. Comments are still fetched from upstream and then filtered client-side, so upstream credits are still consumed for dropped rows.",
            "default": ""
          },
          "date_to": {
            "title": "Only include comments up to this date",
            "type": "string",
            "description": "Drops any comment or reply newer than this date. Leave empty for no upper bound. Same client-side-filter caveat as date_from.",
            "default": ""
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}