Instagram Story Scraper | Stories & Highlights
Pricing
from $3.82 / 1,000 stories
Instagram Story Scraper | Stories & Highlights
Extract Instagram stories and highlights from any public account: image and video links, exact posting time, expiry, swipe-up links and mentions, plus followers, following, posts, bio and website on every row. Track competitors, creators and news accounts daily with no login or account needed.
Pricing
from $3.82 / 1,000 stories
Rating
0.0
(0)
Developer
SilentFlow
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
3
Monthly active users
3 days ago
Last modified
Categories
Share
Instagram Story Scraper
Every active story and every highlight of a public Instagram account, as a table: image and video links, exact posting time, expiry, swipe-up link, mentions, and the account's followers on each row. Three news accounts, 43 stories, in 24 seconds. No login.
How it works

- You paste one or more accounts, or story links. A username, an
@handleor a profile link all name an account; a story link names one precise story. - Each account is read once. Its active stories come back in one call. If you ask for highlights, each album pinned on the profile is opened, newest first, up to the cap you set.
- One row comes back per story or highlight item. 26 fields: the media with its links and exact time, and the account it belongs to with followers, name, bio and website. Ready for a spreadsheet, a database or an AI pipeline.
β¨ Why teams choose this over other Instagram story scrapers
Taking screenshots of competitors' stories every morning before they vanish? Asked by a client to prove that a sponsored story went live at the right time with the right link? Getting back 150 raw keys per story and a unix timestamp when all you wanted was a date and a follower count?
- π 20 fields filled on every row, not 11. The other flat story scraper on the Store fills 11 keys per row; the most used ones return the raw Instagram object with 150 nested keys and unix timestamps. Here every story row carries 20 filled columns, measured on the default run of 22 September 2026 (43 rows, 21 columns filled on the majority of rows, the swipe-up
linkon 25 of them). No other story scraper putsfollowersCount,followingCount,postsCount,biographyandexternalUrlon the row. - π€ The account on every row. Followers, following, posts, name, bio, website, verified badge and avatar come with each story. One dataset answers both "what did they post" and "how big are they", with no second scraper to join.
- β° Exact time and expiry, in a format that sorts.
takenAtandexpiringAtare RFC 3339 (2026-09-21T22:07:02Z), not1758492422. Sort a day of stories, prove a posting window, schedule the next run before anything expires. - π Accounts or precise story links. Name an account by username,
@handleor profile link, or paste the link of one story (instagram.com/stories/cnn/3992904485714001336/) and get exactly that story with its account's figures, to prove a sponsored story went live. The most used scraper of the niche accepts plain usernames only, and no field here is required: accounts, links or both. - ποΈ Stories and highlights, chosen per run. Read what is live now, the permanent albums pinned on the profile, or both, with a cap on albums. The two most used story scrapers read stories only; highlights here return rows even at 3 a.m. when nothing is live.
- πΌοΈ Direct media links and a permalink.
imageUrlfor photos and posters,videoUrlfor the mp4 of video stories,thumbnailUrlfor a preview, and a stableurlper row. Download what you want to keep. - π§Ή No error rows. One row is one real story or highlight item. An unknown or private account produces no row and a clear message on the run, where other scrapers write an error item into your export. Unknown values are
null, never an empty string, and no item appears twice. - π No login, no account to connect. Public accounts only. Paste a username and press Start.
π― What you can do with Instagram story data
| Team | What they build |
|---|---|
| Influencer marketing | Proof of delivery for a paid story: the row shows when it went live, the link it carried and the media, taken by a schedule before it expired |
| Competitive research | A daily archive of every story a list of rival brands posted, with links, mentions and media, searchable months later |
| Social media agencies | A morning digest of what each client's competitors pushed overnight, ready for Slack or a spreadsheet |
| Affiliate and e-commerce | A tracker of the swipe-up links and promo codes creators post in stories, with the UTM tags as they appear |
| Newsrooms and PR | A timeline of the stories a public figure or a news account published around an event, with exact times |
| Research and archives | A dataset of a brand's highlight albums, item by item, with posting dates that span years |
| Creator platforms | A vetting card per creator: followers, posting cadence in stories, share of video versus image, links pushed |
π₯ Input parameters
Essentials
| Field | Type | Description |
|---|---|---|
usernames | array | Public accounts to read, one per line. Accepts a username (cnn), a handle (@cnn) or a profile link (https://www.instagram.com/cnn/). |
startUrls | array | Links of precise stories (https://www.instagram.com/stories/cnn/3992904485714001336/): each gives exactly that story while it is live (24 hours). A profile link here reads the whole account. Highlight links do not name their account: add the account and choose highlights instead. Fill usernames, startUrls or both. |
maxItems | integer, default 100 | Maximum rows for the whole run, stories and highlight items together. |
ποΈ Content
| Field | Type | Description |
|---|---|---|
contentType | string, default stories | stories reads what the account posted in the last 24 hours, one call per account. highlights reads the permanent albums pinned on the profile, one call per album. both reads the two. |
maxHighlights | integer, default 5 | How many highlight albums to open per account, newest first. Each album returns all its items. Ignored when contentType is stories. |
βοΈ Advanced
| Field | Type | Description |
|---|---|---|
debugMode | boolean, default false | Adds detailed lines to the run log. Leave it off for normal runs. |
π Output data
Each row is one story or one highlight item. An active story of a news account looks like this (long media links shortened here):
{"id": "3989588439640364857_217723373","url": "https://www.instagram.com/stories/cnn/3989588439640364857/","type": "story","mediaType": "image","highlightId": null,"highlightTitle": null,"link": "https://www.cnn.com/2026/09/19/style/cfda-fashion-boss-resigns-kolb-protesters-hnk-intl?utm_medium=social&utm_source=igstoryCNN","mentions": [],"username": "cnn","userId": "217723373","fullName": "CNN","biography": "Asking the hard questions and bringing unique perspective from across the globe. This is CNN.","externalUrl": "http://cnn.com/linkinbio","isVerified": true,"followersCount": 23592848,"followingCount": 323,"postsCount": 29599,"profilePicUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.2885-19/353448964_228072746694866_3965541026640463359_n.jpg?β¦","takenAt": "2026-09-19T11:07:04Z","expiringAt": "2026-09-20T11:07:04Z","highlightCreatedAt": null,"imageUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.82787-15/818122990_18633735430059374_6730580538173429432_n.jpg?β¦","videoUrl": null,"thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.82787-15/818122990_18633735430059374_6730580538173429432_n.jpg?β¦","input": "cnn","scrapedAt": "2026-09-20T03:38:17Z"}
A video item of a highlight album keeps the same 26 columns. It carries the mp4 in videoUrl, its poster in imageUrl, the album in highlightId and highlightTitle, and no expiringAt since highlights do not expire (account block shortened here):
{"id": "3797974848153407573_217723373","url": "https://www.instagram.com/s/aGlnaGxpZ2h0OjE4NTQ3NjI4MzIwMDE2NTQy?story_media_id=3797974848153407573","type": "highlight","mediaType": "video","highlightId": "18547628320016542","highlightTitle": "π","link": null,"mentions": [],"username": "cnn","userId": "217723373","fullName": "CNN","followersCount": 23592848,"takenAt": "2025-12-29T02:05:04Z","expiringAt": null,"highlightCreatedAt": "2025-12-29T02:06:51Z","imageUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.71878-15/β¦jpg?β¦","videoUrl": "https://scontent-lga3-2.cdninstagram.com/o1/v/t2/f2/m78/β¦mp4?β¦","thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.71878-15/β¦jpg?β¦","input": "https://www.instagram.com/cnn/","scrapedAt": "2026-09-20T03:47:33Z"}
ποΈ Data fields
26 fields per row: 4 identity, 4 content, 10 account, 3 time, 3 media, 2 meta. mentions is the only list, the usernames tagged in the story.
| Group | Fields |
|---|---|
| Identity | id (Instagram media id), url (permalink), type (story or highlight), mediaType (image or video) |
| Content | highlightId, highlightTitle, link (the swipe-up link), mentions |
| Account | username, userId, fullName, biography, externalUrl, isVerified, followersCount, followingCount, postsCount, profilePicUrl |
| Time | takenAt (RFC 3339, UTC), expiringAt (stories only, 24 hours after takenAt), highlightCreatedAt (highlight items only) |
| Media | imageUrl (the photo, or the poster of a video), videoUrl (mp4, videos only), thumbnailUrl |
| Meta | input (the account as you typed it), scrapedAt (RFC 3339, UTC) |
Good to know when you store the data:
idis Instagram's own media id and never changes.urlis built from it: the story permalink for a story, the share link of the album item for a highlight.takenAtis the moment the story was posted.expiringAtis when Instagram removes it from the profile. A highlight item keeps its originaltakenAt, which can be years old, andhighlightCreatedAttells when the album was created.imageUrl,videoUrl,thumbnailUrlandprofilePicUrlpoint to Instagram's own media servers. They stay valid for a few days, then Instagram rotates them: download the files you want to keep,urlstays.linkis set only when the story carries a swipe-up link,mentionsis an empty list when nobody is tagged.followersCount,followingCountandpostsCountare the numbers shown on the profile at run time.- The account block is identical on every row of an account, so the first row of each
usernameis the account's profile.
π Examples
Get the active stories of three news accounts
{"usernames": ["cnn", "bbcnews", "skynews"]}
Watch a list of competitors every morning
Put this on a daily schedule. Each run returns what is live at that moment, with time, link and media.
{"usernames": ["@nike", "@adidas", "@puma", "@newbalance"],"maxItems": 200}
Export the highlight albums of a brand
{"usernames": ["https://www.instagram.com/cnn/"],"contentType": "highlights","maxHighlights": 10,"maxItems": 500}
Read stories and the latest album together
{"usernames": ["foxnews", "skynews"],"contentType": "both","maxHighlights": 1,"maxItems": 100}
Check that a sponsored story is live on a creator's account
{"usernames": ["https://www.instagram.com/bleacherreport/"],"maxItems": 20}
Sample a large watchlist quickly
{"usernames": ["cnn", "bbcnews", "skynews", "foxnews", "bleacherreport", "natgeo"],"maxItems": 30}
π€ Copy to your AI assistant
Paste this block into Claude, ChatGPT or Cursor to give it full context about this scraper:
You have access to the Instagram Story Scraper on Apify: silentflow/instagram-story-scraperInput schema:- usernames (array of strings): Instagram usernames, @handles or profile links of public accounts- startUrls (array of {url}): links of precise stories, each returning exactly that story while it is live; fill usernames, startUrls or both- maxItems (integer, default 100): max rows for the whole run- contentType (string, default "stories"): "stories" (last 24 hours), "highlights" (permanent albums) or "both"- maxHighlights (integer, default 5): albums opened per account, newest first- debugMode (boolean, default false)Output, one row per story or highlight item (26 fields, null when unknown):- id (string), url (string), type ("story" | "highlight"), mediaType ("image" | "video")- highlightId (string), highlightTitle (string), link (string), mentions (string[])- username, userId, fullName, biography, externalUrl, profilePicUrl (strings)- isVerified (boolean), followersCount, followingCount, postsCount (integers)- takenAt, expiringAt, highlightCreatedAt (RFC 3339 UTC)- imageUrl, videoUrl, thumbnailUrl (strings, Instagram media links valid a few days)- input (string), scrapedAt (RFC 3339 UTC)Private accounts and unknown usernames return no row. No login needed. Use apify-client for Python or JavaScript.
π» Integrations
Keep a daily archive of competitors' stories (Python)
import csvfrom apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("silentflow/instagram-story-scraper").call(run_input={"usernames": ["nike", "adidas", "puma"],"maxItems": 200,})rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())with open("stories-archive.csv", "a", newline="") as f:writer = csv.writer(f)for r in rows:writer.writerow([r["takenAt"], r["username"], r["mediaType"], r["link"], ",".join(r["mentions"]), r["url"], r["videoUrl"] or r["imageUrl"]])print(f"{len(rows)} stories archived")
Alert Slack when a creator posts a story with a link (JavaScript)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('silentflow/instagram-story-scraper').call({usernames: ['bleacherreport', 'espn'],maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const story of items.filter((s) => s.link)) {await fetch(process.env.SLACK_WEBHOOK_URL, {method: 'POST',body: JSON.stringify({ text: `@${story.username} posted a story at ${story.takenAt} linking to ${story.link}` }),});}
Download the media of a highlight album (Python)
import requestsfrom apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("silentflow/instagram-story-scraper").call(run_input={"usernames": ["cnn"],"contentType": "highlights","maxHighlights": 1,"maxItems": 100,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():media_url = item["videoUrl"] or item["imageUrl"]ext = "mp4" if item["videoUrl"] else "jpg"with open(f'{item["username"]}-{item["id"]}.{ext}', "wb") as f:f.write(requests.get(media_url, timeout=60).content)
π Performance
Measured on 22 September 2026 on real accounts.
| Run | Rows | Time |
|---|---|---|
| 3 news accounts, active stories (the default input) | 43 | 24 seconds |
| 1 account by profile link, its 2 latest highlight albums | 28 | 23 seconds |
| 3 accounts, stories and 1 album each, one unknown account, capped at 25 | 25 | 25 seconds |
| 2 sports accounts by profile link, active stories | 13 | 42 seconds |
| 2 news accounts, capped at 5 | 5 | 12 seconds |
| Metric | Value |
|---|---|
| Fields per row | 26 |
| Calls per account | 1 for stories, plus 1 per highlight album |
| Time per call | about 10 seconds, the pace the source allows |
| Columns filled on the default run | all, except link and mentions when the story carries none, and the highlight columns on stories |
| Limit per run | no fixed limit: maxItems is yours to set |
πΎ Data export
Every run stores its rows in a dataset you can download as JSON, CSV, Excel, XML or HTML from the Storage tab, or pull from the API:
https://api.apify.com/v2/datasets/{DATASET_ID}/items?format=csv&token=YOUR_TOKEN
The dataset has two ready-made table views: Stories (account, type, media, highlight, posted, swipe-up link, story URL, image) and Accounts (account, name, followers, following, posts, verified, website, avatar). Schedules, webhooks and the Apify integrations (Google Sheets, Slack, Zapier, Make, n8n) work on top of the same dataset.
π‘ Tips for best results
- Schedule twice a day for a complete archive. Stories last 24 hours. A run every 12 hours sees every story at least once;
expiringAttells you how much margin you had. - Start with accounts that post daily. News and sports accounts have stories around the clock. A brand that posts twice a week returns no story row on most runs, which is normal: switch to
bothto always get rows. - Use
highlightsfor permanent content. Campaign albums, product albums and press albums stay on the profile for years.maxHighlightsdecides how many albums open, newest first. - Download the media you want to keep. Instagram rotates its media links after a few days.
urlstays valid, the files do not. - Size
maxItemsfor the whole run. Ten accounts with about 8 stories each needmaxItems: 100. With highlights, count up to 100 items per album. - Group rows by
usernamefor account reports. The account block is identical on every row of an account.
β FAQ
What does this scraper extract? The active stories and the highlight albums of public Instagram accounts, one row per item, with 26 fields: the media (type, image, video, thumbnail, permalink), its exact posting time and expiry, the swipe-up link and mentions, the album it belongs to, and the account (name, bio, website, verified badge, followers, following, posts, avatar).
What can I type in the accounts field?
A username (cnn), a handle (@cnn), a profile link in any form (https://www.instagram.com/cnn/, instagram.com/cnn), or a story link (instagram.com/stories/cnn/β¦). A link to a post or a reel is skipped and named in the run log.
Do I need an Instagram account? No. The scraper reads public accounts. There is no login, no key and no session to refresh.
Why does an account return no story?
Stories last 24 hours. If the account posted nothing in that window, there is nothing to read, and the run log says so. Run again later, put the run on a schedule, or set contentType to both to get the highlight albums as well.
What about private accounts? Their stories are not public, so the scraper skips them, names them in the run log, and writes no row. Your dataset never contains error rows.
How fresh is the data?
Live. Every run reads the accounts at run time. scrapedAt tells you when each row was read, takenAt when the story was posted.
Are the media links permanent?
url is permanent. imageUrl, videoUrl, thumbnailUrl and profilePicUrl are links to Instagram's media servers and stay valid for a few days. Download the files you want to keep.
Can I scrape many accounts in one run? Yes. List as many accounts as you need. An account named twice is read once, and no item is delivered twice in a run. Each account takes about ten seconds, plus about ten seconds per highlight album.
How do highlights work?
Highlights are the albums pinned under the bio of a profile. With contentType set to highlights or both, the scraper opens up to maxHighlights albums, newest first, and returns every item of each album with the album's id, title and creation date.
Does it get story views, replies or the viewers list? No. Those numbers are only visible to the account owner. The scraper returns what a visitor of the profile can see.
Is there a limit on the number of rows?
No fixed limit. maxItems caps the whole run and you choose it.
Can I get the text written on a story? Not as a field: Instagram does not publish the text of stickers and captions. You get the image or video, which you can pass to an OCR or vision model.
βοΈ Legal
This Actor extracts publicly available data from Instagram. It does not bypass any login, paywall or CAPTCHA, and it only reads public accounts. Users are responsible for complying with Instagram's terms of service and with applicable data protection laws (GDPR, CCPA, and PIPL where relevant). The output contains account information that account owners publish themselves (username, name, bio, website, follower counts, avatar); when you process it as personal data, handle it accordingly. The data returned is informational; verify accuracy for regulated use cases.
π Related scrapers
- Instagram Engagement Scraper: likes and comments behind Instagram posts.
- TikTok Scraper: videos and profiles from TikTok.
- Youtube Channel Scraper: every video of a channel with exact dates, views and likes.
- Facebook Search Scraper: posts, pages and videos from Facebook search.
π¬ Support
Need something this scraper does not do yet? We ship features fast.
- Feature requests go straight to our backlog
- Enterprise needs? We do custom integrations and high-volume plans
- Pricing details live on the Monetization tab of the actor page
Response time: usually under 24 hours.
Check out our other scrapers: silentflow on Apify