Instagram Post Stats API
Returns one post's engagement: likes, comments, and, on video posts only, the play count and the share count shown by the paper plane icon. Collab posts also list co-authors under ext.coauthors.
GET /v1/instagram/post/statsLast updated November 2026Maintained by the SocialCrawl team
When to use the Instagram Post Stats API
Use it when you need the share count for a single post, or the co-author list of one collab post; views also come on post itself, and photo posts return both numbers as null.
From the API reference
Returns full engagement stats for a single Instagram post or reel: likes, comments, the view (play) count, and the share count (engagement.shares), which is the number shown next to the paper-plane Share icon in the app. The share count is a strong authenticity signal: unlike likes and comments, shares are hard to inflate, so it helps separate genuine reach from bought engagement. The standard /v1/instagram/post endpoint cannot return the share count. Metric availability depends on the media type: likes and comments populate on every post, but Instagram exposes a view (play) count and a share count only on video media (reels, videos, and carousels containing a video). On photo posts and photo-only carousels, engagement.views and engagement.shares are null, and because computed.estimated_reach and computed.engagement_rate derive from views, they are null there too. When Instagram's response for a reel includes the save count and the two-arrows Repost ("regram") counter, the plain call returns them at engagement.saves and post.ext.repost_count; Instagram includes them on some responses and not others, so do not rely on the plain call for them. Instagram publishes no save count and no share count on photos and carousels, so engagement.saves is null there on every call. Every post carries post.ext.media_type (image, video or carousel), a carousel carries its slide count at post.ext.carousel_count, and a reel carries Instagram's remix counter at post.ext.remix_count (how many reels were made from it). include=saves is the reliable way to get them: it asks a third source for a reel's save and repost count whenever the plain call came back without them, for 4 extra credits kept only when a save count comes back; a photo or carousel is never looked up. Use this endpoint for a single post; to get the share count for every reel or post across a whole feed in one call, use /v1/instagram/profile/reels/full or /v1/instagram/profile/posts/full. This endpoint also returns the post's collaborative-post co-authors under post.ext.coauthors ({ id, username, full_name, is_verified, profile_pic_url } per account, empty array when the post is not a collab): the standard /v1/instagram/post endpoint cannot, because its web source reports every post as having no co-authors. Pass the post url (a /p/, /reel/, or /tv/ link; story URLs are not accepted, list a user's active stories with /v1/instagram/stories instead).
Searching 69 platforms in parallel
What can you do with the Post Stats API?
The Post Stats endpoint gives you structured Instagram data with computed fields in a single request. No scraping infrastructure to build or maintain.
Example Request
# GET /v1/instagram/post/stats: Metered: holds 5 credits per call up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
# Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
# --max-time 10: this endpoint's measured p99 latency x 1.5.
# --retry 3: retries timeouts, 429 and 5xx, honoring Retry-After.
# -o response.json keeps only the final attempt's body.
# One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
IDEMPOTENCY_KEY=$(od -An -N16 -tx1 /dev/urandom | tr -d ' \n')
curl -sS --max-time 10 --retry 3 -o response.json \
-H "x-api-key: YOUR_API_KEY" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
"https://www.socialcrawl.dev/v1/instagram/post/stats?url=https%3A%2F%2Fwww.instagram.com%2Fp%2FCnpPou9hWqq%2F" && cat response.json# GET /v1/instagram/post/stats: Metered: holds 5 credits per call up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
# Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
import os
import random
import time
import uuid
import requests
API_KEY = os.environ.get("SOCIALCRAWL_API_KEY", "YOUR_API_KEY")
TIMEOUT_S = 10 # this endpoint's measured p99 latency x 1.5.
MAX_RETRIES = 3
URL = "https://www.socialcrawl.dev/v1/instagram/post/stats"
def backoff(attempt):
# Exponential backoff with jitter: about 1 s, 2 s, then 4 s.
return 2 ** attempt * (0.5 + random.random() / 2)
def socialcrawl(params):
# One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
idempotency_key = str(uuid.uuid4())
for attempt in range(MAX_RETRIES + 1):
try:
res = requests.get(
URL,
params=params,
headers={"x-api-key": API_KEY, "Idempotency-Key": idempotency_key},
timeout=TIMEOUT_S,
)
body = res.json()
except (requests.RequestException, ValueError):
# A timeout, a dropped connection or a non-JSON gateway page: retry with the same key.
if attempt == MAX_RETRIES:
raise
time.sleep(backoff(attempt))
continue
if body["success"]:
return body
error = body["error"]
# Branch on error["type"], never on the message text.
if error["type"] == "RESOURCE_NOT_FOUND":
return None # refunded: nothing to read
retry_after = res.headers.get("Retry-After")
# SERVICE_UNAVAILABLE without Retry-After is a withdrawn endpoint: permanent.
permanent = error["type"] == "SERVICE_UNAVAILABLE" and retry_after is None
if not error.get("retryable") or permanent or attempt == MAX_RETRIES:
raise RuntimeError(f"{error['type']}: {error['message']} (request_id {body['request_id']})")
# Retry-After (seconds) wins; otherwise back off.
time.sleep(float(retry_after) if retry_after else backoff(attempt))
params = {
"url": "https://www.instagram.com/p/CnpPou9hWqq/",
}
body = socialcrawl(params)
if body is not None:
print(body["data"])// GET /v1/instagram/post/stats: Metered: holds 5 credits per call up front and refunds what the call does not use. Cache hits are free and failed calls are refunded.
// Check the price first for 0 credits: add dry_run=1 to the query. Nothing is fetched or charged.
const API_KEY = process.env.SOCIALCRAWL_API_KEY ?? "YOUR_API_KEY";
const TIMEOUT_MS = 10_000; // this endpoint's measured p99 latency x 1.5.
const MAX_RETRIES = 3;
type Page = { next_cursor: string | null; has_more: boolean };
type SocialCrawlResponse =
| { success: true; data: any; pagination?: Page; credits_used: number; request_id: string }
| { success: false; error: { type: string; message: string; retryable: boolean }; request_id: string };
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
// Exponential backoff with jitter: about 1 s, 2 s, then 4 s.
const backoffMs = (attempt: number) => 2 ** attempt * 1000 * (0.5 + Math.random() / 2);
async function socialcrawl(url: URL) {
// One Idempotency-Key per request, reused on every retry, so a retried call is never charged twice.
const idempotencyKey = crypto.randomUUID();
for (let attempt = 0; ; attempt++) {
let res: Response;
let body: SocialCrawlResponse;
try {
res = await fetch(url, {
headers: {
"x-api-key": API_KEY,
"Idempotency-Key": idempotencyKey,
},
signal: AbortSignal.timeout(TIMEOUT_MS),
});
body = (await res.json()) as SocialCrawlResponse;
} catch (error) {
// A timeout, a dropped connection or a non-JSON gateway page: retry with the same key.
if (attempt >= MAX_RETRIES) throw error;
await sleep(backoffMs(attempt));
continue;
}
if (body.success) return body;
// Branch on error.type, never on the message text.
if (body.error.type === "RESOURCE_NOT_FOUND") return null; // refunded: nothing to read
const retryAfter = res.headers.get("Retry-After");
// SERVICE_UNAVAILABLE without Retry-After is a withdrawn endpoint: permanent.
const permanent = body.error.type === "SERVICE_UNAVAILABLE" && retryAfter === null;
if (!body.error.retryable || permanent || attempt >= MAX_RETRIES) {
throw new Error(`${body.error.type}: ${body.error.message} (request_id ${body.request_id})`);
}
// Retry-After (seconds) wins; otherwise back off.
await sleep(retryAfter ? Number(retryAfter) * 1000 : backoffMs(attempt));
}
}
const url = new URL("https://www.socialcrawl.dev/v1/instagram/post/stats");
url.searchParams.set("url", "https://www.instagram.com/p/CnpPou9hWqq/");
const body = await socialcrawl(url);
if (body) console.log(body.data);Parameters
| Parameter | Required | Description |
|---|---|---|
| url | Yes | URL of the Instagram post (a /p/, /reel/, or /tv/ link). A share link copied from the app (`instagram.com/share/...`) works too; a share link to a profile is refused at no charge with the handle to send, and a dead one is a free 404. |
| safe_url | No | When true, returns URL-safe media links suitable for embedding. |
| include | No | Set to `saves` (one token only) to ask a third source for a reel's save count (`post.engagement.saves`) and repost count (`post.ext.repost_count`) when the plain call returned without them. 4 extra credits, kept only when a save count comes back; a repeat within the cache window is 0. Photos and carousels are never looked up, because Instagram publishes no save count on them. Adds 3 to 6 seconds when a lookup runs; read `data.hydration` for the credits held and kept and the time. (saves) |
What does the Instagram Post Stats API return?
Every response follows one unified schema. Here is a real, unmodified response body, so you can see the exact fields you get back before spending a credit.
Example response
{
"success": true,
"platform": "instagram",
"endpoint": "/v1/instagram/post/stats",
"data": {
"post": {
"id": "3020013795029641898",
"url": "https://www.instagram.com/reel/CnpPou9hWqq/",
"content": {
"text": "Mumbbongbbong😵💫🎺 \n\nJoin @sun_sim_ (Sunsim), a Maltese, and Deokseon, a bichon frise, on a magic carpet ride into the weekend. \n\n #WeeklyFluff \n\n Video by @sun_sim_",
"media_urls": "https://scontent-lga3-1.cdninstagram.com/o1/v/t2/f2/m82/AQMvIsbCtot9atknWWicTQex1s4NvrA2i8kEYhdBwyu0FaHuOg_Z1IL35MbODe8c-J9__WU2-qMKRsFOs7wtFo-hX7fdOnauV45xI2Y.mp4?_nc_cat=111&_nc_sid=5e9851&_nc_ht=scontent-lga3-1.cdninstagram.com&_nc_ohc=ymhJ-pp52qAQ7kNvwE6Gs1b&efg=eyJ2ZW5jb2RlX3RhZyI6Inhwdl9wcm9ncmVzc2l2ZS5JTlNUQUdSQU0uQ0xJUFMuQzMuNzIwLmRhc2hfYmFzZWxpbmVfMV92MSIsInhwdl9hc3NldF9pZCI6MTM5OTA5MDMzMDgzNDc0MSwiYXNzZXRfYWdlX2RheXMiOjEzNTAsInZpX3VzZWNhc2VfaWQiOjEwMDk5LCJkdXJhdGlvbl9zIjoxMiwidXJsZ2VuX3NvdXJjZSI6Ind3dyJ9&ccb=17-1&vs=87b8f7dbb0b19011&_nc_vs=HBksFQIYT2lnX3hwdl9yZWVsc19wZXJtYW5lbnRfcHJvZC9GRjQzRDJDMEI0MUM2NjVCM0EzMEFDNkE2NDBDRTRBOV92aWRlb19kYXNoaW5pdC5tcDQVAALIARIAFQIYOnBhc3N0aHJvdWdoX2V2ZXJzdG9yZS9HQlZTZXhNSGI0amF5dEFFQUJZaEVIV0JuVHBMYnFfRUFBQUYVAgLIARIAKAAYABsCiAd1c2Vfb2lsATEScHJvZ3Jlc3NpdmVfcmVjaXBlATEVAAAm6tzsouOd_AQVAigCQzMsF0ApZmZmZmZmGBJkYXNoX2Jhc2VsaW5lXzFfdjERAHX-B2XmnQEA&_nc_gid=jUC2jCkUzsOf7fOsQnaz0g&_nc_ss=733ba&_nc_zt=28&oh=00_AQM8vihMXlqyWn76ZCVyfZI59SW3ZwtHcuM4UbzfVyF3dA&oe=6AC1B10C",
"thumbnail_url": "https://scontent-lga3-2.cdninstagram.com/v/t51.71878-15/491414458_1934794933930942_6214267858142308860_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=101&ig_cache_key=MzAyMDAxMzc5NTAyOTY0MTg5OA%3D%3D.3-ccb7-5&ccb=7-5&_nc_sid=58cdad&efg=eyJ2ZW5jb2RlX3RhZyI6IkNMSVBTLnhwaWRzLjcyMC5zZHIudmlkZW9fZGVmYXVsdF9jb3Zlcl9mcmFtZS5DMyJ9&_nc_ohc=uGUD5PzbNQEQ7kNvwEH7szm&_nc_oc=Adri7HHQy1sirgBp5L6PrlCm3tNR7m-QBOmaN410XnkZZPRVlGnUs5Q7e4FCzg7YqgU&_nc_ad=z-m&_nc_cid=0&_nc_zt=23&_nc_ht=scontent-lga3-2.cdninstagram.com&_nc_gid=jUC2jCkUzsOf7fOsQnaz0g&_nc_ss=733ba&oh=00_AQM5jW80toSLVOnwaaCMoy7vBrwdF9qX4HuMRQi1RcU3Wg&oe=6AC58B6B",
"duration_seconds": 12.7
},
"author": {
"username": "instagram",
"display_name": "Instagram",
"avatar_url": "https://scontent-lga3-3.cdninstagram.com/v/t51.82787-19/550891366_18667771684001321_1383210656577177067_n.jpg?stp=dst-jpg_e0_s150x150_tt6&_nc_cat=1&ig_cache_key=GGbv1SApFvlLPVJCAOtF0XrDJjITbmNDAQAB1501500j-ccb7-5&ccb=7-5&_nc_sid=669407&efg=eyJ2ZW5jb2RlX3RhZyI6InByb2ZpbGVfcGljLnd3dy4xMDgwLkMzIn0%3D&_nc_ohc=_dBpg1akaE4Q7kNvwEzSMUO&_nc_oc=Adp9q_1Hrmtqt3yFS7bzLmqMIgR0CmP3FcRmB19tdTIu1Cfkhh3iiYM1aODNYACuWkQ&_nc_ad=z-m&_nc_cid=0&_nc_zt=24&_nc_ht=scontent-lga3-3.cdninstagram.com&_nc_gid=jUC2jCkUzsOf7fOsQnaz0g&_nc_ss=733ba&oh=00_AQNIpSLWw0UZdi6WlpjJ0nI7_alvrmUQ0w9uk4IU0vIufQ&oe=6AC59627",
"verified": true
},
"engagement": {
"views": 45016542,
"likes": 1390842,
"comments": 16381,
"shares": 47,
"saves": null
},
"flags": {
"nsfw": null,
"spoiler": null,
"pinned": false,
"deleted": false
},
"published_at": "2023-01-20T16:56:42.000Z",
"ext": {
"ig_play_count": 45016542,
"repost_count": null,
"media_type": "video",
"remix_count": 197,
"published_at_epoch": 1674233802,
"coauthors": []
}
},
"computed": {
"engagement_rate": 0.031261,
"language": "en",
"content_category": "other",
"estimated_reach": 54019850
}
},
"credits_used": 5,
"request_id": "req_example000000",
"cached": false,
"credits_remaining": 9999,
"source": "captured",
"captured_at": "2026-10-02T15:37:11.366Z",
"redacted": true
}Live sample illustrating the unified response shape. Field values reflect the record you query.
How does the Instagram Post Stats API work?
Send a GET request with your API key and get back clean, structured JSON in our unified schema. Supported computed fields are populated when the source provides the required inputs.
Method
GET
Response
JSON
How do you scrape social media data in seconds?
The fastest social media scraping API for developers. Scrape profiles, posts, comments, and analytics from 69 platforms covering 10B+ monthly active users.
One schema, every platform
Query 69 platforms with identical response structures. Write your integration once.
Computed fields, not just scraped
When an endpoint supports these metrics and the source provides the required inputs, the normalized record includes engagement_rate, estimated_reach, content_category, and language. Ready to use.
See your data before you code
Visual Data Explorer. Paste any URL, get rich result cards, sortable tables, CSV export.
import requests
response = requests.get(
'https://www.socialcrawl.dev/v1/tiktok/profile',
params={'handle': 'charlidamelio'},
headers={'x-api-key': 'sc_YOUR_API_KEY'}
)
data = response.json(){
"success": true,
"platform": "tiktok",
"data": {
"author": {
"username": "charlidamelio",
"followers": 152400000
},
"engagement": {
"likes": 12400000000,
"engagement_rate": 0.087
},
"metadata": {
"language": "en",
"content_category": "lifestyle"
}
}
}Have a question? We got answers
Find answers to frequently asked questions about SocialCrawl's API, pricing, and capabilities.
Contact usHow do I get the share count for an Instagram post?
Why can't the standard post endpoint return share count?
Why does the share count matter for authenticity?
Does it return the save count or the repost count?
What post URLs and pricing does the endpoint use?
Ask AI about SocialCrawl
Ready to scrape Instagram Post Stats data?
Get your API key and start pulling Instagram data in under 60 seconds.
