# Instagram Stories & Highlights Scraper (`maximedupre/instagram-stories-highlights`) Actor

Collect live stories and saved highlights from public Instagram accounts. Get photos, videos, download links, account details, and story times. You can also get items this Actor saved on earlier runs.

- **URL**: https://apify.com/maximedupre/instagram-stories-highlights.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Social media, Marketing, Videos
- **Security:** Limited permissions
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 stories

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 📸 Save Instagram stories and highlights for content research

Instagram Stories & Highlights Scraper helps marketers, creator teams, and researchers collect public [Instagram](https://www.instagram.com/) stories and saved highlights. Get one row per photo or video, with account details, media links, saved download files, and times. Use the data to review content and keep copies after Instagram's media links expire.

- Save live stories from public brands for a campaign review.
- Collect the photos and videos in a profile's saved highlights for a content audit.
- Read link stickers and mentions to study where story content sends people.
- Get one highlight by its link to review a specific collection.
- Include items saved on earlier runs to review content that is no longer live.

#### 🗂️ Photos, videos, and story details

Each dataset row is one story item, whether it comes from live stories or a highlight. Highlight items include the highlight ID and, when available, its title and cover image. Other available fields include dimensions, video length, link stickers, mentions, and a reshared post link.

The Actor saves copies of media files as well as Instagram's own media URLs. The saved files can stay available after Instagram's URLs expire, subject to your Apify storage retention. Optional fields appear only when available. Duplicate story IDs are saved once per run. If the same item is found through several inputs or highlights, the saved row describes the occurrence that was saved first.

#### ▶️ Collect stories from accounts or links

1. Add public usernames, @handles, profile links, story links, or highlight links to **Accounts or links**.
2. Choose live stories, highlights, or both for usernames and profile links.
3. Set a run-wide item limit, or leave it empty to collect all available items.
4. Start the run, then open its dataset and download links.

You do not need to supply an Instagram login, cookies, or API key. Private accounts are skipped. Available content can change between runs, and a run can return fewer items than the limit.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `accounts` | array of strings | Required. Mix usernames, @usernames, Instagram profile URLs, story URLs, and highlight URLs. The form prefills `instagram`; this is not a schema default. Invalid inputs are skipped. |
| `contentTypes` | array of strings | Accepts `stories`, `highlights`, or both. Defaults to both when omitted. An empty array skips usernames and profile links. Story and highlight links select their own content regardless of this choice. |
| `maxItems` | integer | Run-wide maximum number of unique story items. Accepts whole numbers of 0 or more. Omit it or use `0` for no item cap. The form prefills `5`; this is not a schema default. |
| `includeExpired` | boolean | Defaults to `false`. Includes items this Actor saved on earlier runs that are no longer returned for an account. Usernames and profile links use the selected content types. Account story links (`/stories/username/`) include past stories only, regardless of `contentTypes`, and exclude past highlight items. It does not recover unseen content or add past items to a single-item story link or a highlight link. |

A story URL ending in `/stories/username/` selects that account's live stories. A URL with a story ID selects only that story. A highlight URL selects the items in that highlight. You can mix these with usernames and profile links in one run.

**Example input**

This is the public input from the successful default-input beta run:

```json
{
  "accounts": [
    "instagram"
  ],
  "contentTypes": [
    "stories",
    "highlights"
  ],
  "maxItems": 5,
  "includeExpired": false
}
```

#### 🧾 Output

**Output fields**

Live stories and highlight items share this row shape. Fields that do not apply or are unavailable are omitted.

| Field | Type | What it does |
| --- | --- | --- |
| `id` | string | Instagram story item ID. |
| `url` | string | Instagram link to the story item. |
| `input` | string | Submitted account or link that led to the saved item. |
| `owner` | object | Account that posted the item. |
| `owner.username` | string | Instagram username. |
| `owner.id` | string | Instagram account ID, when available. |
| `owner.fullName` | string | Account display name, when available. |
| `owner.isVerified` | boolean | Whether the account has a verified badge, when available. |
| `highlight` | object | Highlight that holds this item. Omitted for live stories. |
| `highlight.id` | string | Highlight ID. |
| `highlight.title` | string | Highlight title, when available. |
| `highlight.coverImageUrl` | string | Highlight cover image URL, when available. |
| `mediaType` | string | `image` or `video`. |
| `width` | integer | Media width in pixels. |
| `height` | integer | Media height in pixels. |
| `videoDuration` | number | Video length in seconds. Only for videos. |
| `imageUrl` | string | Instagram photo URL or video preview image URL. It can expire. |
| `videoUrl` | string | Instagram video URL. Only for videos. It can expire. |
| `imageFileUrl` | string | Download link for the saved photo or video preview image. |
| `videoFileUrl` | string | Download link for the saved video file. Only for videos. |
| `postedAt` | string | Posted time in ISO date-time format. |
| `expiresAt` | string | Live story expiration time in ISO date-time format. |
| `capturedAt` | string | Last time this Actor saved the item, in ISO date-time format. Past items keep their earlier capture time. |
| `linkStickers` | array of objects | Link stickers, when present. |
| `linkStickers.url` | string | Web address opened by a sticker. |
| `mentions` | array of strings | Mentioned Instagram usernames, when present. |
| `resharedPost` | object | Post or reel reshared in the story, when present. |
| `resharedPost.url` | string | Permanent Instagram post or reel URL. |
| `resharedPost.ownerUsername` | string | Original post owner's username, when available. |

**Example highlight item**

This genuine video row comes from a successful beta run:

```json
{
  "id": "3398250234472938888",
  "url": "https://www.instagram.com/stories/instagram/3398250234472938888/",
  "input": "instagram",
  "owner": {
    "username": "instagram",
    "id": "25025320",
    "fullName": "Instagram",
    "isVerified": true
  },
  "highlight": {
    "id": "18223279177302854",
    "title": "close friends",
    "coverImageUrl": "https://scontent.cdninstagram.com/v/t51.71878-15/756700225_1653985762331725_8429300849500507026_n.jpg?stp=dst-jpg_s150x150_tt6&_nc_cat=1&ccb=7-5&_nc_sid=acbce5&_nc_ohc=CS02agR9HxEQ7kNvwGcNOY7&_nc_oc=Adp6wqvbFviX0dSmXSY_rbWfni4K6U6DG7m1uHy9DndThFvhWj3wLzay8ghhDsFDeOo&_nc_zt=23&_nc_ht=scontent.cdninstagram.com&_nc_gid=pydoxZ0DREgHgyf4j_e9UQ&_nc_ss=7b689&oh=00_AQTFZ4dreV1exAi3IessKD2SYauLmjHmy69fqBkSimoxWg&oe=6AF0947E"
  },
  "mediaType": "video",
  "width": 720,
  "height": 1280,
  "videoDuration": 15,
  "imageUrl": "https://scontent-jnb2-1.cdninstagram.com/v/t51.71878-15/553371552_1466879574367694_447362504004074224_n.jpg?stp=dst-jpg_e15_tt6&_nc_cat=103&ig_cache_key=MzM5ODI1MDIzNDQ3MjkzODg4OA%3D%3D.3-ccb7-5&ccb=7-5&_nc_sid=58cdad&efg=eyJ2ZW5jb2RlX3RhZyI6IlNUT1JZLnhwaWRzLjY0MC5zZHIudmlkZW9fZGVmYXVsdF9jb3Zlcl9mcmFtZS5DMyJ9&_nc_ohc=2ZX7u4o9hJQQ7kNvwE_n8q5&_nc_oc=AdrfOPhYyCrKnU6H9ckwsCZzz9NqnUQSRECTuyq8QIz4cuIieUl-A03Ou6Vckfu9mU4&_nc_zt=23&_nc_ht=scontent-jnb2-1.cdninstagram.com&_nc_gid=EV_AA4am645GCXbRwld3fQ&_nc_ss=7b689&oh=00_AQTfVz27xrEAvmK5F2jhwuEP066dKvnT9UF-4au4i7z-Sw&oe=6AEF3441",
  "videoUrl": "https://scontent-jnb2-1.cdninstagram.com/o1/v/t2/f2/m78/AQPV7AvHfaG9MIs3LiSITpbxkDqMwQHcfHTFVqYxTG7VBxJZOYp87i4HBo4GsWYP_6zTafYVDZTT5gYa5xYnxT5af7173SQCAHRyIcE.mp4?_nc_cat=110&_nc_sid=5e9851&_nc_ht=scontent-jnb2-1.cdninstagram.com&_nc_ohc=5YA4hzMd7D0Q7kNvwEQnNcT&efg=eyJ2ZW5jb2RlX3RhZyI6Inhwdl9wcm9ncmVzc2l2ZS5JTlNUQUdSQU0uU1RPUlkuQzMuNzIwLmRhc2hfYmFzZWxpbmVfMV92MSIsInhwdl9hc3NldF9pZCI6MTE0Njc0Nzg5OTcxNDE5OCwiYXNzZXRfYWdlX2RheXMiOjg2MCwidmlfdXNlY2FzZV9pZCI6MTA4MjYsImR1cmF0aW9uX3MiOjE1LCJ1cmxnZW5fc291cmNlIjoid3d3In0%3D&ccb=17-1&vs=cfe2bfec8b4d2eb6&_nc_vs=HBksFQIYUWlnX3hwdl9wbGFjZW1lbnRfcGVybWFuZW50X3YyLzQxNEY2MUUyOTE2MDlDOTBGRkFBNjhDNjJBNUNEQjkwX3ZpZGVvX2Rhc2hpbml0Lm1wNBUAAsgBEgAVAhhGaWdfeHB2X3JlZWxzX3Blcm1hbmVudF9zcl9wcm9kLzkwMzMzMDUxNTEyNTE1NF84NzMwODM5MjIxOTkzNTgxMzY3Lm1wNBUCAsgBEgAoABgAGwKIB3VzZV9vaWwBMRJwcm9ncmVzc2l2ZV9yZWNpcGUBMRUAACas6qzTwb2JBBUCKAJDMywXQC4AAAAAAAAYEmRhc2hfYmFzZWxpbmVfMV92MREAdegHZZSpAQA&_nc_gid=EV_AA4am645GCXbRwld3fQ&_nc_ss=7b689&_nc_zt=28&oh=00_AQT8xhlCmjb-drAL93I2shkeGsAfPo07PicwsQf-9ZSKPA&oe=6AEB4F3B",
  "imageFileUrl": "https://api.apify.com/v2/key-value-stores/PuAoHIZkGfEPh6Umd/records/3398250234472938888-image?signature=1fA5SSYDxI12MWdtYaYuA",
  "videoFileUrl": "https://api.apify.com/v2/key-value-stores/PuAoHIZkGfEPh6Umd/records/3398250234472938888-video?signature=kl4cfLQkXfKMnRWm2Q3F",
  "postedAt": "2024-06-25T13:43:22.000Z",
  "capturedAt": "2026-11-04T05:46:50.953Z"
}
```

#### 💳 Pricing

You pay for each unique story item saved to the dataset. A photo is one item, and a video with its preview image is one item. Items returned from earlier runs are charged when saved to the new dataset too. Empty accounts, skipped inputs, and items that cannot be saved do not create story-item charges.

| Apify plan | Price per story item (USD) |
| --- | --- |
| Free | $0.0031 |
| Bronze | $0.0027 |
| Silver | $0.0018 |
| Gold, Platinum, Diamond | $0.0009 |

These are the configured story-item prices. Check the pricing panel for current prices and any separate Apify platform or storage costs.

#### 🔌 Integrations

Export the dataset as JSON, CSV, or Excel, or read it through the Apify API. Use Apify schedules for repeat collection and the saved media links in your own download workflow.

https://www.youtube.com/watch?v=bNACk1_S_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can I see who viewed Instagram story highlights?

This Actor does not return viewer lists or view counts. It returns public story and highlight content with the fields listed above.

##### Can I get stories that expired before my first run?

Only if they are still available in a public highlight or this Actor saved them on an earlier run. `includeExpired` does not recover content the Actor has never saved.

##### Does a highlight link collect the whole profile?

No. It selects only the items in that highlight. Use a username or profile link and select `highlights` to collect the profile's available highlights.

##### Why are some items missing?

The item cap, unavailable content, or a failed media download can reduce the count. Private, missing, and invalid inputs are skipped. The run log reports skipped inputs and collection problems. If a profile's full highlight list is unavailable, the Actor warns that some highlights may be missing.

##### Can I create or edit highlights, or open my private Instagram archive?

No. The Actor collects public content and copies it to Apify. It does not change Instagram accounts or access a user's private story archive.

##### Do the download links last forever?

Instagram media URLs can expire. The saved file links use Apify storage and remain subject to its retention and access settings. Keep your own copies when you need a separate archive.

### 📝 Changelog

**v0.0** (04-11-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~instagram-stories-highlights/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Instagram Stories Scraper](https://apify.com/maximedupre/instagram-story-viewer): Collect active stories when you do not need highlights.
- [Instagram Post & Reel Content Scraper](https://apify.com/maximedupre/instagram-post-content-scraper): Collect feed posts and Reels alongside your story research.
- [Instagram Reels Comments Scraper](https://apify.com/maximedupre/instagram-reels-comments-scraper): Read public Reel comments to study audience responses.
- [Instagram Profile Stats Scraper](https://apify.com/maximedupre/instagram-profile-stats-scraper): Add public audience and profile counts to a content review.
- [Instagram User Search Scraper](https://apify.com/maximedupre/instagram-user-search-scraper): Find public accounts by keyword before collecting their stories.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `accounts` (type: `array`):

Add one public Instagram account per line. Use a username (instagram), an @username (@instagram), or a profile link (https://www.instagram.com/instagram/). You can also add a story link (https://www.instagram.com/stories/instagram/) or a highlight link (https://www.instagram.com/stories/highlights/17912345678901234/). You can mix them freely.

## `contentTypes` (type: `array`):

Pick what to get for each username or profile link. Live stories are the stories an account has up right now, for 24 hours. Highlights are the stories the account saved on its profile, with every photo and video in each one.

## `maxItems` (type: `integer`):

The most story items to get in this run. Leave it empty or set 0 to get all of them.

## `includeExpired` (type: `boolean`):

Also get items this Actor saved on earlier runs that are no longer returned for these accounts. Usernames and profile links use the content types you pick. Account story links (/stories/username/) include past stories only, no matter which content types you pick, and exclude past highlight items. It does not add past items to a single-item story link or a highlight link, or recover items never saved by this Actor.

## Actor input object example

```json
{
  "accounts": [
    "instagram"
  ],
  "contentTypes": [
    "stories",
    "highlights"
  ],
  "maxItems": 5,
  "includeExpired": false
}
```

# Actor output Schema

## `storyItems` (type: `string`):

Stories and highlight items found in this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "accounts": [
        "instagram"
    ],
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/instagram-stories-highlights").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "accounts": ["instagram"],
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/instagram-stories-highlights").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "accounts": [
    "instagram"
  ],
  "maxItems": 5
}' |
apify call maximedupre/instagram-stories-highlights --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/instagram-stories-highlights"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/p5LzRovfJNaFTNguz/builds/dHOLvmyG5lNurqXVK/openapi.json
