Instagram Stories & Highlights Scraper - Media Export

Export accessible Instagram Stories and Highlights with direct media URLs, timestamps, captions, links, mentions, hashtags, stickers, music, profile metrics, and Highlight context. Use usernames, profile URLs, date filters, CSV, Excel, JSON, API, or MCP. Authorized session cookie required.

Data fields

FieldTypeDescription
kindstringValue exported as kind.
usernamestringValue exported as username.
profileUrlstringValue exported as profileUrl.
profileIdstring | nullValue exported as profileId.
fullNamestring | nullValue exported as fullName.
biographystring | nullValue exported as biography.
isVerifiedboolean | nullValue exported as isVerified.
isPrivateboolean | nullValue exported as isPrivate.

Input preview

targetsInstagram profiles *
maxProfilesMaximum profiles
includeStoriesInclude active stories
includeHighlightsInclude saved highlights
maxHighlightsPerProfileMaximum highlights per profile
maxItemsPerHighlightMaximum items per highlight

API and agents

This actor can be run through Apify API, datasets, webhooks, schedules, and the official Apify MCP server.

How this actor works

See example inputs, outputs, API usage, and practical limits before running this actor on Apify.

Open Apify page

Export accessible Instagram Stories and Highlights with direct image/video URLs, timestamps, captions, links, mentions, hashtags, stickers, music, profile metrics, and highlight context. Download results as CSV, Excel, JSON, XML, or RSS, or use them through the Apify API and MCP server.

Instagram requires a logged-in session for story and highlight access. Supply your own authorized sessionid value or full Cookie header. This Actor does not log in for you, bypass private-profile permissions, or expose the cookie in output.

What can it do?

  • Collect active 24-hour Stories and saved Highlight items.
  • Return direct image/video variants, thumbnails, dimensions, duration, audio presence, and accessibility captions.
  • Extract visible captions, links, mentions, hashtags, sticker types, and music title/artist/ID.
  • Preserve highlight ID, title, cover, order, item order, and item count.
  • Add profile ID, name, biography, verification/privacy status, picture, follower/following/post counts, business category, and external URL when Instagram returns them.
  • Filter returned media by sinceDate and prevent duplicate rows by stable ID.
  • Keep valid results when another profile or one media source fails.
  • Distinguish a verified no-media profile from an expired cookie, private/missing profile, rate limit, changed response, or deadline stop in RUN_SUMMARY.

Who is it for

This scraper is for social media analysts, brand owners, agencies, journalists, and compliance teams that need structured exports of Instagram Stories and Highlights they are authorized to view.

Access and permitted use

Only export Instagram content you are allowed to access and process. Respect Instagram's terms, privacy rules, copyright, and local data-protection laws. Do not use exported media or profile data for spam, harassment, or unauthorized surveillance.

Use cases

  • Archive authorized campaign Stories before their 24-hour expiry.
  • Monitor accessible brand or creator Highlights for additions and changes.
  • Verify influencer Story links, mentions, media, and timestamps.
  • Compare Highlight themes, titles, covers, and content across public profiles.
  • Feed scheduled media snapshots into spreadsheets, warehouses, alerts, dashboards, or research agents.

Use a secondary Instagram account dedicated to authorized research where possible. In your logged-in browser, copy either the sessionid cookie value or the full Cookie header and paste it into the secret instagramCookies input.

The session can access only content that account is allowed to view. This Actor rejects private profiles instead of attempting to bypass privacy. Instagram may expire the session, request a checkpoint, or restrict a session/IP; renew the cookie in your browser when that happens. Never paste a cookie into an issue, task title, log, README, or public message.

Input settings

Setting JSON field Description
Profiles targets One or more usernames, @handles, or exact Instagram profile URLs. Duplicate profiles run once.
Maximum profiles maxProfiles Process 1-1,000 unique profiles.
Active Stories includeStories Collect active Stories visible to the session.
Highlights includeHighlights Collect saved Highlight collections/items visible to the session.
Highlight limit maxHighlightsPerProfile Process 0-200 Highlights per profile.
Item limit maxItemsPerHighlight Export 1-500 items per Highlight.
Date filter sinceDate Optional ISO date/timestamp; older returned media is filtered.
No-media row saveProfileOnNoMedia Save a status row after an authorized check confirms no matching media. When false, a valid no-media result has no dataset row to carry the hidden recovery anchor; after an unclean stop before the checkpoint is saved, that profile can be checked and charged again on retry. Exact-once recovery applies only when an output row exists.
Raw data includeRaw Preserve the source media object. Defaults to true for backward compatibility.
Session cookie instagramCookies Required authorized sessionid value or full Cookie header. Stored as a secret input.
Proxy proxyConfiguration Apify Proxy configuration; residential/ISP routes are usually more reliable.
Reliability retryCount, initialRetryDelayMillis, requestPacingMillis, runTimeSecs Optional retry, pacing, and safe-deadline controls.

The backward-compatible startUrls input remains accepted through API calls even though targets is the preferred UI field.

Input example

{
  "targets": ["natgeo", "https://www.instagram.com/instagram/"],
  "instagramCookies": "sessionid=YOUR_AUTHORIZED_SESSION_ID",
  "includeStories": true,
  "includeHighlights": true,
  "maxProfiles": 2,
  "maxHighlightsPerProfile": 5,
  "maxItemsPerHighlight": 20,
  "sinceDate": "2026-07-01T00:00:00Z",
  "includeRaw": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}

Output example

{
  "kind": "highlight_item",
  "username": "natgeo",
  "profileUrl": "https://www.instagram.com/natgeo/",
  "profileId": "787132",
  "fullName": "National Geographic",
  "isVerified": true,
  "status": "ok",
  "sourceUrl": "https://www.instagram.com/stories/highlights/123456/",
  "stableId": "787132:highlight_item:123456:987654",
  "mediaId": "987654",
  "mediaType": "video",
  "mediaUrl": "https://scontent.cdninstagram.com/video.mp4",
  "thumbnailUrl": "https://scontent.cdninstagram.com/image.jpg",
  "imageUrls": ["https://scontent.cdninstagram.com/image.jpg"],
  "videoUrls": ["https://scontent.cdninstagram.com/video.mp4"],
  "caption": "Field notes #Wildlife",
  "takenAt": "2026-07-14T10:00:00.000Z",
  "durationSeconds": 8.5,
  "width": 1080,
  "height": 1920,
  "linkUrls": ["https://example.org/story"],
  "mentions": ["example_creator"],
  "hashtags": ["Wildlife"],
  "stickerTypes": ["link"],
  "musicTitle": "Example track",
  "musicArtist": "Example artist",
  "highlightId": "123456",
  "highlightTitle": "Expeditions",
  "highlightIndex": 1,
  "highlightItemIndex": 2,
  "highlightItemCount": 12,
  "scrapedAt": "2026-07-14T10:05:00.000Z",
  "raw": null
}

Direct CDN media URLs can expire or require compatible session context later. Archive authorized media promptly if long-term retention is part of your workflow.

Reliability and charging behavior

  • Input and cookie format are validated before the start event.
  • The start charge is fatal; it is never silently ignored.
  • A profile event is charged only after an authorized profile check produces media or confirms a valid no-media result.
  • Missing, private, authentication-rejected, rate-limited, deadline, and other failed profiles produce diagnostic rows without a profile event.
  • If every profile fails, the platform run fails instead of appearing green with paid error rows.
  • Mixed runs preserve successful media and finish with PARTIAL in RUN_SUMMARY.
  • Bounded retries use profile-specific proxy sessions, exponential backoff, and Retry-After when Instagram supplies it.
  • Highlight items are requested in bounded batches; repeated media IDs are removed.
  • A safe work deadline leaves time to persist rows and RUN_SUMMARY before the platform timeout.

API usage

JavaScript

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/instagram-stories-highlights-scraper').call({
  targets: ['natgeo'],
  instagramCookies: process.env.INSTAGRAM_COOKIE,
  includeStories: true,
  includeHighlights: true,
  maxHighlightsPerProfile: 5,
  includeRaw: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('fetch_cat/instagram-stories-highlights-scraper').call(run_input={
    'targets': ['natgeo'],
    'instagramCookies': os.environ['INSTAGRAM_COOKIE'],
    'includeStories': True,
    'includeHighlights': True,
    'maxHighlightsPerProfile': 5,
    'includeRaw': False,
})
print(client.dataset(run['defaultDatasetId']).list_items().items)

cURL

curl -X POST 'https://api.apify.com/v2/acts/fetch_cat~instagram-stories-highlights-scraper/runs?token=YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"targets":["natgeo"],"instagramCookies":"sessionid=YOUR_AUTHORIZED_SESSION_ID","includeStories":true,"includeHighlights":true}'

Keep cookies in environment variables or secret inputs rather than source code or shell history.

MCP and AI agents

Use the Actor through the Apify MCP server:

https://mcp.apify.com/?tools=fetch_cat/instagram-stories-highlights-scraper

Add it to Claude Code:

claude mcp add apify-instagram-stories 'https://mcp.apify.com/?tools=fetch_cat/instagram-stories-highlights-scraper'

Example MCP JSON configuration:

{
  "mcpServers": {
    "apify-instagram-stories": {
      "url": "https://mcp.apify.com/?tools=fetch_cat/instagram-stories-highlights-scraper"
    }
  }
}

Example prompts:

  • “Using my secret Instagram session input, export the accessible Stories from these three public brand profiles.”
  • “Collect the first five Highlights for this profile and list external Story links and mentions.”
  • “Return media posted since yesterday and summarize music and sticker usage.”

Support

If a run behaves unexpectedly, open an Actor issue with:

  • The run ID or run URL.
  • The input JSON with instagramCookies, proxy URLs, and all secrets removed.
  • The expected output and actual output returned by the dataset.
  • An example reproducible public URL, when possible.

Never post a session cookie. RUN_SUMMARY is designed to show whether the problem was input validation, an expired/rejected session, a private/missing profile, source response change, rate limit, partial source failure, or deadline.

Privacy and data handling

Use this Actor only for content your session is authorized to view and for a lawful purpose. Inputs and outputs remain in your Apify account storage according to your settings. Requests go to Instagram and, when enabled, through Apify Proxy; FetchCat does not send them to advertising networks, data brokers, or model-training services.

Common questions

Questions and answers reused from the canonical actor README.

Why is a session cookie required for public profiles?

Instagram’s current story/highlight interfaces require a logged-in session even when the target profile is public. Anonymous third-party claims do not change the requirements of the direct Instagram interface used by this Actor.

Why did the run fail instead of returning an auth_required success row?

If every profile is rejected, a failed run prevents authentication errors from masquerading as successful paid extraction. The dataset and RUN_SUMMARY still explain the failure; no profile event is charged for the rejected target.

Can it access a private profile?

No. The Actor explicitly rejects private profiles and does not use session follows to bypass this rule.

Why are some media fields empty?

Instagram varies fields by image/video, sticker type, region, account, experiment, and content age. The Actor preserves available variants and raw data when requested, but does not invent missing values.

How should I schedule active Story monitoring?

Run at least daily because active Stories expire after roughly 24 hours. Use sinceDate and stableId to filter and deduplicate downstream archives.