Use TikTok Post & Slideshow Detail Scraper with Python
Fetch full metadata for any TikTok video or photo-carousel post by URL or ID: engagement stats, author snapshot, music details, hashtags, mentions, and signed media URLs.
1. Choose the data you need
Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.
2. Prepare a source-based input
This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.
{
"includeAuthorStats": true,
"includeComments": false,
"includeHashtags": true,
"includeMediaUrls": true,
"includeMentions": true,
"includeRawFields": false,
"includeReplies": false,
"includeSubtitles": false,
"maxCommentsPerPost": 100,
"maxDetail": 1,
"maxItems": 1,
"mode": "posts",
"postUrls": [
"https://www.tiktok.com/@khaby.lame/video/7574844184952081686"
],
"validateMediaUrls": false
}
Download input.example.json and save your reviewed copy as input.json.
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | optional | What to scrape: individual posts, a profile's newest posts, or comment threads on posts. |
postUrls | array | optional | TikTok video/photo URLs, /v/ share links, embed links, vm.tiktok.com or vt.tiktok.com short links, or bare numeric post IDs. Duplicates are scraped once. |
postIds | array | optional | Numeric TikTok post IDs (15-20 digits). Use this instead of, or in addition to, postUrls. |
profiles | array | optional | TikTok usernames (@handle), profile URLs, or bare handles. Profiles mode returns up to 500 newest posts per profile; comments mode can use them as comment targets. |
maxItems | integer | optional | Global cap on output rows. Posts mode counts posts; profiles mode counts posts; comments mode counts comments and replies. Status rows do not count. |
maxDetail | integer | optional | How many posts get the slower page/detail enrichment (caption language, collect/repost counts, video tracks). Remaining posts use the fast embed record. Set to 1 for the smallest daily-test run. |
maxCommentsPerPost | integer | optional | Maximum comments plus replies to keep for each post in comments mode, or to attach to each post when Include comments is on. |
includeReplies | boolean | optional | Fetch the reply thread under each root comment and include replies with their parent. |
includeComments | boolean | optional | In posts/profiles mode, attach a comments array to each post. In comments mode, emit root comment rows (comments mode enables this automatically when both comment toggles are off). |
proxyConfiguration | object | optional | Optional. Leave empty to run directly; a proxy is not required. The actor falls back to an Apify datacenter proxy on a block signal. |
includeMediaUrls | boolean | optional | Include signed video, cover, music, and slideshow image URLs plus mediaUrlExpiresAt. They typically expire in about 48 hours. |
validateMediaUrls | boolean | optional | Check the main media URL with a GET Range request (TikTok's CDN rejects HEAD) and add mediaUrlAccessible. Adds latency. |
includeAuthorStats | boolean | optional | Include follower, following, heart, and video counts in author and authorStats. |
includeHashtags | boolean | optional | Include the hashtags array extracted from the caption. |
includeMentions | boolean | optional | Include the mentions array extracted from the caption with text offsets. |
includeSubtitles | boolean | optional | Include video.subtitleInfos, video.bitrateInfo, and video.volumeInfo (detail path only). |
includeRawFields | boolean | optional | Include item_control, contents, effectStickers, and stickersOnItem from the detail payload. Legacy includeEffectStickers/includeItemControl/includeContents inputs map here. |
3. Start an Actor run
Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.
Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.
import json
import os
import urllib.request
# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
actor_input = json.load(stream)
token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
"https://api.apify.com/v2/acts/VSfaWsBiswkFBVtAo/runs?timeout=120&maxTotalChargeUsd=0.50",
data=json.dumps(actor_input).encode("utf-8"),
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.
4. Inspect the actual results
Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.
Post rows with engagement stats, author snapshot, music, media, hashtags/mentions; comment rows with replies; and explicit status rows for unavailable inputs.
Questions before you run
Which inputs are required?
No top-level fields are marked required in the published schema. Conditional requirements can still apply; check the README.
What does this guide verify?
The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.
What if the run request times out?
Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.
Generated from source build Ua3QPyCof7v3HFAEk and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.