Instagram API v1
Public Instagram data — accounts, posts, reels, active stories, comments, popular reels and trending terms — as JSON, from https://api.fetchlayer.dev/instagram. Everything returned is what Instagram makes public: nothing private, nothing from an account you do not own. FetchLayer is not affiliated with, endorsed by, or sponsored by Instagram or Meta.
Three ceilings, stated first
Instagram makes less public than any other platform here. These three limits decide what you can build, so they are up front rather than buried — and all three announce themselves in the notes array on every response that hits them.
- Twelve posts per page. Instagram serves a grid 12 at a time whatever
limitsays, solimit: 60is five pages and five credits.pagesFetchedreports what actually happened. - Comments page, a page at a time. Instagram serves a post’s comments newest first, 10–16 to a page.
pagesreturns up to 10 in one request andcursorcontinues from anextCursor; each page is one credit.totalCountcounts replies too, so it runs higher than the comments listed./comment-repliesreturns the replies to one comment, about 8 to a page, given the comment’sid. - Some counts are never public. Instagram does not publish view counts on photos and carousels, or share and save counts on photos and carousels. Those fields — a photo’s
playCount,shareCountandsaveCount— are alwaysnull, never a made-up zero.
Two things you will not find elsewhere
Story highlights are on the profile. user-profile returns highlights — the id, title and cover of every highlight the account keeps — in the same call that returns the bio and the follower count, at no extra cost. The contents of a highlight are not public, and nothing here claims otherwise; the titles alone tell you how an account organises itself.
Listings carry engagement. Every reel from user-reels comes back with playCount, likeCount and commentCount, and user-posts normally carries each post’s date and counts too, so sizing an account does not need a detail call per post. The profile’s stats.postCount is exact.
Available endpoints
/user-profile POST List an account’s posts /user-posts POST List an account’s reels /user-reels POST Read an account’s active stories /user-stories POST Get one post or reel in full /post-detail POST Read a post’s comments /post-comments POST Read the replies to a comment /comment-replies POST Browse popular reels /reels-feed POST List what Instagram is trending /trending-searches POST Parse an Instagram URL (free) /resolve-url GET Stream an image or video asset /media One post shape, and what a listing leaves out
Every route that returns posts or reels returns the same record: id, shortcode, url, kind, productType, caption, createdAt, likeCount, commentCount, playCount, videoDuration, shareCount, repostCount, saveCount, countsHidden, dimensions, altText, assets, carousel, author, coauthors, taggedUsers, location, hashtags, mentions, topics, hasAudio and fieldsFrom.
fieldsFrom says which shape a record has, so a null count is never mistaken for a zero: detail is a full post, listing_full a listing record with its date and counts, and listing one without them — which /reels-feed always is. On a posts or reels listing, a post still missing its date or a count is named by short code in the note, with the fields it lacks; asking again with include returns them. A nextCursor works only on the route, and with the account, that produced it; any other cursor is a 400. repostCount, shareCount and saveCount are filled when you ask for them with include on /post-detail, /user-posts or /user-reels — any of "reposts", "shares", "saves" — at the same price; shares and saves exist for reels and videos only. On a listing, include adds a few seconds per page, usually 2 to 8; when a count is not available for some posts the note names them, and /post-detail with include returns them for any single post. playCount is Instagram plays, the same figure on listings and on a single post. countsHidden true is the other reason a count is absent: the account turned like and view counts off.
Ids
Every id — posts, reels, story frames, carousel frames, comments, accounts — is a string holding Instagram’s exact id. Instagram’s ids are 64-bit numbers, larger than a JSON number can carry exactly, so keep them as strings rather than parsing them. A link built from one is exact, for example https://www.instagram.com/stories/<username>/<id>/, and /post-detail and /post-comments accept a post’s id in place of its URL or short code. An account’s id can be passed back as userId on /user-profile, /user-reels and /user-stories.
Captions and alt text are not transcripts
caption is the author’s own written post body. altText is Instagram’s machine-written image description (“Photo by NASA on August 19, 2026. May be an image of text.”). Neither is a transcript of spoken audio, and Instagram publishes no subtitles — so this API returns none, and nothing here should be read as offering one.
Paging and billing
limit caps the items returned; pages caps how many pages are fetched to get them, up to 20. Because Instagram’s page is 12 items, the two are tied: a limit of 60 needs five pages, and without a limit every item on the pages fetched comes back (pages: 2 returns 24). Billing follows the pages, not the item count. When more exists, hasMore is true and nextCursor carries an opaque value to pass back as cursor. Passing -1 means “the maximum this service allows”, which is 240 items and 20 pages. On /post-comments a page holds 10–16 comments and pages goes up to 10.
Billing follows pages: one credit per page of results fetched, stated on every response as pagesFetched. A single-page request costs 1. /resolve-url reaches Instagram not at all, reports pagesFetched: 0 and is free.
Read the notes array
Several real limits on this platform are reported only in notes: how comments page, the counts Instagram does not make public, a listed post still missing its date or a count, a list that stopped early, a private account, whose posts and reels are not public, and a restricted account. An empty result always comes with a note explaining it rather than as an unexplained empty array.
Requests are strict
An unrecognised body field is a 400 naming it, not a silent no-op. A typo such as usernam would otherwise be dropped and answered with the wrong data and no indication why.
What Instagram does not publish
These are not gaps in effort. Instagram does not make any of them public, so no service can honestly return them as public data:
- Posts under a hashtag, and posts at a place. Instagram does not make either public, so no route returns them.
/resolve-urlstill identifies a hashtag or place link and says so, and/reels-feedand/trending-searchesreturn what Instagram does publish for discovery. - Keyword search over accounts, hashtags or places.
/trending-searchesand/reels-feedare the public substitutes. - Follower and following lists. The counts are published; the lists are not.
- The contents of a highlight. Highlight titles and covers are published, and come back on
/user-profile; the stories an account has up now come back on/user-stories. - Posts an account is tagged in, and who liked a post.
- Share and save counts on photos and carousels (reels and videos have them), view counts on photos and carousels, and an account’s former usernames.
- Transcripts or subtitles. Instagram publishes none here.
captionis written by the author,altTextis machine-written alt text, and neither is a transcript.