GET /v1/post
One post from any of the four platforms, normalized to a single shape. Pass the post's URL; the platform is detected from it.
Request
curl "https://tikdata.io/v1/post?url=https://www.tiktok.com/@tiktok/video/7680721699171601694" \
-H "Authorization: Bearer thr_live_xxx"
| param | required | notes |
|---|---|---|
url |
yes | any TikTok, Instagram, YouTube or X post URL (URL-encode it) |
platform |
no | tiktok | instagram | youtube | x — overrides detection |
Accepted URL forms:
| platform | forms |
|---|---|
| TikTok | tiktok.com/@user/video/{id}, /photo/{id}, /v/{id} |
instagram.com/p/{code}/, /reel/{code}/, /tv/{code}/ |
|
| YouTube | youtube.com/watch?v={id}, /shorts/{id}, /embed/{id}, youtu.be/{id} |
| X | x.com/{user}/status/{id}, twitter.com/{user}/status/{id} |
TikTok short links (tiktok.com/t/…) are not resolved — follow the redirect first, or use /v1/raw with fetch_one_video_by_share_url.
Response — 200
{
"platform": "tiktok",
"id": "7680721699171601694",
"url": "https://www.tiktok.com/@tiktok/video/7680721699171601694",
"caption": "this summer was all about the classic hits…",
"cover": "https://p16-common-sign.tiktokcdn-us.com/…",
"createdAt": "2026-09-02T00:03:08.000Z",
"author": { "handle": "tiktok", "name": "TikTok", "followers": 95663434 },
"stats": {
"views": 202473,
"likes": 8267,
"comments": 1261,
"shares": 631,
"saves": 922,
"reposts": 0,
"quotes": 0,
"downloads": 40
}
}
| field | type | notes |
|---|---|---|
platform |
string | detected or forced |
id |
string | the platform's own post id (Instagram: the shortcode) |
url |
string | the URL you passed |
caption |
string | "" if none |
cover |
string | thumbnail URL; TikTok single-video covers are HEIC |
createdAt |
ISO 8601 | null | |
author.handle |
string | bare handle, no @ |
author.name |
string | display name |
author.followers |
integer | see per-platform notes |
stats.* |
integer | every engagement number the platform exposes; 0 where it does not |
What each platform reports
| views | likes | comments | shares | saves | reposts | quotes | downloads | |
|---|---|---|---|---|---|---|---|---|
| TikTok | play_count | digg_count | comment_count | share_count | collect_count | repost_count | — | download_count |
| play_count | like_count | comment_count | share_count | save_count | repost_count | — | — | |
| X | views | likes | replies | retweets | bookmarks | retweets | quotes | — |
| YouTube | view_count | like_count | comment_count | — | — | — | — | — |
A dash means the platform does not expose that number publicly; the field is present and 0.
On X a repost is the share mechanism, so shares and reposts carry the same number there by design — a caller summing shares across platforms gets a comparable figure instead of a 0.
Per-platform notes
- TikTok —
author.followersis the author's live follower count. Cover images are HEIC; the feed endpoint's covers are webp if you need something vision models can decode. - Instagram — uses the provider's
v2/fetch_post_info, the only Instagram post endpoint that returns likes, shares, saves and reposts. It costs$0.002per call versus$0.001for the basic endpoint.author.followersis0— the post payload's user object does not carry it; use/v1/profilefor that. - X —
author.followerscomes from the tweet's embedded author block. Numbers are read from the flattened top level, so a quoted or retweeted tweet's stats can never leak in. - YouTube —
commentsis parsed from an abbreviated display string ("2.4M") and is therefore rounded.author.followersis subscribers, also from a display string ("4.54M subscribers").
Missing vs gone
Missing individual stats are 0, never an error — platforms omit different fields and a partial answer beats a failed refresh.
A deleted or unknown post is a 404, never a post with zeroed stats:
{ "error": "post not found", "platform": "tiktok", "id": "9999999999999999999", "url": "…" }
The provider answers 200 with the post object omitted for dead content; the router checks for it explicitly. Private and deleted are not distinguishable — see errors.
Errors
| status | body |
|---|---|
| 400 | {"error":"url is required","hint":"GET /v1/post?url=https://www.tiktok.com/@x/video/123"} |
| 400 | {"error":"unrecognized url","hint":"supported: tiktok, instagram, youtube, x"} |
| 400 | {"error":"could not extract a tiktok post id from that url"} |
| 404 | {"error":"post not found", …} |
| 502 | {"error":"upstream error","status":500,"platform":"…","upstream":{…}} or {"error":"upstream unreachable"} |
Fallbacks
TikTok tries three independent backends, Instagram two, YouTube two; X has one (no working alternate exists on this node, so it retries instead). A backend that answers 200 with nothing is treated as blind and the next is tried; a 5xx or dropped connection is retried on the same one. x-router-source and x-router-attempts on the response say which answered and what it cost. Full detail in errors.
Billing
One upstream call per request when the first backend answers — the common case. A post that no backend can serve costs the whole chain (3 calls on TikTok) before returning 404, which is the price of never reporting a live post as deleted. Billed by the provider whether or not the post still exists. Instagram costs $0.002 rather than $0.001 (see above).