# Instagram (/docs/instagram)
Instagram [#instagram]
Public Instagram data without a Meta app review: profiles and their whole feed, reels with view
and share counts, comment threads, story trays and saved highlights, the follower and following
graph, hashtag and location feeds, and the audio library. Most reads are 1 credit; the ones that
need a heavier upstream are 5. Which is which is the main thing to learn on this platform.
Base URL: `/v1/instagram/...`
`/v1/instagram/post`
does not carry a share count, and no cheap endpoint does. Share counts, follower lists, stories and comments all come from a 5-credit upstream —
`/v1/instagram/post/stats`
for one post,
`/v1/instagram/profile/posts/full`
or
`/v1/instagram/profile/reels/full`
for a whole feed. View counts are different: they stay on the 1-credit reads, with
`post`
,
`profile/posts`
and
`profile/reels`
all carrying them on video. Plan the call before you build the loop.
Getting started [#getting-started]
Every endpoint is a `GET` with query parameters and an `x-api-key` header. Handles never carry a
leading `@`.
```bash
# 1. The account
curl "https://www.socialcrawl.dev/v1/instagram/profile?handle=instagram" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"
# 2. What it posted, cursor-paged on next_max_id
curl "https://www.socialcrawl.dev/v1/instagram/profile/posts?handle=instagram" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"
# 3. One post in detail
curl "https://www.socialcrawl.dev/v1/instagram/post?url=https://www.instagram.com/p/CnpPou9hWqq/" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"
```
`GET /v1/instagram/profile/full?handle=instagram` collapses steps 1 and 2 into one flat 5-credit
call and adds computed analytics on top — average engagement rate, posting cadence, top post,
and the mix of formats. Set `posts` (1-100, default 25) to choose the window the averages cover,
or `include=computed` to drop the raw posts array from the payload. If the posts leg fails the
profile still comes back, with the post-dependent metrics null.
Accounts [#accounts]
`profile` is the snapshot: bio, the exact integer follower count on `author.followers`, following count, post count, avatar, verification.
`/v1/instagram/basic-profile` is its minimal sibling for when all you hold is a numeric `userId`
and you only need a name and picture. `/v1/instagram/engagement` does the arithmetic for you —
an overall engagement rate, totals, and a per-post breakdown including likes and comments per
hour.
Three endpoints walk the graph, all 5 credits and all accepting either `handle` or `user_id`:
`/v1/instagram/followers` and `/v1/instagram/following` for the two directions, and
`/v1/instagram/similar` for the accounts Instagram itself suggests as comparable, which is a
single fixed list with no pagination.
`/v1/instagram/search` is Instagram's own mixed search box: accounts, hashtags, and places in
one payload. Reach for `search/profiles`, `search/hashtag`, or `search/location` when you want
one type already split. `/v1/instagram/search/popular` is the popular-posts feed for a keyword,
distinct from `search/reels`. `/v1/instagram/search/profiles` finds accounts by bio or caption
keyword. It reads Google's index of Instagram rather than Instagram's own account search, so
treat it as discovery rather than a lookup. `/v1/instagram/username-suggestions` is unrelated
despite the name: it invents available handle ideas from a keyword and does not look anything
up. `/v1/instagram/user/embed` returns an embeddable HTML snippet for dropping a profile onto
your own page.
Posts, reels and share counts [#posts-reels-and-share-counts]
`/v1/instagram/profile/posts` and `/v1/instagram/profile/reels` are the cheap feed pulls (1
credit each), and they return likes, comments and, on reels, views. Neither carries a share
count, because the upstream that serves them does not expose one.
When shares matter, `/v1/instagram/profile/posts/full` and `/v1/instagram/profile/reels/full`
fan out to a second source and attach a per-item share count plus a `coverage` figure telling
you what fraction of the items got one. Both are metered: they consume upstream pages of 12
items and bill 5 credits per page, from 5 up to 25 for a `limit=50` walk. Both need a `handle`
for the share leg — a `user_id`-only call still returns views, likes and comments, with shares
null and a partial refund.
For a single post, `/v1/instagram/post` returns the caption, media, tagged users and the
engagement numbers, including the play count on video. Instagram removed play counts from its
public web pages in August 2026, so the API now fills the count from a second source inside the
same call; you still make one request and pay one credit. `/v1/instagram/post/stats` adds the
paper-plane share count on video. Photo posts return views and shares as null, which is
Instagram's behaviour rather than a gap. `/v1/instagram/post/likers` returns who liked it, and
`/v1/instagram/media/transcript` returns the spoken words in a video or reel.
Comments [#comments]
`/v1/instagram/post/comments` returns a post's comment section, ranked by Instagram's popularity
order by default. Pass `sort=recent` whenever you intend to walk a whole thread: Instagram only
ranks the most-liked head of the list, so a `top` walk starts repeating comments once you page
past it. Page deeper with the `next_cursor` from each response. To open one comment's replies,
use `/v1/instagram/post/comment/replies` with the same post `url` and that comment's `comment_id`.
It is the thread, not a second copy of the section.
`GET /v1/instagram/comment` resolves one specific comment you already know about, by permalink
(`comment_url`) or by `post_url` plus `comment_id`. It can also search a post for comments by
`author_username` or `text_contains`, returning up to `max` matches. It is a bounded server-side
scan rather than a direct fetch, because Instagram exposes no fetch-one-comment read: it costs 5
credits, or 15 with `deep_scan` for comments buried deep in a large thread. Passing back the
`lookup.position_hint` from an earlier call replays the last-known sort chain first, which makes
re-checking a comment you have already found much cheaper.
Stories and highlights [#stories-and-highlights]
`/v1/instagram/stories` returns the tray a user has live right now — an account with nothing
live returns an empty list rather than an error. `/v1/instagram/story/download` pulls one
specific story's full-resolution media, taking the author's `user_id` together with the
`story_id`. Highlights are the permanent version: `/v1/instagram/highlights` lists the saved
collections on a profile, and `/v1/instagram/highlight/detail` opens one by id.
Discovery [#discovery]
* `/v1/instagram/search/hashtag` pulls a tag feed, with `type` selecting `top` (default),
`recent`, or `clips` for reels only
* `/v1/instagram/search/reels` searches reels by keyword or phrase, page-paginated, with an
optional `date_posted` filter
* `/v1/instagram/reels/trending` samples Instagram's public trending page; it takes no
parameters, sends a small batch per call, and repeats items, so call again to see more
* `/v1/instagram/search/location` turns a place name into a `location_id`, which
`/v1/instagram/location/posts` then uses to return what was posted there
* `/v1/instagram/tagged` returns posts other people tagged an account in, which is a different
question from what that account posted itself
Reel search ordering is relevance, not a stable list [#reel-search-ordering-is-relevance-not-a-stable-list]
`/v1/instagram/search/reels` returns Instagram's own relevance ranking for the keyword, and that
ranking is live: the same query re-run minutes later can come back with a different, partially
overlapping set of reels, and pages can overlap at their boundaries. There is no parameter that
pins an ordering, and `date_posted` narrows the window rather than sorting it.
Build on that rather than against it. Rank on `engagement.views` in your own code instead of
trusting result order, deduplicate by `post.id` across pages and across runs, and if you need a
stable view of a keyword over time, accumulate results into your own store across repeated runs
rather than expecting one call to be reproducible. For a creator's complete back catalogue in a
fixed order, walk `/v1/instagram/profile/reels` instead — a profile listing is stable in a way a
relevance search cannot be.
Follower counts next to search results [#follower-counts-next-to-search-results]
`/v1/instagram/search/reels` rows carry the creator's identity on every row: `post.author.username` and `post.ext.author_id`, the numeric user id. `post.ext.author_followers` is historical — Instagram stripped follower counts out of its search payload in August 2026, so the field is null on every row and no source can restore it. Resolve follower counts from the creator's username instead.
The current count lives on `author.followers` via `GET /v1/instagram/profile?handle=` (1cr, the exact integer, cached for 15 minutes) — every row's `post.author.username` is the join key. For a crawl, deduplicate creators across the whole run, then resolve them through `POST /v1/prism/profiles`: up to 50 handles per call at 1 credit per resolved profile, failed rows refunded, never served from cache, and one call can mix platforms, so TikTok and Instagram creators resolve together. Match rows to your input by each row's `index`.
```bash
curl "https://www.socialcrawl.dev/v1/instagram/profile?handle=nasa" \
-H "x-api-key: sc_your_api_key_here"
```
Audio [#audio]
`/v1/instagram/search/music` finds a track by name and `/v1/instagram/music/trending` returns
whatever is popular right now with no parameters at all. Both return an audio id, and
`/v1/instagram/audio/reels` takes that `audio_id` — the number in an
`instagram.com/reels/audio/{audio_id}/` URL — and returns the reels using that sound,
cursor-paged. That chain is how you measure a sound's spread rather than its chart position.
Endpoints [#endpoints]
Read this before you build [#read-this-before-you-build]
**Media URLs expire.** The `media_urls` on any post are short-lived signed CDN links. For
archiving, call `post` with `download_media=true` and read the durable links from
`data.post.ext.download_media_urls`, each entry carrying `post_id`, `cdn_url`, `type` and
`cached`. It adds a few seconds of latency while the media is fetched.
**Likers are capped at roughly 100.** `post/likers` returns a sample regardless of how many
likes the post has; the full like *count* is in the same response, but the list is not complete.
Instagram does not expose more.
**`safe_url=true` where you are embedding.** Several endpoints accept it, and it returns
URL-safe profile picture and media links suitable for dropping straight into a page.
**Carousels return every slide.** A sidecar post's `media_urls` is the full array, not just the
cover image.
Notes [#notes]
* All endpoints use `GET` with query parameters
* Authentication via the `x-api-key` header
* Responses follow the unified SocialCrawl schema
* Handles are passed without the `@`; where an endpoint accepts `user_id` as well, it is the
faster of the two
* `trim=true` on the profile and feed endpoints returns a slimmed-down payload
Official Instagram Resources [#official-instagram-resources]
* [Instagram Graph API](https://developers.facebook.com/docs/instagram-api/) — Official Meta
developer documentation
* [Instagram Basic Display
API](https://developers.facebook.com/docs/instagram-basic-display-api/) — Basic profile and
media access