Post metrics
Read a public post's views, likes, comments, shares and saves, its caption and its owner, straight from the post URL.
Counts are read from the platform at the moment you call and never stored, so call again whenever you want newer numbers.
One post
curl -G {API_BASE_URL}/v1/stats \
-H "Authorization: Bearer <API_TOKEN>" \
--data-urlencode "url=https://www.tiktok.com/@creator/video/7300000000000000000"const params = new URLSearchParams({ url: "https://www.tiktok.com/@creator/video/7300000000000000000" });
const res = await fetch(`${API_BASE_URL}/v1/stats?${params}`, {
headers: { Authorization: `Bearer ${API_TOKEN}` },
});
const { owner, stats } = await res.json();{
"platform": "tiktok",
"contentType": "video",
"postUrl": "https://www.tiktok.com/@creator/video/7300000000000000000",
"owner": {
"handle": "creator",
"accountId": "7198363676607530026",
"secUid": "MS4wLjAB...",
"displayName": "Creator"
},
"post": {
"caption": "New video",
"postedAt": "2026-09-22T18:30:00.000Z",
"thumbnailUrl": "https://...",
"mediaUrls": ["https://..."]
},
"stats": {
"views": 125000,
"likes": 5432,
"comments": 312,
"shares": 89,
"saves": 144
},
"source": "provider"
}| Field | Notes |
|---|---|
contentType | post or reel on Instagram, video on TikTok |
postUrl | The cleaned-up post URL, without share tags or other query parameters |
owner.accountId | The platform's id for the account that posted. It stays the same when the handle changes |
owner.secUid | TikTok only; null on Instagram |
post.thumbnailUrl, post.mediaUrls | Signed platform URLs that expire. Download the files promptly if you need to keep them |
stats.views | Reels and TikTok videos; null for Instagram image posts |
stats.shares, stats.saves | Always null on Instagram, which does not show them publicly |
source | provider normally; fallback when a second read path answered, see below |
Any metric is null when the platform does not expose it, for example when the author hides the like count.
Check ownership with accountId
To confirm a post belongs to a creator, compare owner.accountId with the accountId from their creator profile, not the handle in the URL. A handle can change or be typed wrong; the account id cannot.
Fallback reads
Some Instagram posts, such as age-restricted ones, cannot be read the usual way. The API then tries a second read path and, if that works, answers 200 with source: "fallback". A fallback read carries the views, likes, comments and thumbnail, but owner is all null, caption and postedAt are null, and mediaUrls is empty. Do not use a fallback read for an ownership check.
Up to 25 posts in one call
Instagram and TikTok URLs can be mixed. Results come back in the order you sent them.
curl -X POST {API_BASE_URL}/v1/stats/batch \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://www.tiktok.com/@creator/video/7300000000000000000",
"https://www.instagram.com/p/GONE/"
]
}'{
"results": [
{
"url": "https://www.tiktok.com/@creator/video/7300000000000000000",
"ok": true,
"platform": "tiktok",
"contentType": "video",
"postUrl": "https://www.tiktok.com/@creator/video/7300000000000000000",
"owner": { "handle": "creator", "accountId": "7198363676607530026", "secUid": "MS4wLjAB...", "displayName": "Creator" },
"post": { "caption": "New video", "postedAt": "2026-09-22T18:30:00.000Z", "thumbnailUrl": "https://...", "mediaUrls": ["https://..."] },
"stats": { "views": 125000, "likes": 5432, "comments": 312, "shares": 89, "saves": 144 },
"source": "provider"
},
{
"url": "https://www.instagram.com/p/GONE/",
"ok": false,
"error": { "code": "POST_NOT_FOUND", "message": "Post not found" }
}
],
"summary": { "total": 2, "succeeded": 1, "failed": 1 }
}Each URL succeeds or fails on its own. A successful result has the same fields as a single lookup, and url is the URL exactly as you sent it. A failed result carries the error code that URL would have returned alone, inside error.code; note that this is an object here, not the plain error string of a single call.
| Status | Meaning |
|---|---|
200 | The batch ran. A failed post does not fail the batch, so check ok on every result |
422 VALIDATION_ERROR | The body is not { "urls": [...] } with 1 to 25 entries. Nothing was read |
429 RATE_LIMITED | The batch would go past 60 URLs per minute from your client IP. Wait for Retry-After |
- Duplicates. A URL sent twice is read once and returned in both positions.
- Deadline. A batch stops after 100 seconds. URLs not finished by then come back with
BATCH_TIMEOUT; send them again in a new batch. - Usage. Each distinct post that succeeds counts as one lookup. Failed and timed-out URLs do not count.
Errors
When the post cannot be read, the single lookup returns one of the data lookup errors. 404 and 422 are permanent for that post; 429, 502 and 503 are worth retrying.
Last updated on