# Instagram Reels Stats API: 12 Reels, 2 Credits (https://www.socialcrawl.dev/blog/instagram-reels-stats-api)
> Instagram Reels Stats API: 12 public reels with views, likes, shares, and saves for 2 credits. Graph Insights still needs a Page you own. Live 2026-09-15.
On 2026-09-15, `GET /v1/instagram/profile/reels?handle=anaheubl&include=stats` returned **12** public reels with views, likes, comments, shares, saves, reposts, remix (0, filled), and audio id for **2 credits**. No Facebook Page. No app review. Header `x-api-key`. That is an Instagram reels stats API on a public handle.
This is a read of counts on a public reels page, not Graph `media_publish`. The Instagram reels API list path and named 404s live on [Instagram API: About is back, 1 credit, named 404s](/blog/instagram-api-reliability). [What Instagram counts as a view](/blog/how-instagram-counts-views) is the 425-post benchmark. This post is the API that returns the counts on a page for 2 credits.
Twelve separate `GET /v1/instagram/post/stats` calls billed **5** each this run would be **60**. The stats page did it in **2**.
**Stack:** curl + Python `requests` · `GET https://www.socialcrawl.dev/v1/instagram/…` · header `x-api-key`. Real captured JSON from this night, including the nulls.
## How do you get a full Instagram Reels stats page in one call?
A public-handle Instagram reels stats API call is one page, not twelve follow-ups. `include=stats` on `GET /v1/instagram/profile/reels` fills views, likes, comments, shares, saves, reposts, remix, and audio id on the reels tab. Existing 1-credit calls keep the same shape. `include=stats` is opt-in.
```bash
curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \
"https://www.socialcrawl.dev/v1/instagram/profile/reels?handle=anaheubl&include=stats"
```
`req-QlBhdv4tv3RZYy2g` (harvest 2026-09-15), **2 credits**, `cached: false`, `items.length = 12`, `dropped = 0`, `pagination.has_more = true`. Every count below is frozen to that request. Live numbers moved later in the same hour.
| # | Reel | Views | Likes | Comments | Shares | Saves | Reposts | Remix | Audio |
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 0 | [DZpHFjVOHrz](https://www.instagram.com/reel/DZpHFjVOHrz/) | 8,545,975 | 728,794 | 160 | 57,245 | 35,348 | 17,703 | 0 | Original audio / anaheubl |
| 1 | [DdQ1J_fuleG](https://www.instagram.com/reel/DdQ1J_fuleG/) | 444,290 | 20,417 | 101 | 6,895 | 1,208 | 388 | 0 | Original audio / anaheubl |
| 2 | [DdPF34IOz9o](https://www.instagram.com/reel/DdPF34IOz9o/) | 299,049 | 5,199 | 14 | 123 | 115 | 7 | 0 | Original audio / anaheubl |
| 3 | [DdKHLZDOkes](https://www.instagram.com/reel/DdKHLZDOkes/) | 375,965 | 10,798 | 18 | 724 | 906 | 32 | 0 | Original audio / anaheubl |
| 4 | [Dc6eUKGO3fZ](https://www.instagram.com/reel/Dc6eUKGO3fZ/) | 306,534 | 9,436 | 54 | 129 | 170 | 6 | 0 | Original audio / anaheubl |
| 5 | [Dc4By47uHm3](https://www.instagram.com/reel/Dc4By47uHm3/) | 220,567 | 7,816 | 130 | 139 | 217 | 13 | 0 | Original audio / anaheubl |
| 6 | [Dc1dtaUO9_9](https://www.instagram.com/reel/Dc1dtaUO9_9/) | 525,998 | 26,797 | 137 | 459 | 481 | 43 | 0 | Original audio / anaheubl |
| 7 | [Dc1EfXGOivq](https://www.instagram.com/reel/Dc1EfXGOivq/) | 130,882 | 1,870 | 12 | 52 | 141 | 3 | 0 | Original audio / anaheubl |
| 8 | [Dcy6R0DuMRZ](https://www.instagram.com/reel/Dcy6R0DuMRZ/) | 530,162 | 15,792 | 43 | 602 | 421 | 65 | 0 | Original audio / anaheubl |
| 9 | [DcviDl6uoow](https://www.instagram.com/reel/DcviDl6uoow/) | 102,073 | 3,782 | 16 | 6 | 42 | 7 | 0 | Original audio / anaheubl |
| 10 | [DcqGdnrOiNv](https://www.instagram.com/reel/DcqGdnrOiNv/) | 399,386 | 16,572 | 26 | 181 | 304 | 32 | 0 | Original audio / anaheubl |
| 11 | [DcoQWsQsNSn](https://www.instagram.com/reel/DcoQWsQsNSn/) | 583,105 | 18,246 | 72 | 112 | 237 | 15 | 0 | Voulez-Vous / ABBA |
Filled on this page: `engagement.views`, `.likes`, `.comments`, `.shares`, `.saves`, `ext.repost_count`, `ext.remix_count`, and `ext.music_id` (+ title + artist) on **12 / 12**. `ext.media_type` is `video` on 12 / 12. Remix is **0** on every row — a filled zero, not null. Do not read that as "Instagram has no remix count."
If you wanted an Instagram reels views API, this page already has views on all 12 rows. What those views *mean* is the [425-post benchmark](/blog/how-instagram-counts-views), not this post.
Trimmed `items[0]` from that same request:
```json
{
"id": "3920696118462675699",
"url": "https://www.instagram.com/reel/DZpHFjVOHrz/",
"content": {
"text": "So dankbar für unsere kleine Familie 💓",
"duration_seconds": 7.533
},
"author": {
"username": "anaheubl",
"display_name": "Ana Heubl",
"verified": true
},
"engagement": {
"views": 8545975,
"likes": 728794,
"comments": 160,
"shares": 57245,
"saves": 35348
},
"ext": {
"repost_count": 17703,
"remix_count": 0,
"media_type": "video",
"music_id": "36562246683389576",
"music": {
"id": "36562246683389576",
"track_title": "Original audio",
"artist": "anaheubl",
"is_original": true
}
},
"computed": {
"engagement_rate": 0.091996
}
}
```
`computed.engagement_rate` is `(likes + comments + shares) / views`. On this reel: `(728794 + 160 + 57245) / 8545975 = 0.091996`. **Saves are not in the formula.** An Instagram engagement API that only sums likes and comments would miss the 57,245 shares sitting on that row.
Audio id filled on **12 / 12** rows of this 2-credit page, 11 original sounds and 1 licensed track.
`@anaheubl` is a verified German-language creator. Counts, fill rates, and OCR language below are this account on this night, not a platform-wide benchmark.
### What the 1-credit plain page leaves null
```bash
curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \
"https://www.socialcrawl.dev/v1/instagram/profile/reels?handle=anaheubl"
```
`req-XnzLx8AAZVKR5ZIH`, **1 credit**, 12 reels. `engagement.shares`, `engagement.saves`, and `ext.repost_count` were **null on 12 / 12**. `ext.remix_count` was still filled (all 0). Licensed music already arrived on the plain call (the ABBA row); original sounds needed `include=stats` this run.
URL overlap with the stats page was **11 / 12**. Stats-only: `DZpHFjVOHrz`. Plain-only: `DcmLD9_OO7i`. `include=stats` is a second read of the tab. Treat the two pages as two reads, not one shared set of twelve.
### Graph Insights still needs a Page
[Instagram Platform Insights](https://developers.facebook.com/documentation/instagram-platform/insights) "returns only data for media owned by Instagram professional accounts." Endpoints are per object: `GET /MEDIA_ID/insights` and `GET /ACCOUNT_ID/insights`. Facebook Login usually needs a Facebook Page. Serving other professional accounts needs [App Review](https://developers.facebook.com/documentation/instagram-platform/overview). That is the official Instagram analytics API. It is not a public-handle read.
| | Graph Insights | This call |
| --- | --- | --- |
| Who | Media you own. Professional account. Usually a Facebook Page. App review for Advanced Access. | Public handle, `x-api-key` |
| Shape | `GET /MEDIA_ID/insights` per object | One page of 12 reels |
| Official media example | `engagement` (likes + comments), `impressions` (deprecated on new media), `reach` | views, likes, comments, shares, saves, reposts, remix, audio id |
The current [REELS metric list](https://developers.facebook.com/documentation/instagram-platform/reference/instagram-media/insights) does document `views`, `saved`, `shares`, and `reposts` — on media you own. [Business Discovery](https://developers.facebook.com/documentation/instagram-platform/instagram-api-with-facebook-login/business-discovery) can return `like_count`, `comments_count`, and `view_count` on other professional accounts. It does not document saves, shares, reposts, remix, or audio id. There is no official Graph path that returns Insights-grade saves and shares on a public handle you do not manage.
The [Help Center Insights UI](https://help.instagram.com/1533933820244654) is a dashboard click-path, not an API. This is not a consumer `instagram analytics` / `instagram insights` walkthrough. For a vendor list, see [best Instagram data APIs](/blog/best-instagram-data-apis-2026).
### Single-reel `post/stats` on the 8.5M reel
```bash
curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \
"https://www.socialcrawl.dev/v1/instagram/post/stats?url=https://www.instagram.com/reel/DZpHFjVOHrz/"
```
`req-qxkuzb3jT3hsqV87`, **5 credits**. Same `post.id` as row 0 above. Views **8,545,988**, shares **57,246**, `remix_count = 0`, `media_type = "video"`. **`saves = null`. `repost_count = null`.** `include=saves` was not called. The plain single-post route is not a saves guarantee.
The `include=stats` page already had saves **35,348** on that reel, inside a 2-credit page of twelve. One measured `post/stats` at 5 credits is why twelve separate calls would be **60**. The quoted `include=saves` ceiling of 9 credits a reel (12 × 9 = 108) is a quote, not this harvest.
`published_at` disagreed on this id: `include=stats` **2026-09-14T10:15:25Z**, `post/stats` **2026-06-16T09:50:50Z**. Quote each against its own endpoint. Do not use that row for cadence. Views also moved during the hour: 8,545,975 (stats page) → 8,545,983 (batch) → 8,545,988 (`post/stats`). Freeze a `request_id` when you quote a number.
A trend panel can rank on views, shares, *and* saves without twelve follow-up calls. `computed.engagement_rate` comes along for free.
## How do you get an Instagram audio id on a reels or posts page?
Audio arrived with the stats page: **12 / 12** `music_id`, 11 original sounds, 1 licensed track (ABBA, "Voulez-Vous"), `req-QlBhdv4tv3RZYy2g` (harvest 2026-09-15). That id is the one `GET /v1/instagram/audio/reels` takes. `include=audio` was not billed on its own this run. Licensed audio (the ABBA row) already appeared on the plain 1-credit page; original sounds needed `include=stats`. The listed price for combined `include=audio,stats` on reels is still 2 credits; that combination was not a separate call this harvest.
## What does the Instagram screen text API actually read?
A photo, the first 10 carousel slides, or a reel **cover**. Text later in a reel is not read. This is not full-reel OCR. Graph Insights has [no OCR, screen-text, or voice-to-text field](https://developers.facebook.com/documentation/instagram-platform/reference/instagram-media/insights). TikTok's Research API `voice_to_text` is generated speech-to-text, not overlay OCR ([TikTok Query Videos](https://developers.tiktok.com/docs/en/research-api-specs-query-videos)). This Instagram media API path is overlay OCR on the cover, the photo, or the first 10 slides — not speech-to-text.
```bash
curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \
"https://www.socialcrawl.dev/v1/instagram/media/screen-text?url=https://www.instagram.com/p/DdEqEl5Dl-S/"
```
`req-SmEdBZKawT2gF74e`, **5 credits**, 20-slide carousel `DdEqEl5Dl-S` (also on anaheubl's recent grid, `carousel_count = 20`):
```json
{
"media_type": "carousel",
"slide_count": 20,
"texts": [
"\"Ana, dein Speicherplatz ist voll.",
"Du musst Fotos löschen\"",
"...",
"See KLAUSE",
"Happy BirthDay",
"Notfall: 81",
"5122",
"5140",
"KH Vinzer",
"ELEACEL"
],
"source": "ocr",
"warnings": [
"This carousel has 20 slides; text was read from the first 10 only."
],
"credits_used": 5,
"request_id": "req-SmEdBZKawT2gF74e"
}
```
`texts.length = 10`, `images.length = 10` (indexes 0–9). Indexes 2, 4, 5, 7, and 9 of those first ten came back with empty per-slide `texts`. OCR is noisy (`See KLAUSE`, `ELEACEL`). None of that overlay text is in the caption. Both URLs this harvest were carousels; a reel-cover capture was not run. The product limit still applies to reel covers: later frames of a reel are not read.
The 3-slide carousel `DBEFb2poEGc` (`req-0pXyJmoGNWa8xE6k`, also **5 credits**) is the other answer you will get:
```json
{
"media_type": "carousel",
"slide_count": 3,
"texts": [],
"source": "none",
"warnings": null,
"credits_used": 5,
"request_id": "req-0pXyJmoGNWa8xE6k"
}
```
Empty is a real answer, not a 404. A missing post refunds as 404; that path was not called this harvest.
## How do you batch Instagram post stats across 100 URLs?
A clipper payout loop can POST the permalinks an Instagram feed API walk already returned. You pay 2 credits per Instagram row that comes back. Unread links refund instead of failing the batch. `POST /v1/prism/post-stats` accepts up to 100 URLs, including handle-form links from `profile/posts`. This harvest submitted 5. The single-post sibling is `GET /v1/instagram/post/stats` at 5 credits; the batch is 2 credits per Instagram row that resolves.
```bash
curl -s -X POST -H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "content-type: application/json" \
"https://www.socialcrawl.dev/v1/prism/post-stats" \
-d '{"urls":["https://www.instagram.com/reel/DZpHFjVOHrz/","https://www.instagram.com/anaheubl/reel/DdQ1J_fuleG/","https://www.instagram.com/anaheubl/p/DdUajnwDhh9/","https://www.instagram.com/reel/DdKHLZDOkes/","https://www.instagram.com/reel/ZZZZNOTEXIST999/"]}'
```
`req-c34vvJjObni9cLkN`. Trimmed summary:
```json
{
"summary": {
"total": 5,
"ok": 4,
"not_found": 1,
"credits_charged": 8,
"credits_refunded": 2
},
"credits_used": 8,
"request_id": "req-c34vvJjObni9cLkN"
}
```
| Input URL | Form | status | views | likes | shares | saves | reposts | cost |
| --- | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
| `…/reel/DZpHFjVOHrz/` | reel permalink | ok | 8,545,983 | 728,795 | 57,246 | **35,348** | 17,703 | 2 |
| `…/anaheubl/reel/DdQ1J_fuleG/` | handle-form reel | ok | 444,315 | 20,421 | 6,973 | **1,208** | 388 | 2 |
| `…/anaheubl/p/DdUajnwDhh9/` | handle-form carousel | ok | null | 17,495 | **null** | **null** | 15 | 2 |
| `…/reel/DdKHLZDOkes/` | reel permalink | ok | 375,973 | 10,798 | 724 | **906** | 32 | 2 |
| `…/reel/ZZZZNOTEXIST999/` | invented dead link | **not_found** | — | — | — | — | — | **0** |
Saves filled **on the reels** (3 of 3 reel rows this panel: 35,348 / 1,208 / 906). That is not a promise for the next panel. The carousel row had `saves = null` and `shares = null`. Instagram does not publish save or share on photos and carousels. Do not estimate them. That same carousel returned `reposts = 15` this run; do not turn one row into a guarantee.
Handle-form permalinks resolved. The dead URL cost 0.
## How do you skip pinned Instagram posts and stop a walk at N days?
Pinned 2024 posts no longer occupy page 1 of a 45-day job, and the page is still 1 credit.
Plain `GET /v1/instagram/profile/posts?handle=anaheubl` (`req-dh8MJ5SkvY9nH6UC`, **1 credit**): **12** rows, **3** pinned.
| URL | media_type | carousel_count | pinned | published_at |
| --- | --- | ---: | --- | --- |
| [forbes_swiss/DR5WXAxjHZp](https://www.instagram.com/forbes_swiss/p/DR5WXAxjHZp/) | image | — | **true** | 2025-12-05T21:00:36Z |
| [C7m80FyNmL4](https://www.instagram.com/anaheubl/p/C7m80FyNmL4/) | video | — | **true** | 2024-05-30T22:01:21Z |
| [DBEFb2poEGc](https://www.instagram.com/anaheubl/p/DBEFb2poEGc/) | carousel | 3 | **true** | 2024-10-13T12:10:33Z |
| [DdUajnwDhh9](https://www.instagram.com/anaheubl/p/DdUajnwDhh9/) | carousel | 7 | false | 2026-09-15T19:01:59Z |
Nine more recent rows follow. Mix on the plain page: image 1, video 4, carousel 7. `post.ext.media_type` is `image`, `video`, or `carousel`. `carousel_count` was present on every carousel this run (3, 7, 5, 20, 4, 9).
The same handle with `exclude_pinned=true&recent_days=45` (`req-16t1ibIDALPd4Eut`, still **1 credit**): **9** rows, **0** pinned, dated 2026-09-04 through 2026-09-15. `next_cursor` was still present. A 45-day walk does not stop on page 1 when the rest of the grid is still inside the window. The stop happens once a page reaches older posts.
The same pair exists on `profile/reels`. This harvest ran it on `profile/posts` only.
## How do you start using this?
1. Get an API key. Signup includes free credits.
2. Replay the Instagram reels stats API call below against the SocialCrawl API (2 credits). Check `items.length` and which of `views` / `likes` / `comments` / `shares` / `saves` / `repost_count` / `remix_count` / `music_id` are non-null. Counts will have moved. Field fill and the credit line are what to re-check.
3. Same call in Python `requests`. Put one API key in `SOCIALCRAWL_API_KEY`.
4. Next: [Instagram endpoint docs](/docs/instagram) and the [Instagram platform page](/platforms/instagram) for the live catalogue of Instagram API endpoints. See the page in the Explorer before writing a single line.
```bash
curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \
"https://www.socialcrawl.dev/v1/instagram/profile/reels?handle=anaheubl&include=stats"
```
```python
body = requests.get(
"https://www.socialcrawl.dev/v1/instagram/profile/reels",
params={"handle": "anaheubl", "include": "stats"},
headers={"x-api-key": os.environ["SOCIALCRAWL_API_KEY"]},
timeout=60,
).json()
items = body["data"]["items"]
print(body["credits_used"], body["request_id"], len(items))
```
This 2026-09-15 harvest spent **33 credits** across nine data calls (balance 92,150 → 92,117). Optional extra, still 5 credits: `GET /v1/instagram/post/likers` on the 8.5M reel (`req-E5jLS5CzJiM3LbcQ`) returned **999** accounts against `total = 728,795` likes, **918 / 999** with a `display_name`, 8 verified, `has_more = false`. Ranked sample, not the whole like list. Display names are on the sample. 999 is not 728,795.
The unified schema makes `computed.engagement_rate` comparable across those rows without a second parser.
## Frequently asked questions
### How many credits does an Instagram Reels stats API call cost?
`include=stats` on `profile/reels` billed **2** this run (`req-QlBhdv4tv3RZYy2g`). The plain reels page is **1**. Twelve separate `post/stats` calls billed **5** each this run would be **60**. The quoted `include=saves` ceiling of 9 credits a reel was not called this run. There is no settle-rate number from this harvest.
### Does the Instagram screen text API read every frame of a reel?
No. Photo, first 10 carousel slides, or reel cover. The 20-slide harvest read 10 and warned: "This carousel has 20 slides; text was read from the first 10 only." Later reel frames are not read. This is not full-reel OCR. Both URLs this harvest were carousels.
### Can you get save and share counts on Instagram photos and carousels?
No. Instagram does not publish those. The batch carousel `DdUajnwDhh9` this run: `saves = null`, `shares = null`, `views = null`. Do not estimate them. Reels on the `include=stats` page and on this panel did return saves. Plain `post/stats` on the 8.5M reel did not (`saves = null`).
### What is the difference between Instagram Graph Insights and a public Reels stats API?
Graph Insights is media you own, a professional account, usually a Facebook Page, per-media ID, and [app review](https://developers.facebook.com/documentation/instagram-platform/overview) for Advanced Access. A public Reels stats API call here is `handle` + `x-api-key` and one page of 12. Graph cannot return Insights-grade saves, shares, or reposts on a handle you do not manage. This harvest does not claim audience age, gender, or country.
### Does `include=audio` cost extra on a reels stats page?
Not a standalone call this run. Audio already arrived with `include=stats` at **2 credits**, 12 / 12 `music_id`, no extra lookups. Listed price: `include=audio` on posts/reels is +1 credit per video row filled; combined `include=audio,stats` on reels is still 2. That combination was not a separate call this harvest. Licensed audio (the ABBA row) already appeared on the plain 1-credit page.
### What happens to dead URLs in a batch Instagram post-stats call?
Unread links are refunded. This panel: 5 URLs, 4 ok / 1 not_found, charged 8, refunded 2. Dead `/reel/ZZZZNOTEXIST999/` cost 0. Handle-form permalinks resolved.
Replay `GET /v1/instagram/profile/reels?handle=anaheubl&include=stats` (2 credits) and compare fill, not the live view count. Endpoint catalogue: [`/docs/instagram`](/docs/instagram). Named 404s and the About restore sit on the [reliability post](/blog/instagram-api-reliability). View definition sits on the [425-post study](/blog/how-instagram-counts-views).