# Instagram Highlights Scraper - Stories & Media, No Login (`benthepythondev/instagram-highlights-scraper`) Actor

Returns the story highlights of public Instagram accounts: each highlight with title, cover, creation date and every story in it (image or video file link, time, length, link stickers, mentions, location). Instagram's own story count is in each row to check completeness. No login, no cookies.

- **URL**: https://apify.com/benthepythondev/instagram-highlights-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** Social media, Marketing, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.25 / 1,000 highlights

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

## 📌 Instagram Highlights Scraper

Returns the story highlights of public Instagram accounts, without a login or cookies. Give usernames or highlight links and get one row per highlight: title, cover, creation date, and every story inside it with its picture or video file link, time, length, link stickers, mentions and location. Each row also carries Instagram's own story count, so you can see that nothing is missing.

**Price:** $5.00 per 1,000 highlights on the Apify Free plan, $4.75 on Bronze, $4.50 on Silver and $4.25 from the Gold plan up. A highlight is one charge, whether it holds 3 stories or 100. An account without highlights, a private account, a name that does not exist and a highlight that is not shown give no row and cost nothing. Export to JSON, CSV or Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🔎 What is the Instagram Highlights Scraper?

Highlights are the stories an account decided to keep on its profile. Instagram shows them to visitors who are not logged in: the profile lists the highlight circles, and each highlight opens with all its stories. This Actor makes the same requests a visitor's browser makes, one per account for the list and one per five highlights for the stories. No browser is started: a run needs 512 MB of memory.

What Instagram hands a logged-out visitor, as measured on October 6 and 7, 2026:

- **The first 10 highlights of an account,** in the order of the profile. Accounts with more than 10 exist (Glossier, Zara, H\&M in our test); the list does not continue for a visitor. Any highlight, also one beyond the first 10, can be read by its link.
- **Every story of a highlight in one answer,** with Instagram's own count next to it. In our test of six accounts, 46 of 46 highlights came with exactly the number of stories Instagram counts in them (973 stories).
- **Stickers as data.** 273 of those 973 stories carried a link sticker, 277 a mention, 6 a location. The link is given as its real target, without Instagram's redirect.
- **File links that expire.** Each link names its own end; the first one of a row ended 32 to 105 hours after the run in our test. The row gives that time as `mediaLinksExpireAt`.

#### What data does it extract?

- **Highlight:** `highlightId`, `highlightUrl`, `title`, `coverUrl`, `position` on the profile, `createdAt`, `latestStoryAt`, `isPinned`
- **Counts:** `mediaCount` (stories in the row), `reportedCount` (stories Instagram counts in the highlight), `videoCount`, `imageCount`
- **Across the highlight:** `links` (targets of all link stickers), `mentions` (all mentioned usernames), `mediaLinksExpireAt`
- **Each story:** `id`, `mediaType`, `imageUrl`, `videoUrl`, `timestamp`, `takenAt`, `durationSeconds`, `hasAudio`, `width`, `height`, `links`, `mentions`, `location`
- **Account:** `username`, `fullName`, `userId`, `isVerified`

#### What users of highlights Actors report, and what this Actor does

The issue pages and listings of the highlights Actors on Apify were read on October 7, 2026.

| Reported or stated there | Here |
|---|---|
| "Highlight returns less stories than there are" | `reportedCount` is Instagram's own number, next to `mediaCount`. A highlight that arrives short is asked again from a new visitor and the longer answer is kept; the run's summary names any row that stays short. 46 of 46 were complete in our test |
| "actor returns less Highlights" | Stated plainly: Instagram lists a logged-out visitor the first 10 highlights of an account. The status message names the accounts that have more, and `highlightUrls` reads any highlight by its link |
| "Suggestion: Add limit of highlights to scrape" | `maxHighlightsPerUser` |
| Free runs capped at 20 highlights, at most 20 usernames per run | No cap per run and none on the number of usernames |
| Charged per story item (from $3 per 1,000 stories on two Actors: a highlight of 16 stories costs $0.048 there) | Charged per highlight: $0.005, whatever the number of stories |
| Titles, covers and counts only, no stories | Every story with its file link, stickers and time |
| "Instagram blocks datacenter addresses", residential proxy required | Read without a proxy in our tests; 250 requests in a row from one datacenter address were all served. The Actor moves to other addresses by itself when one is refused |

### ⬇️ Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `usernames` | array | | Accounts whose highlights are read: `nasa`, `@nasa` or a profile link |
| `highlightUrls` | array | | Single highlights: a link (`instagram.com/stories/highlights/<id>/`), a share link (`instagram.com/s/…`) or the bare id |
| `maxHighlightsPerUser` | integer | 0 | At most this many highlights per username, in the profile's order. 0 reads all that Instagram lists (10 at most) |

Both lists can be used in one run. An account or a highlight named twice is read once, and a highlight link pasted among the usernames is read as a highlight. An empty input reads nothing and costs nothing.

#### Example input

All listed highlights of one account:

```json
{
  "usernames": ["nasa"]
}
```

The first three highlights of three accounts:

```json
{
  "usernames": ["glossier", "@sephora", "https://www.instagram.com/gymshark/"],
  "maxHighlightsPerUser": 3
}
```

Two highlights by link and by id:

```json
{
  "highlightUrls": [
    "https://www.instagram.com/stories/highlights/18123023338592759/",
    "17975319242920589"
  ]
}
```

### ⬆️ Output

One row per highlight. A real row of October 7, 2026, with two of its nine stories and with the file links shortened:

```json
{
  "username": "nasa",
  "fullName": "NASA",
  "userId": "528817151",
  "isVerified": true,
  "highlightId": "18195781759377100",
  "highlightUrl": "https://www.instagram.com/stories/highlights/18195781759377100/",
  "title": "Roman",
  "coverUrl": "https://scontent-fra5-1.cdninstagram.com/…/785745361_1537…?…&oe=6ACBD87B",
  "position": 1,
  "isPinned": false,
  "createdAt": "2026-08-30T14:33:04+00:00",
  "latestStoryAt": "2026-08-30T13:08:03+00:00",
  "mediaCount": 9,
  "reportedCount": 9,
  "videoCount": 9,
  "imageCount": 0,
  "links": ["https://go.nasa.gov/adoptapixel"],
  "mentions": ["nasakennedy"],
  "mediaLinksExpireAt": "2026-10-08T17:17:11+00:00",
  "stories": [
    {
      "id": "3975089864169193671",
      "mediaType": "video",
      "imageUrl": "https://scontent-fra3-1.cdninstagram.com/…/790023468_2121…?…&oe=6ACBCD01",
      "videoUrl": "https://scontent-fra3-1.cdninstagram.com/…/AQOO5y0fuDTYz6…?…&oe=6AC7F58E",
      "timestamp": 1788087653,
      "links": [],
      "mentions": ["nasakennedy"],
      "takenAt": "2026-08-30T11:00:53+00:00",
      "durationSeconds": 26.816,
      "hasAudio": true,
      "width": 1080,
      "height": 1920,
      "location": null
    },
    {
      "id": "3975097618556613637",
      "mediaType": "video",
      "imageUrl": "https://scontent-fra5-1.cdninstagram.com/…/791296357_8758…?…&oe=6ACBDB80",
      "videoUrl": "https://scontent-fra3-2.cdninstagram.com/…/AQON7m5G2J1XNz…?…&oe=6AC7FFF8",
      "timestamp": 1788088572,
      "links": [],
      "mentions": [],
      "takenAt": "2026-08-30T11:16:12+00:00",
      "durationSeconds": 58.966,
      "hasAudio": true,
      "width": 1080,
      "height": 1920,
      "location": null
    }
  ],
  "scrapedAt": "2026-10-07T08:45:40.189351+00:00"
}
```

Stories are listed oldest first, as Instagram plays them. `position` is the highlight's place on the profile and is empty for a highlight given by link. For a video, `imageUrl` is its still. The run's key-value store holds a `SUMMARY` record: highlights and stories saved, accounts without highlights, names not found, private accounts, highlights not shown, and the accounts that have more highlights than Instagram lists.

### 💰 What a run costs

| Plan | Per highlight | 1,000 highlights |
|---|---|---|
| Free | $0.005 | $5.00 |
| Bronze | $0.00475 | $4.75 |
| Silver | $0.0045 | $4.50 |
| Gold, Platinum, Diamond | $0.00425 | $4.25 |

Plus $0.00005 per run start. The 5 highlights of the first example cost $0.025 on the Free plan. Not charged: an account without highlights, a private account, a name or highlight that does not exist, an entry that is no username or highlight link. A run stops by itself at the maximum charge you set and says so in its status message; every row saved until then is complete.

### ⏱️ Measured (October 6 and 7, 2026)

These times are from a test server outside Apify, without a proxy. Times on Apify can differ; the counts do not depend on the server.

| Run | Result | Time |
|---|---|---|
| `nasa`, all highlights | 5 highlights, 89 stories | 4.5 s |
| Six accounts, all listed highlights | 46 highlights, 973 stories, 46 of 46 complete | 26 s, 112 MB of memory at the peak |
| 46 highlights by link | 46 highlights, 973 stories | 28 s |
| The same run killed after 7 s and started again | 46 rows, none twice | |
| 250 story requests in a row from one datacenter address | 250 served, each highlight complete | 294 s |

A highlight of 22 stories is 33 KB on the wire and a row of it about 30 KB in the dataset.

### 🤖 For AI agents

One input to copy. No credential is needed, both target fields are arrays, and the result is the run's default dataset.

```json
{
  "usernames": ["nasa"],
  "maxHighlightsPerUser": 2
}
```

Each row is one highlight; the stories are in `stories`. `links` and `mentions` hold every link sticker target and mentioned username of the highlight, so most questions need no walk through the stories. Cost: $0.005 per row on the Free plan, nothing for accounts without highlights. File links in `imageUrl` and `videoUrl` stop working at `mediaLinksExpireAt`; download before that.

### 💡 Use cases

- 🛍️ **Competitor and brand research:** see which launches, collections and campaigns a brand keeps on its profile, and which shop links its stories point to
- 🤝 **Influencer vetting:** list the brands a creator mentions in highlights, with the stories as evidence
- 🗄️ **Archiving:** save the pictures and videos of your own or a client's highlights before they are edited or removed
- 🔗 **Link and campaign tracking:** collect link sticker targets with their tracking parameters on a schedule and compare runs by `highlightId`, `mediaCount` and `latestStoryAt`

### ⚠️ Limits, stated plainly

- **The first 10 highlights per account.** Instagram's highlight list does not continue for a logged-out visitor. A highlight beyond those is read when you give its link or id in `highlightUrls`; the link is what the browser shows when the highlight is open.
- **Public accounts only.** A private account gives no row. The Actor does not log in, and it does not read an account's current 24-hour stories: Instagram shows those to logged-in users only.
- **File links expire.** In our test between 32 and 105 hours after the run. The Actor returns links and does not store the files.
- **No view counts, likes or replies.** Instagram does not show them to visitors. Hashtag, music and poll stickers are not in the rows; link stickers, mentions and locations are.
- **`isPinned` was false on all 46 highlights of our test.** It is passed on as Instagram sends it.
- **A reserve route with fewer fields.** If Instagram closes the request that returns the stories, the Actor reads through the request of the highlight page instead. Rows then come without `mentions`, `createdAt`, `isPinned` and `reportedCount`, and the log says so. This did not happen in any test run.
- **Highlights change.** A highlight that held 87 stories on October 6 held 7 a day later; the account had edited it. A row shows the highlight at `scrapedAt`.

### ❓ FAQ

**Do I need an Instagram account, cookies or a proxy?** No. The Actor reads what Instagram shows a visitor who is not logged in, and brings its own addresses for the case that one is refused.

**How do I get the highlights after the tenth?** Open the highlight on Instagram and copy the link from the address bar, or use the share link from the app. Put the links into `highlightUrls`.

**How do I know a highlight is complete?** `mediaCount` equals `reportedCount`. The `SUMMARY` record lists every highlight where it does not.

**What happens with a username that does not exist?** A second visitor is asked before the name is called missing. Then it is named in the status message and the summary, without a row and without a charge. The same goes for accounts without highlights.

**Can I download the pictures and videos?** Yes, from `imageUrl` and `videoUrl`, until `mediaLinksExpireAt`. `videoUrl` is the MP4 with sound.

**Can I run it on a schedule to see what changed?** Yes. `highlightId` is stable, so compare `mediaCount`, `latestStoryAt` and the story `id` values between runs. Every run reads and charges the highlights again; the Actor keeps no memory between runs.

**What happens when a run is aborted, hits its timeout or is moved to another server?** It continues without saving a highlight twice: a started run reads its own dataset first. Shortly before the timeout it stops by itself and says how far it got.

**I come from another highlights Actor. What is different?** The input names `usernames` and `maxHighlightsPerUser` are the same, and `highlightIds`, `links`, `username` and `maxResults` are read too. The row fields `username`, `highlightId`, `title`, `coverUrl`, `mediaCount`, `stories` and the story fields `id`, `mediaType`, `imageUrl`, `videoUrl`, `timestamp`, `links`, `mentions` keep their names. Differences: `links` and `mentions` are always present (empty lists instead of missing fields), `imageUrl` is the largest picture, and the rows add `reportedCount`, `createdAt`, `position`, the lists across the highlight and the fields after `mentions` in each story.

**Is it legal?** The Actor reads highlights that public accounts published for everyone, the way a visitor without an account sees them, and nothing behind a login. Stories can show people and name them. If you store or process such data you need a lawful basis under the GDPR, the CCPA or the rules that apply to you; do not use it to profile private persons, and honour Instagram's terms and removal requests. Ask a lawyer when in doubt.

**Something is missing or wrong.** Open an issue on the Issues tab with the run id; we answer within a business day.

### 🔗 You might also like

- [Instagram Profile Scraper](https://apify.com/benthepythondev/instagram-profile-scraper): followers, biography and links of public accounts
- [Instagram Posts Scraper](https://apify.com/benthepythondev/instagram-posts-scraper): an account's posts with likes, comments and dates
- [Instagram Reels Scraper](https://apify.com/benthepythondev/instagram-reels-scraper): an account's reels with plays
- [Instagram Video Downloader](https://apify.com/benthepythondev/instagram-video-downloader): the MP4 behind a reel or post link, optionally stored
- [Instagram Reel Transcript Scraper](https://apify.com/benthepythondev/instagram-reel-transcript-scraper): what is said in a reel, as text
- [Instagram Comments Scraper](https://apify.com/benthepythondev/instagram-comments-scraper): the comments under a post

**Keywords:** instagram highlights scraper, instagram story highlights, instagram highlights downloader, instagram highlight stories api, download instagram highlights, instagram stories scraper no login, instagram highlight link stickers, instagram story mentions, instagram highlights export csv, instagram highlight cover, instagram story archive, instagram competitor monitoring, instagram influencer vetting, instagram highlights json, instagram scraper no cookies, instagram highlights by username, instagram highlight viewer api

# Actor input Schema

## `usernames` (type: `array`):

Instagram accounts whose story highlights are read: plain names (nasa), @names or profile links. Each highlight Instagram lists for a logged-out visitor becomes one row with all its stories. Instagram lists a visitor the first 10 highlights of an account; for the others, give their links in the field below. Private accounts and accounts without highlights give no row and cost nothing.

## `highlightUrls` (type: `array`):

Single highlights to read, without listing a profile first: links (instagram.com/stories/highlights/18123023338592759/), share links (instagram.com/s/...) or bare highlight ids. Use it for highlights beyond an account's first 10, or to read one highlight again. A highlight that does not exist or is not shown to visitors gives no row and costs nothing.

## `maxHighlightsPerUser` (type: `integer`):

Reads at most this many highlights per username, in the order Instagram shows them on the profile. 0 reads every highlight Instagram lists for a visitor (10 at most). Each highlight is one row and one charge, whatever the number of stories in it.

## Actor input object example

```json
{
  "usernames": [
    "nasa"
  ],
  "maxHighlightsPerUser": 0
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "usernames": [
        "nasa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/instagram-highlights-scraper").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 = { "usernames": ["nasa"] }

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/instagram-highlights-scraper").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 '{
  "usernames": [
    "nasa"
  ]
}' |
apify call benthepythondev/instagram-highlights-scraper --silent --output-dataset

```

## MCP server setup

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

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/sVgWYugZkoUsRuSag/builds/xUHWdZxNRyl1ASQWW/openapi.json
