{
  "openapi": "3.0.1",
  "info": {
    "title": "TikTok Comments Scraper - Comments, Authors & Likes",
    "description": "Scrape comments from TikTok videos using one or more video URLs or IDs. Extract comment text, author, likes, reply count and timestamp in clean structured data. Supports multiple videos in a single run with no login required.",
    "version": "0.1",
    "x-build-id": "64MCnfvKSOvRYwhgU"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~tiktok-comments-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-tiktok-comments-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/abotapi~tiktok-comments-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-tiktok-comments-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/abotapi~tiktok-comments-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-tiktok-comments-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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "videos",
              "search"
            ],
            "type": "string",
            "description": "How to choose the videos. 'videos': scrape the video URLs/ids you paste. 'search': give usernames and the actor walks their recent videos, then scrapes comments on those.",
            "default": "videos"
          },
          "videoUrls": {
            "title": "Video URLs or IDs",
            "type": "array",
            "description": "One or more TikTok videos to pull comments from. Paste the full video URL (https://www.tiktok.com/@user/video/1234567890) or just the numeric video id. Short share links (vm.tiktok.com) are not supported.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "usernames": {
            "title": "Usernames",
            "type": "array",
            "description": "One or more TikTok usernames (with or without @). The actor lists each account's recent videos and scrapes their comments.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxVideosPerUser": {
            "title": "Max videos per username (search mode)",
            "minimum": 0,
            "type": "integer",
            "description": "How many of each account's most recent videos to scan for comments. 0 = unlimited.",
            "default": 10
          },
          "minCommentLikes": {
            "title": "Minimum comment likes",
            "minimum": 0,
            "type": "integer",
            "description": "Only keep comments with at least this many likes. 0 = no minimum.",
            "default": 0
          },
          "commentKeyword": {
            "title": "Comment text contains",
            "type": "string",
            "description": "Only keep comments whose text contains this word or phrase (case-insensitive). Leave empty for no text filter."
          },
          "excludeReplies": {
            "title": "Exclude replies",
            "type": "boolean",
            "description": "Keep only top-level comments and drop replies to other comments.",
            "default": false
          },
          "commentsSinceDays": {
            "title": "Only comments from the last N days",
            "minimum": 0,
            "type": "integer",
            "description": "Drop comments older than this many days. 0 = no date filter.",
            "default": 0
          },
          "fetchReplies": {
            "title": "Fetch replies",
            "type": "boolean",
            "description": "Also try to collect replies. The source currently returns no reply rows for automated sessions, so this usually adds nothing; leave it off unless you want to try.",
            "default": false
          },
          "maxRepliesPerComment": {
            "title": "Max replies per comment",
            "minimum": 0,
            "type": "integer",
            "description": "Cap on replies collected per comment when reply fetching is enabled. 0 = unlimited.",
            "default": 5
          },
          "replyPatienceSeconds": {
            "title": "Seconds per reply page",
            "minimum": 3,
            "type": "integer",
            "description": "Time budget for each reply request. Only used when reply fetching is enabled.",
            "default": 10
          },
          "maxCommentsPerVideo": {
            "title": "Max comments per video",
            "minimum": 0,
            "type": "integer",
            "description": "How many comments to collect from each video. 0 = unlimited.",
            "default": 20
          },
          "maxPagesPerVideo": {
            "title": "Max pages per video",
            "minimum": 0,
            "type": "integer",
            "description": "Safety cap on result pages per video. 0 = no page limit (the comment cap above still applies).",
            "default": 0
          },
          "pagePatienceSeconds": {
            "title": "Seconds per page",
            "minimum": 5,
            "type": "integer",
            "description": "The source answers only a share of requests, and only during certain windows (sometimes shut for a minute or more), so each page keeps being requested until one succeeds or this budget runs out. Raise it for stubborn videos.",
            "default": 120
          },
          "maxAttemptsPerPage": {
            "title": "Max requests per page (optional ceiling)",
            "minimum": 0,
            "type": "integer",
            "description": "Optional hard ceiling on requests per page. 0 = no ceiling (the seconds budget above is the only limit).",
            "default": 0
          },
          "concurrency": {
            "title": "Parallel requests",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many requests run at the same time. Higher samples more exits per second. 20 is the maximum.",
            "default": 20
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large crawl without re-collecting or re-billing comments already saved there."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for recurring monitoring: each comment is labelled NEW, UPDATED, UNCHANGED or REAPPEARED against the remembered baseline, and unchanged comments are not returned. Turn on Emit unchanged or Emit expired only if you also want those rows returned (and billed).",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional name for this monitoring campaign. Leave empty to let the actor derive a key from the videos and filters."
          },
          "emitUnchanged": {
            "title": "Emit unchanged comments (incremental mode only)",
            "type": "boolean",
            "description": "Return comments that did not change since the last run. Off by default because unchanged rows are usually noise.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired comments (incremental mode only)",
            "type": "boolean",
            "description": "Return comments that were in the baseline but are gone this run. Only emitted after a run that provably finished the whole tracked scope.",
            "default": false
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          },
          "proxyTier": {
            "title": "Proxy tier",
            "enum": [
              "datacenter",
              "residential"
            ],
            "type": "string",
            "description": "Datacenter is the default and is enough for this source. Residential is available if datacenter runs return too few comments.",
            "default": "datacenter"
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Leave apifyProxyGroups unset so the 'Proxy tier' field above decides. Set it here only to pin a non-standard group. Leave the country empty; exits rotate automatically."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}