Instagram API documentation
Everything you need to call the StoriesFly API: how to get a key and make a first request, the rules for authentication, paging, errors and rate limits, and a page for each of the 43 data endpoints, and one for the free account call, with its parameters, a real sample answer and code to copy. The whole API is also described in openapi.json.
Quick start
Sign in with Telegram in the dashboard and create a key. A new account gets 100 free requests, so you can try the endpoints before you pay.
Then send a GET request to https://storiesfly.com/api/v1/ with the key in the X-Api-Key header. This call reads the profile of an account and takes 1 request.
curl "https://storiesfly.com/api/v1/user/profile?username=arianagrande" \
-H "X-Api-Key: sf_live_your_key"The first answer
The answer is JSON. The headers say what the call cost: X-Units-Charged: 1, and what is left in X-Balance-Remaining and X-Free-Units-Remaining. Long texts and links are shortened in this example.
{
"id": "7719696",
"username": "arianagrande",
"full_name": "Ariana Grande",
"bio": "petal out now ꕤ 。˚",
"followers": 362337023,
"following": 1075,
"posts": 599,
"verified": true,
"is_private": false,
"profile_pic_url": "https://scontent-iad3-1.cdninstagram.com/v/t51.82787-19/758252911_18764924023039697_5331858031316748508_n.jpg",
"external_url": "https://linktr.ee/arianagrande"
}Official client
For Node.js 18 or newer and for TypeScript there is an official client on npm. It has a method for every Instagram endpoint; call the TikTok endpoints and download over HTTP for now. It sends the X-Api-Key header, follows next_cursor through a list, retries a 429 after the wait the API asks for, types every answer and returns the cost of a call and your balance in the response meta.
Each page of a list is charged as one call, so set maxPages unless you mean to read the whole list. For other languages, call the API with cURL as above, or generate a client from openapi.json.
npm install storiesflyimport { StoriesFly } from "storiesfly";
const sf = new StoriesFly({ apiKey: process.env.STORIESFLY_KEY! });
const { stories } = await sf.user.stories({ username: "brooklynandbailey" });for await (const page of sf.paginate(sf.user.followers, { username: "arianagrande" }, { maxPages: 4 })) {
console.log(page.users.length);
}Authentication
Send your key in the X-Api-Key header of every call. There is no login and no token exchange, and you do not need an Instagram or Facebook account.
A missing or wrong key answers unauthorized (HTTP 401). A key whose account is not linked to Telegram answers telegram_required with a link_url to do it. Keep the key on your server, because anyone who has it can spend your balance. You can replace and revoke keys in the dashboard.
Every endpoint is a GET under https://storiesfly.com/api/v1/, and its parameters go in the query string.
Pagination
An endpoint that returns a list sends it a page at a time. The answer has next_cursor and has_more.
To get the next page, send the next_cursor back as cursor and keep every other parameter the same: https://storiesfly.com/api/v1/user/following?username=arianagrande&cursor=<next_cursor>. When has_more is false, next_cursor is null and the list has ended.
A cursor is an opaque text. Do not build or change one: a cursor that the endpoint did not return answers bad_request. Each page takes the price of one call.
Page size follows Instagram and varies by endpoint. The page of an endpoint says how many items a page holds where we measured it.
{
"user": {
"id": "7719696",
"username": "arianagrande"
},
"users": [
{
"id": "1000000012",
"username": "sample_user_16",
"full_name": "Sample Name",
"profile_pic_url": "https://example.com/pic.jpg",
"verified": true,
"is_private": false
}
],
"next_cursor": "c1.ryg6VkAgkE2BcPyGM0q6ADwLG1KAGWvXyxXcleap6rtdnm6USXXD4rRRujLUjticHxS2vixe2jbdlG4LggGvIE1ISp6sYLXI6XWcb66UIrM_RMPDKCUhQylnCgNoMsPrfzM",
"has_more": true
}Errors and what is charged
A failed call answers with an HTTP status and a JSON body {error, code}. error is a sentence for people and code is the value to test for in your program. A refused parameter also lists its names in fields.
You are charged for answers: the data, not_found and private_account. A wrong parameter, a rate limit and an empty balance cost nothing, and a failure on our side is refunded. Most data calls take 1 request at your level's rate, and resolving a share link takes 2. download has a fixed price at every level instead: $0.20 per 1,000 for a TikTok link, $0.50 per 1,000 for an Instagram link. A download uses one free request while you have free requests left. The page of each endpoint says what its call takes.
| Status | Code | Charged | When |
|---|---|---|---|
200 | ok | charged | The data you asked for |
404 | not_found | charged | The account or post does not exist |
403 | private_account | charged | The account is private |
400 | bad_request | free | A parameter is missing or wrong |
402 | credits_exhausted | free | Top up to continue |
429 | rate_limited | free | Too fast; wait for Retry-After |
503 | upstream_unavailable | refunded | Our side failed or timed out |
401 | unauthorized | free | The X-Api-Key header is missing or the key is wrong |
403 | telegram_required | free | The account behind the key is not linked to Telegram; the answer has a link_url |
500 | internal_error | refunded | A fault on our side |
{
"error": "The request parameters are missing or invalid.",
"code": "bad_request",
"fields": [
"username"
]
}Rate limits
Your level sets how many requests per second you may send, for all your keys together. A call over the limit answers rate_limited (HTTP 429) with a Retry-After header, and costs nothing. X-RateLimit-Limit and X-RateLimit-Remaining show the limit on every answer.
Levels above Start are not open yet. The default limits today are 1 request per second for an account that has not topped up yet and 3 requests per second at Start. Prices are on the pricing page.
Higher limits are set by agreement, for example for large volumes. Write to us.
| Level | Reached by | Requests per second | Status |
|---|---|---|---|
| Free | Signing in with Telegram | 1 | Open |
| Start | Top up from $10 | 3 | Open |
| Growth | Top-ups totalling $100 | 5 | Opens soon |
| Business | Top-ups totalling $300 | 10 | Opens soon |
| Scale | Top-ups totalling $1,000 | 15 | Opens soon |
Response headers
An answer to a call that reaches your account carries these headers, so your code can read what the call cost and what is left. X-Request-Id is on every answer, errors included. Quote it when you write to support about a call.
| Header | Type | Meaning |
|---|---|---|
X-Units-Charged | integer | Units this call charged. 0 when it was free or was refunded. |
X-Balance-Remaining | string | Your balance after the call, in US dollars with four decimals. |
X-Free-Units-Remaining | integer | Free units you have left after the call. |
X-RateLimit-Limit | integer | How many requests per second your account may send. |
X-RateLimit-Remaining | integer | Requests left in the current second. |
X-Request-Id | string | The id of this call. Quote it when you write to support about the call. |
Endpoints
43 data endpoints and the free account call that shows your balance, all GET, grouped as on the API page. Each has a page with its parameters, a real sample answer, the errors it can give and code in cURL, JavaScript and Python, and for the Instagram endpoints the npm client as well.
User
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/user/profile | Profile with verified badge, bio, link and counts | 1 |
| GET /v1/user/about | Country, join month and former usernames | 1 |
| GET /v1/user/posts | Posts with likes, comments, views, shares, saves and reposts | 1 |
| GET /v1/user/reels | Reels with captions, video and play counts | 1 |
| GET /v1/user/tagged | Posts the account is tagged in | 1 |
| GET /v1/user/pinned | Posts pinned to the top of the profile | 1 |
| GET /v1/user/stories | Stories live now, with the length of each video | 1 |
| GET /v1/user/highlights | Highlight covers and titles | 1 |
| GET /v1/user/followers | Followers, page by page | 1 |
| GET /v1/user/following | Accounts followed, page by page | 1 |
| GET /v1/user/followers/search | Find someone among the followers | 1 |
| GET /v1/user/following/search | Find someone among the accounts followed | 1 |
| GET /v1/user/reposts | Posts and reels the account reposted | 1 |
| GET /v1/user/suggested | Similar accounts Instagram suggests | 1 |
Post
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/post | One post: media links, caption, views, likes, comments, shares, saves and reposts | 1 |
| GET /v1/post/comments | Comments with likes and reply counts | 1 |
| GET /v1/post/comment-replies | Replies to a comment | 1 |
| GET /v1/post/likers | Accounts that liked the post | 1 |
| GET /v1/post/usertags | People tagged in the post | 1 |
| GET /v1/post/music | The track used in a reel | 1 |
| GET /v1/comment/likers | Accounts that liked a comment | 1 |
Stories
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/story | One story by link or id | 1 |
| GET /v1/highlight | Every story in a highlight, by link or id | 1 |
Hashtags
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/hashtag | A hashtag with its post count | 1 |
| GET /v1/hashtag/posts | Posts under a hashtag: top, recent or reels | 1 |
Places
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/location | Place name, address, city and coordinates | 1 |
| GET /v1/location/posts | Posts tagged at a place: top or recent | 1 |
| GET /v1/location/search | Find places by name or around a point | 1 |
Search
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/search/users | Find accounts by name or username | 1 |
| GET /v1/search/hashtags | Find hashtags, with their post counts | 1 |
| GET /v1/search/places | Find places by name | 1 |
| GET /v1/search/music | Find tracks by title or artist | 1 |
| GET /v1/search/reels | Find reels for a text | 1 |
| GET /v1/search/top | The top posts for a text | 1 |
TikTok
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/tiktok/video | One TikTok video without the watermark, with views, likes, comments and shares | 1 |
| GET /v1/tiktok/user/profile | TikTok profile with followers, following, likes and video count | 1 |
| GET /v1/tiktok/user/videos | A TikTok account's latest videos with their numbers | 1 |
| GET /v1/tiktok/user/stories | TikTok stories live now | 1 |
Download
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/download | Files of an Instagram post or reel, or a TikTok video, by link | 1 |
Other
| Endpoint | What it returns | Requests |
|---|---|---|
| GET /v1/track | Track title, artist, length and audio link | 1 |
| GET /v1/resolve | Turn a post, reel or share link into data | 1, or 2 for a share link |
| GET /v1/shop/storefront | An account's shop: collections and first products | 1 |
| GET /v1/shop/products | Products in a shop collection | 1 |
| GET /v1/account | Your plan, balance, free units and use | 0 |
More
- The whole API in one file: openapi.json, OpenAPI 3.1, for code generators and API clients.
- Pricing has the levels from $1.50 per 1,000 requests, the billing rules and how to pay. The changelog lists what changed and when.
- Reading stories? See the Instagram Stories API. Wondering about a login? See the API without login.
- The endpoints that came before v1 are on the older endpoints page, with the date they stop.
Your first 100 requests are on us
Sign in with Telegram, create a key, call any endpoint. Top up only when you need more.
