Instagram API — Getting Started — FetchLayer Docs
Documentation menu
FetchLayer FetchLayer API

Getting Started

Read public Instagram profiles, posts, reels, comments and trends as structured JSON. No Instagram account and no developer application — just your FetchLayer key.

1. Get your API key

Create an account and generate a FetchLayer API key from your dashboard. The same key works on every platform.

Create free account →

2. Read an account

Pass a handle with or without the @, or a profile URL. The bio links come back unwrapped to their real destinations, and the story highlights come back with them.

bash
curl -X POST https://api.fetchlayer.dev/instagram/user-profile \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"username":"@nasa"}'

Story highlights come free with the profile

highlights lists the id, title and cover of every highlight on the profile, in the same call and for the same credit. Their contents are not public — only the titles and covers are.

stats.postCount is always null

Instagram publishes no post count to a signed-out reader. The response says so in notes: “The source does not publish a post count for a signed-out reader; read the account's posts to count them.” Follower and following counts are published normally.

3. List what they posted

Newest first, with captions, hashtags, mentions, alt text and every rendition.

bash
curl -X POST https://api.fetchlayer.dev/instagram/user-posts \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"username":"@nasa","limit":60}'

Twelve posts per page, and a grid has no counts

Instagram serves 12 posts per page whatever limit says, so limit: 60 reads five pages and costs five credits — pagesFetched reports it. And a listing carries no like count, no comment count and no posting date: Instagram does not publish them on a grid. Each post says which shape produced it in fieldsFrom, so a null is never mistaken for a zero.

4. Read the reels, with play counts

Same shape as the posts listing, with one difference worth the call: every reel comes back with playCount, likeCount and commentCount. It is the only Instagram listing that publishes engagement at all.

bash
curl -X POST https://api.fetchlayer.dev/instagram/user-reels \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"username":"@nasa","limit":12}'

5. Open one post, and read its comments

By URL or by the short code from it. This is where the counts and the posting date live.

bash
curl -X POST https://api.fetchlayer.dev/instagram/post-detail \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"post":"https://www.instagram.com/p/DcOX3hWFiey/"}'

curl -X POST https://api.fetchlayer.dev/instagram/post-comments \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"post":"DcOX3hWFiey"}'

One page of comments, about thirteen of them

Instagram publishes the first page of comments to a signed-out reader and no more. It still reports a far larger totalCount and sets hasMore true, so the response spells it out: “These are the 13 comments of the 4,334 the source reports that are public for this post. The source does not publish the rest to a signed-out reader, so there is no further page to read.” Do not loop on hasMore — you will read the same thirteen and be billed again. Reply text is not public either; each comment reports only how many replies it has.

6. Discovery, without search

Instagram publishes no keyword search and no hashtag feed to a signed-out caller — both redirect to a login page. What it does publish is its own reel feed and the terms it is promoting.

bash
curl -X POST https://api.fetchlayer.dev/instagram/reels-feed \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"limit":12}'

curl -X POST https://api.fetchlayer.dev/instagram/trending-searches \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"limit":48}'

Trending is not search

/trending-searches returns the terms Instagram itself is promoting, grouped into its own sections, each with Instagram’s rounded count of posts under it. It is what Instagram is putting in front of everyone — not a query you control.

7. Assets that keep working

Instagram’s asset URLs are signed and expire, so every asset carries a downloadUrl pointing at GET /instagram/media, which re-fetches it on demand with Range support.

bash
curl -L "https://api.fetchlayer.dev/instagram/media?url=<asset url>" \
  -H "Authorization: Bearer ss-your-key" \
  --output post.jpg

Resolving a pasted link

When someone hands you an Instagram URL and you do not know what it points at, /resolve-url tells you — post, reel, account, hashtag, place, story or explore — plus the short code, numeric id, handle, tag or place id it encodes. It reaches Instagram not at all, so it is free.

bash
curl -X POST https://api.fetchlayer.dev/instagram/resolve-url \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://www.instagram.com/p/DcOX3hWFiey/"}'

A link naming something Instagram does not publish to a signed-out reader — a hashtag page, a place, a story — is still identified, with a note saying it cannot be read. That is the cheapest way to find out.

Errors and retries

A 400 names the field to fix; unrecognised fields are rejected rather than ignored. A 404 means there is no such public account or post — {"error":"no account \"fetchlayerprobe9f3\" was found"} — never a 503 dressed up as a failure. A 502 or 503 is worth retrying after a wait. Read notes on successful responses too: the comment ceiling, the withheld post count and a private account all announce themselves there rather than as an error.

Next steps