API tutorial · September 2026

Instagram Reels API: Get Views, Likes, and Shares Programmatically

Pull reels for any public account as structured JSON — play counts, likes, comments, captions, audio metadata — and know exactly which metric you are reading.

· 12 minute read

Reels are where Instagram engagement now lives, and they are also where measurement is easiest to get wrong. “Views”, “plays”, “impressions” and “reach” are four different numbers, and the one you actually receive depends on which API you call. Before you build a dashboard on top of a number, it is worth knowing which number it is.

This guide fetches reels for public accounts through the GramScraper API (an Instagram-specific wrapper), shows the real response fields, prices each call in credits, and then compares it honestly against Meta’s official Instagram API, which is a different tool with a different purpose.

Reels are served through the “clips” endpoints

Instagram’s own API surface calls short-form video clips. That naming carries into the endpoints, so if you go looking for a path literally called /reels you will miss the ones that work. The documented reels routes are:

EndpointWhat it returns
/v2/user/clipsA page of a user’s reels. Takes user_id and an optional page_id cursor.
/gql/user/clipsReels via GraphQL. Takes user_id, an optional max_id cursor, flat, and sort_by_views.
/v1/user/clips/chunkThe chunked variant, paged with end_cursor. Also includes trial publications.
/v1/media/insightInsight data for a single media object by media_id.
/gql/media/clips_metadataAudio and music metadata for a reel, by media_id.

Base URL: https://gramscraper.com/api/instagram, authorised with Authorization: Bearer gs_your_key. A free account starts you with 100 credits.

Step 1: turn a username into a user ID

The clips endpoints take a numeric user_id, not a username. Resolve it once and cache it — this is a genuine cost saver, because every reels page for that account then needs no lookup:

curl — resolve username to user ID
curl -s -H "Authorization: Bearer gs_your_key" \
  "https://gramscraper.com/api/instagram/v1/user/by/username?username=natgeo"

The response contains pk (for example 787132). That number is the user_id for every clips call. This lookup costs 1 credit.

Step 2: fetch the reels

curl

curl — first page of reels
curl -s -H "Authorization: Bearer gs_your_key" \
  "https://gramscraper.com/api/instagram/v2/user/clips?user_id=787132"

Node.js 18+

Node.js — reels for a public account
const BASE = "https://gramscraper.com/api/instagram";
const KEY = process.env.GRAMSCRAPER_API_KEY;

async function getReels(userId, pageId = null) {
  const url = new URL(`${BASE}/v2/user/clips`);
  url.searchParams.set("user_id", userId);
  if (pageId) url.searchParams.set("page_id", pageId);

  const res = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

const page = await getReels("787132");
for (const reel of page.response.items) {
  console.log(
    reel.code,
    "plays:", reel.play_count ?? 0,
    "likes:", reel.like_count ?? 0,
    "comments:", reel.comment_count ?? 0
  );
}

Python 3

Python — reels for a public account
import os, requests

BASE = "https://gramscraper.com/api/instagram"
HEADERS = {"Authorization": f"Bearer {os.environ['GRAMSCRAPER_API_KEY']}"}

def get_reels(user_id, page_id=None):
    params = {"user_id": user_id}
    if page_id:
        params["page_id"] = page_id
    r = requests.get(f"{BASE}/v2/user/clips", headers=HEADERS, params=params)
    r.raise_for_status()
    return r.json()

page = get_reels("787132")
for reel in page["response"]["items"]:
    print(reel.get("code"), reel.get("play_count"), reel.get("like_count"))

What reels actually return

Clips pages use the same envelope as other list endpoints: items under response.items, cursor under next_page_id. A reel item looks like this:

Response — one reel item
{
  "response": {
    "items": [
      {
        "pk": "3162273595027945978",
        "id": "3162273595027945978_787132",
        "code": "DYNOQDIgNmw",
        "media_type": 2,
        "product_type": "clips",
        "taken_at": "2026-08-14T17:02:03+00:00",
        "caption_text": "Behind the scenes of the shoot 🎬",
        "like_count": 184322,
        "comment_count": 1204,
        "play_count": 4820331,
        "view_count": 0,
        "video_duration": 18.4,
        "video_url": "https://scontent.cdninstagram.com/...",
        "thumbnail_url": "https://scontent.cdninstagram.com/...",
        "share_count_disabled": false,
        "comments_disabled": false,
        "is_paid_partnership": false,
        "user": {
          "pk": "787132",
          "username": "natgeo",
          "full_name": "National Geographic",
          "is_verified": true
        }
      }
    ],
    "paging_info": { "more_available": true },
    "status": "ok"
  },
  "next_page_id": "QVFCcnhIWE82OUswLXBtNzlpZ0ZaUnhWZEhr"
}
FieldWhat it is
pk / idThe reel’s media ID. Use it for /v1/media/insight and /gql/media/clips_metadata.
codeThe shortcode in the reel URL: instagram.com/reel/<code>/.
play_countThe play count for the reel. This is the field to read for reels views. Can be null.
like_countLikes on the reel.
comment_countComment count as a number. To read the comments themselves, see the comments API guide.
view_countA view counter on the media object. Frequently 0 for reels — prefer play_count.
taken_atISO-8601 publish timestamp in UTC.
caption_textThe caption as plain text.
video_durationLength in seconds.
video_url / thumbnail_urlCDN URLs. These are signed and expire, so download promptly if you need the asset.
product_typeclips for reels, feed for an ordinary post.

On “shares”. Do not expect a share counter here. The reel object exposes share_count_disabled — a boolean flag telling you whether sharing is disabled — not the number of shares. Meta’s official API does expose a shares metric, but only for media your own account owns, as we cover below. Any reel API advertising public share counts for arbitrary accounts should be checked carefully before you trust it.

Paging through reels

Pagination is cursor-based and identical in spirit to comments. Terminate on a null cursor, not on a short page.

Node.js — walk reels pages
async function allReels(userId, maxPages = 10) {
  const out = [];
  let cursor = null, pages = 0;

  do {
    const page = await getReels(userId, cursor);
    out.push(...page.response.items);
    cursor = page.next_page_id || null;
    pages += 1;
  } while (cursor && pages < maxPages);

  return out;
}

The /v1/user/clips/chunk variant pages differently — it returns a two-element array of [items, end_cursor] and you feed end_cursor straight back. If you prefer GraphQL, /gql/user/clips accepts max_id and, usefully, a sort_by_views flag so you can retrieve the highest-performing reels first instead of walking chronologically and sorting client-side.

Credit cost breakdown

CallCredits
/v1/user/by/username (resolve the user ID)1, once per account
/v2/user/clips (one page of reels)1
/gql/user/clips1
/v1/user/clips/chunk1
/v1/media/insight (per-post insight)1
/gql/media/clips_metadata (audio metadata)1

So a practical job — resolve one account and pull one page of reels — is 2 credits. If you reuse the cached user_id for further pages, each additional page is 1 credit. The response _meta block reports credits_consumed and credits_remaining, so the authoritative number is always in the payload rather than your own table.

At published rates ($9 for 10,000 credits), 10,000 page-fetches works out at roughly $0.90 per 1,000 calls. Purchased credits do not expire, which suits reels monitoring that runs in bursts.

How this compares to Meta’s official Reels API

Meta’s Instagram API is not a worse version of this — it is a different tool, and for some jobs it is the correct one.

GramScraper (Instagram-specific API)Meta Instagram API (/insights)
Whose mediaAny public accountMedia your own app user owns
AuthOne API keyAn Instagram professional account, a Meta app, and approved permissions such as instagram_business_basic and instagram_business_manage_insights
Metricsplay_count, like_count, comment_count, caption, duration, audio metadataRich insight metrics including reach, saved, shares, reposts, ig_reels_avg_watch_time, and total_interactions
FreshnessReturned as the platform serves itMeta documents that metric data can be delayed up to 48 hours
Missing dataFields are nullableMeta returns an empty dataset rather than 0 when a metric is unavailable
Best forCompetitor and creator research at scale, without owning the accountsAnalytics for accounts you own, where you need watch-time and reach

The honest summary: if you own the account and have the permissions, Meta’s insights endpoint gives you metrics nothing else can — average watch time, reach, saves, and share counts. Those are first-party numbers. Our API cannot produce them for arbitrary third-party accounts, and no third-party API can produce Meta’s first-party insight metrics at all.

What this API is good at is the other half of the problem: reading reels for accounts you do not own — competitors, prospective influencers, or a market you are researching — without an app review, a linked professional account, or an owned-media constraint. If your need is “the top reels of these 200 creators, sorted by plays”, the official API simply is not the tool for the job.

Also worth noting: Meta documents that insights metrics such as comments, likes, and views count organic interaction only, that album media has no insights at all, and that story metrics expire after 24 hours. Those are real constraints of the official path, not a criticism invented here.

Honest limitations of the reels endpoints

Get 100 free API credits

Resolve a creator, pull a page of reels, and check the fields against your own requirement — before choosing a pack. Starter is $9 for 10,000 non-expiring credits.

Create a free account →