Instagram Stories Scraper - Live Stories and Highlights
Pricing
from $2.44 / 1,000 results
Instagram Stories Scraper - Live Stories and Highlights
Scrape stories and pinned highlights from public Instagram profiles: media type, image and video links, posting time, caption, mentions, links and hashtags, location, sponsored flag and highlight tray. A story is gone 24 hours after it goes up, so a run sees what is live now. $2.50 per 1,000 rows.
Pricing
from $2.44 / 1,000 results
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
48
Total users
25
Monthly active users
a day ago
Last modified
Categories
Share
Name up to ten public Instagram handles and get their stories and highlights back as rows: media type, the image or video link, when it was posted, the caption, the accounts and hashtags tagged on it, the address behind any link sticker, any location tag, and the sponsored flag.
Here is the thing that decides whether this is useful to you. A story is gone 24 hours after it goes up, so a run only sees what is live at the moment you press Start. If you want the older material, that is what highlights are: the trays an account pins to its profile, which do not expire. They are on by default on paid plans. On the free Apify plan a run reads the first profile's live stories only, without highlights, and a free row in the dataset says so; a paid plan gets the full run.
| Input | Up to 10 public handles, @handles or profile URLs |
| Output | One row per story or highlight item: media type, image and video links, posting time, caption, mentions, link stickers, hashtags, location tag, sponsored flag, poster, highlight tray |
| Ceiling | 100 stories and 100 highlight items per profile, 10 profiles per run |
| Account needed | No account from you |
| Price | $2.50 per 1,000 rows on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 2,000 |
🔍 What Instagram Stories Scraper does
It reads what is live on each handle right now, plus the pinned highlight trays unless you untick
that box, and writes one row per item. Stories and highlights come back in the same shape, and
recordType tells you which you are looking at. Highlight rows also carry the tray they came from
in highlightTitle.
maxStoriesPerProfile is applied to current stories and to highlights separately. With highlights
ticked and the cap at 25, a profile with both can return up to 50 rows, and you pay per row. Set it low while you are
working out how much a handle actually has.
mode picks stories only, highlights only, or both. To see just which highlights an account has,
highlightTitlesOnly gives one row per tray. Each handle also ends with one free summary row saying
what the run found there.
📋 What data you get from each Instagram story
| What you get | Field |
|---|---|
| Story or highlight, and its id | recordType, storyId |
| Which of your handles it came from, and who posted it | sourceUsername, sourceProfileId, ownerUsername |
| The poster's name, verified badge and profile picture | ownerFullName, ownerIsVerified, ownerProfilePicUrl |
| Photo, video or carousel | mediaType |
| The image or cover frame, and the video file | imageUrl, videoUrl |
| Length and frame size | durationSeconds, dimensions |
| When it was posted, and when it expires | takenAt, expiresAt, expiresAtComputed |
| Caption and location sticker | caption, location |
| Accounts tagged, and hashtags | mentions, hashtags |
| Where the link stickers point | linkUrls |
| Paid-partnership flag | isSponsored |
| A link to the story | storyUrl |
| The highlight tray it is pinned in, its cover and size | highlightId, highlightTitle, highlightCoverUrl, highlightItemCount |
| One summary per handle | status, storiesDelivered, highlightsDelivered |
▶️ How to scrape Instagram stories
- Open Instagram Stories Scraper and click Try for free.
- Put your handles into Public Instagram profiles, up to ten.
- Set Maximum current stories per profile. Start at 5 while you look at the output shape.
- Pick What to read: live stories, highlights, or both, which is the default.
- Click Start, then download the dataset as JSON, CSV or Excel.
Start a run with no profiles and you get one labelled sample row showing the output shape. That row is not charged.
💰 How much does it cost to scrape Instagram stories?
$2.50 per 1,000 rows on the Free plan. Paid plans pay a little less: $2.48 on Starter, $2.46 on Scale and $2.44 on Business. On the free plan, the $5 Apify gives you each month covers about 2,000 rows. A run on the free plan reads only the first profile's live stories, without highlights, and ends with a free row saying it was limited. On a paid Apify plan the same input gets the full run.
One charge per row delivered, whether it is a live story or a highlight item. With
highlightTitlesOnly, each tray row is billed as one result, the same as a story. Sample rows,
diagnostic rows and the summary row for each handle are not billed, and a profile with nothing live
is not billed for results.
With highlights ticked the cap counts twice, once for current stories and once for highlights. A five-profile run at 25 can come back with 250 rows rather than 125 if every profile has both.
📥 What you give it
{"profiles": ["nasa", "natgeo"],"maxStoriesPerProfile": 25,"includeHighlights": true}
| Field | Default | What it is |
|---|---|---|
profiles | none | nasa, @nasa or a full profile URL. Up to 10 in one run. |
maxStoriesPerProfile | 25 | Rows per profile, 1 to 100, counted separately for current stories and for highlights. |
includeHighlights | true | The pinned trays. Untick it to get only what is live today. A profile with nothing pinned returns nothing extra. Needs a paid Apify plan. |
mode | both | both, storiesOnly or highlightsOnly. Highlights only skips the live stories and does not use a cookie. |
maxHighlightTrays | none | Read only the first this many trays of each profile, 1 to 100. Empty reads every tray. |
highlightTitlesOnly | false | One row per tray (title, cover, item count) without the items. |
maxRunSeconds | 120 | Wall-clock ceiling for the whole run, 20 to 180. |
requestTimeoutSeconds | 15 | How long one request may take, 5 to 30. |
maxAttempts | 6 | How many times a failed request is tried again before the run gives up on it. 1 to 12. |
sessionCookies | none | Optional: your own session, used only for your run. You are responsible for using it within the site's terms. Current stories only with it. |
proxyConfiguration | none | Optional. Servers of your own are used exactly as given. |
📤 What you get back
The row for one of National Geographic's stories from August 2026, with the long links cut short:
{"ok": true,"recordType": "story","storyId": "3966484401895803027","sourceUsername": "natgeo","sourceProfileId": "787132","ownerUsername": "natgeo","ownerFullName": "National Geographic","ownerIsVerified": true,"ownerProfilePicUrl": "https://scontent-lga3-3.cdninstagram.com/v/t51.82787-19/...","mediaType": "image","takenAt": "2026-08-18T14:03:28.000Z","expiresAt": "2026-08-19T14:03:28.000Z","expiresAtComputed": true,"caption": null,"imageUrl": "https://scontent-lga3-3.cdninstagram.com/v/t51.82787-15/...","videoUrl": null,"durationSeconds": 0,"dimensions": null,"isSponsored": false,"location": null,"linkUrls": ["https://www.nationalgeographic.com/health/article/bioelectronic-medicine-vagus-nerve-chronic-disease?cmpid=..."],"mentions": [],"hashtags": [],"storyUrl": "https://www.instagram.com/stories/natgeo/3966484401895803027/"}
A highlight row is the same shape with recordType: "highlight" and four extra fields naming the
tray it was pinned into: highlightId, highlightTitle, highlightCoverUrl and
highlightItemCount. With highlightTitlesOnly, a tray comes back as one highlight_title row
carrying those four and the handle, with no media.
| Field | How to read it |
|---|---|
storyId | Unique per item. Use it as your dedupe key across runs. |
mediaType | image, video or carousel. A video row carries both imageUrl (the cover frame) and videoUrl. |
imageUrl, videoUrl | Signed links that expire within hours. Download anything you want to keep, in the same job. |
takenAt | When the item was posted. null when Instagram did not supply it, never a made-up date. |
expiresAt | Instagram's own expiry when it sends one. When it does not, the posting time plus 24 hours, and expiresAtComputed is true. Always null on highlights, which do not expire. |
linkUrls | Where the story's link stickers go, unwrapped from Instagram's redirect link. An empty list when there are none. |
mentions, hashtags | Handles tagged on the story and hashtags placed on it, without the @ or #. Empty lists when there are none. |
dimensions | Frequently null. It arrives when Instagram sends it and is left empty when it does not. |
location | An object with the place id, name, address and coordinates when the item carries a location sticker. null otherwise. |
isSponsored | Instagram's own paid-partnership flag on the item. |
🧾 Reading the output
Four kinds of row land in your dataset, and only the first kind is billed.
| Row | How to spot it | Billed |
|---|---|---|
| A story, a highlight item, or a highlight tray | ok: true; recordType is story, highlight or highlight_title | yes |
| The summary for each handle | recordType: "account_status" | no |
| The sample row | _sample: true, and only on a run with no profiles | no |
| A diagnostic | ok: false and an errorCode | no |
Filter on ok == true and drop the _sample row if you have one, and you have your media. Every
diagnostic and summary row names the handle it belongs to in sourceUsername.
The summary row's status is live_stories_found, none_live, private or not_found. Two more
can appear: not_read when the run stopped before reaching that handle, and
stories_not_requested with mode set to highlights only. storiesDelivered and
highlightsDelivered count what you got for it.
| Code | What it means |
|---|---|
NO_CURRENT_STORIES | Nothing was live on that profile at the moment of the run. |
NOT_FOUND | No such account. |
PRIVATE_OR_RESTRICTED | The account is private, or closed to a reader who is not following it. |
BAD_INPUT | Nothing in profiles looked like a handle. |
PARTIAL | The run delivered some rows and then stopped. What arrived is complete and correct. |
FREE_PLAN_LIMIT | You are on the free Apify plan, so the run read only part of your input. profilesNotRead lists what it skipped. A paid plan gets the full run. |
DEADLINE_EXCEEDED | The run hit maxRunSeconds before reaching that profile. Raise it. |
RATE_LIMITED | Too many requests too close together. Space the runs out. |
AUTHENTICATION_FAILED, SESSION_EXHAUSTED | If you supplied a cookie, check it is still valid. |
PROXY_GROUP_IGNORED | A setting in proxyConfiguration could not be used as written. |
SERVER_ERROR, NETWORK | Instagram was unreachable or answered badly. Re-run it. |
No diagnostic row is billed as a result.
💡 What people use it for
- Checking daily whether a set of brands is running stories.
- Pulling a competitor's highlight trays as a snapshot of how they present themselves.
- Collecting story links and sponsored flags to see which creators are running paid placements.
🚧 What it does not do
- No expired stories. Once the 24 hours are up the item is gone, and highlights are the only way back to older material.
- No private accounts, and no accounts that only show stories to followers.
- No viewer lists, no reply counts, no poll or quiz results. Those are visible only to the account that posted.
- Highlights need a run without a cookie. Supply your own cookie and you get current stories
only, unless
modeis highlights only, which leaves the cookie unused. expiresAtis often worked out, not read. Instagram usually sends no expiry with a story, so the row gives the posting time plus 24 hours and says so inexpiresAtComputed.dimensionsis often empty, so do not build a pipeline that requires it.- Media links expire within hours. Download the files in the same job.
- Ten profiles per run, 100 rows per profile on each of the two kinds.
- It is not an official Instagram tool. Dami's Studio is independent and is not affiliated with or endorsed by Instagram or Meta, or by any other company named on this page.
🧭 Which Instagram scraper do you need?
| If you want | Use |
|---|---|
| Live stories and pinned highlights | This one |
| Posts and reels from a profile | Instagram Scraper |
| Follower counts, bio and links | Instagram Profile Scraper |
| Reels from a profile's reels tab | Instagram Reel Scraper |
| Posts other people made about a handle | Instagram Mentions Scraper |
| The current story on a public Snapchat profile | Snapchat Profile Scraper |
❓ Questions people ask
Do I need an Instagram account to scrape stories?
No, not from you. Leave the cookie field empty.
Why did I get nothing back?
Most likely nobody had a story live at that moment. The NO_CURRENT_STORIES row in your dataset
says so, and it is not billed.
Can I get Instagram stories from yesterday?
Only if the account pinned them into a highlight. Instagram deletes the rest after 24 hours.
How often should I schedule it?
Every few hours if you want to catch everything, since stories come and go inside a day. Dedupe on
storyId across runs.
Can I call it from code or connect it to an AI assistant?
Yes. The API tab has
ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP
client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-stories-scraper.
Either way the run happens on your Apify account at the same price.
Is scraping Instagram stories legal?
This reads public profiles only, never private accounts or messages. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the handle you used and the run ID. The errorCode
on the diagnostic row usually explains it on its own.