Instagram Highlights Scraper & Highlight Details Insights
Pricing
Pay per usage
Instagram Highlights Scraper & Highlight Details Insights
Scrape Instagram Story Highlights with the Instagram Highlights Scraper. Extract highlight titles, cover images, stories, video URLs, captions, and timestamps. Perfect for content analysis, trend tracking, and competitor research. Fast, accurate, and scalable for any profile.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
21
Total users
5
Monthly active users
5 days ago
Last modified
Categories
Share
Instagram Highlights Scraper — Covers, Summary & Leaderboard
Instagram Highlights Scraper & Highlight Details Insights pulls a public profile's entire Story Highlights tray — title, ID, and cover image per highlight — through Instagram's logged-out GraphQL endpoint, paginating past the first page most tools stop at. Beyond raw per-highlight rows, it computes two uncharged insight rows per profile: a summary (count, titles, success rate) and a cross-profile leaderboard ranked by highlight count. Every response is structured JSON, ready to pass to an LLM, load into a vector store, or feed a monitoring pipeline. No Instagram login is required.
What is Instagram Highlights Scraper & Highlight Details Insights?
Instagram Highlights Scraper & Highlight Details Insights queries a public Instagram profile's Story Highlights tray and returns one JSON row per highlight — title, numeric ID, and cover image — plus two derived, uncharged rows per profile: a per-profile summary and a cross-profile leaderboard ranked by highlight count. It follows Instagram's own cursor pagination (has_next_page / end_cursor) across every page of the tray, so a profile with a large highlight collection isn't silently truncated to whatever fits on page one. No Instagram account or login is required — every request goes through Instagram's public, logged-out GraphQL and embed endpoints.
- Full highlights-tray extraction with true cursor pagination, not just the first page
- Genuinely full-resolution cover images — resolved via Instagram's
reels_mediaendpoint and matched to the tray thumbnail by CDN asset ID, not the 150x150 cropped thumbnail the tray query itself returns - Uncharged per-profile summary row: highlight count, combined titles, first/last highlight ID, success rate
- Uncharged cross-profile leaderboard ranking every profile in the run by highlight count
- Accepts profile URLs, usernames, direct highlight links, or post/reel/IGTV shortcodes — all resolved to the owning profile automatically
- Automatic proxy escalation (no proxy → datacenter → sticky residential, up to 3 retries) when Instagram blocks a request
What data can you get with Instagram Highlights Scraper & Highlight Details Insights?
Every run can produce three row types, distinguished by the type, isSummary, and isLeaderboard fields, sharing one 21-field schema.
| Result Type | Extracted Fields | Primary Use Case |
|---|---|---|
| Highlight | input_url, username, user_id, type, id, title, cover_media, cover_media_full_res, cover_media_expires_at, cover_media_archive_url, success, error, timestamp | Building a per-highlight content archive or catalog |
| Profile summary (uncharged) | isSummary, profile_highlight_count, profile_titles, profile_first_highlight_id, profile_last_highlight_id, profile_success_rate | One rollup row per profile for reporting without re-aggregating raw rows yourself |
| Leaderboard entry (uncharged) | isLeaderboard, leaderboard_rank, profile_highlight_count, profile_success_rate | Ranking many profiles by highlight-tray size in a single run |
Uncharged profile summary and leaderboard insights
This is the layer that separates this Actor from a plain per-highlight scrape. After a profile's highlight rows are pushed, the Actor emits one extra instagram_highlights_profile_summary row (isSummary: true) carrying profile_highlight_count, the profile's combined profile_titles (joined with " | "), its profile_first_highlight_id / profile_last_highlight_id, and a computed profile_success_rate — the share of that profile's rows that scraped successfully, rounded to four decimal places. Once every profile in the run has been processed, it emits one instagram_highlights_leaderboard_entry row per profile (isLeaderboard: true), ranked by leaderboard_rank from the highest highlight count down to the lowest. Both row types are controlled by the enableProfileSummary and enableLeaderboard input toggles (default true for both), and both are pushed without a charged_event_name, so neither ever counts as a billable event — they're free analytics riding alongside the raw scrape.
{"type": "instagram_highlights_leaderboard_entry","username": "natgeo","isSummary": false,"isLeaderboard": true,"leaderboard_rank": 1,"profile_highlight_count": 14,"profile_success_rate": 1.0}
Full-resolution, permanently archived cover images
The highlights tray query itself only ever exposes a 150x150 cropped_image_version thumbnail. This Actor separately calls Instagram's reels_media endpoint for the same highlight ID and matches the returned image back to the tray thumbnail by its CDN asset ID, so cover_media_full_res is verified to be the same photo at full resolution — never a mismatched item from the reel. When archiveCoverImages is on, that image is downloaded and saved permanently to the run's Key-Value Store as cover_media_archive_url, so the cover survives after Instagram's CDN link (cover_media_expires_at) expires.
Why not build this yourself?
Instagram's Graph API has no public endpoint for pulling an arbitrary public profile's story-highlights tray — its Stories/highlights permissions only cover accounts you manage that have completed Meta's app review, not third-party profiles. Reproducing this yourself means reverse-engineering the internal PolarisProfileStoryHighlightsTrayContentQuery relay call, handling its cursor pagination and anti-hijacking for (;;); JSON prefix, extracting CSRF tokens from live cookies, and building a proxy fallback ladder for when Instagram blocks a request. This Actor already does all of that, plus the full-resolution cover resolution and derived-insights layer, normalized into one stable JSON schema. Build your own only if you need to change the underlying scraping logic itself.
How to scrape Instagram highlights with Instagram Highlights Scraper & Highlight Details Insights?
No input field is required by the schema, but a run needs at least one entry in profileTargets to return any rows.
- Open the Actor on its Apify Store listing under Scrapier and go to the Input tab.
- Add one or more profile URLs, usernames, direct highlight links, or shortcodes to
profileTargets(e.g.https://www.instagram.com/mrbeast/). - Set the real controls that matter:
maxHighlightsPerProfileto cap output,archiveCoverImagesto permanently save full-res covers, andenableProfileSummary/enableLeaderboardto toggle the derived insight rows. - Start the run.
- Read results from the Dataset tab, or export as JSON or CSV.
{"profileTargets": ["https://www.instagram.com/mrbeast/", "natgeo"],"maxHighlightsPerProfile": 0,"archiveCoverImages": true,"enableProfileSummary": true,"enableLeaderboard": true}
How to run multiple profiles in one job
profileTargets accepts an array — each entry is a separate profile, shortcode, or highlight link processed within the same run. Profiles are scraped one at a time in sequence (there is no documented concurrency setting for parallel profile fetches), and proxy-escalation state is shared across the whole batch: once one profile trips a block and falls back to sticky residential, every subsequent profile in that run uses residential directly instead of re-testing no-proxy first. This lets a batch of profiles run as one job instead of one run per profile.
⬇️ Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
profileTargets | No | array | Profile URLs, usernames, direct highlight links, or shortcodes — one entry per line. Shortcodes and highlight links are resolved to the owning profile via a public embed-page lookup. Legacy key startUrls is still accepted as a fallback. | ["https://www.instagram.com/mrbeast/"] |
maxHighlightsPerProfile | No | integer | Cap on highlights kept per profile after the full tray has been paginated (all pages fetched regardless, then trimmed). 0 = unlimited. Default 0. | 0 |
archiveCoverImages | No | boolean | Resolve each highlight's genuinely full-resolution cover (matched to the tray thumbnail by CDN asset ID) and save a permanent copy to this run's Key-Value Store. Default true. | true |
enableProfileSummary | No | boolean | Push one extra, uncharged summary row per profile — highlight count, combined titles, first/last highlight ID, success rate. Default true. | true |
enableLeaderboard | No | boolean | Push one extra, uncharged leaderboard row per profile at the end of the run, ranked by highlight count. Default true. | true |
proxyConfiguration | No | object | Proxy strategy. Starts with your selection; on HTTP 429/403 escalates to datacenter, then sticky residential (up to 3 retries with a new proxy URL each time). | {"useApifyProxy": true} |
Example JSON input
{"profileTargets": ["https://www.instagram.com/mrbeast/","natgeo","https://www.instagram.com/stories/highlights/17895948565602293/"],"maxHighlightsPerProfile": 0,"archiveCoverImages": true,"enableProfileSummary": true,"enableLeaderboard": true,"proxyConfiguration": { "useApifyProxy": true }}
Common pitfall: maxHighlightsPerProfile only trims the OUTPUT after every page of the highlights tray has already been fetched — setting it to a small number does not reduce how many GraphQL pages the Actor requests, so it will not meaningfully speed up a run against a profile with a large highlights tray.
⬆️ Output
Results are typed, normalized JSON with a consistent 21-field schema across all three row types, exportable as JSON or CSV from the Dataset tab. Rows are pushed in real time as each highlight is processed. Every instagram_highlights row — including a failure row like "no highlights found for this profile" — is billed as a row_result event; only the isSummary/isLeaderboard insight rows are free. Filter a run's charged content with success == true, or exclude the free rows entirely with isSummary == false AND isLeaderboard == false.
Scraped results
[{"input_url": "https://www.instagram.com/natgeo/","username": "natgeo","user_id": "787132","type": "instagram_highlights","id": "17895948565602293","title": "Oceans","cover_media": "https://scontent.cdninstagram.com/v/t51.2885-15/thumb_150x150.jpg","cover_media_full_res": "https://scontent.cdninstagram.com/v/t51.2885-15/full_1080x1080.jpg","cover_media_expires_at": "2026-08-02T14:20:00+00:00","cover_media_archive_url": "https://api.apify.com/v2/key-value-stores/abc123/records/cover-17895948565602293.jpg","success": true,"error": null,"isSummary": false,"profile_highlight_count": null,"profile_titles": null,"profile_first_highlight_id": null,"profile_last_highlight_id": null,"profile_success_rate": null,"isLeaderboard": false,"leaderboard_rank": null,"timestamp": "2026-07-26T09:12:01+00:00"},{"input_url": "https://www.instagram.com/natgeo/","username": "natgeo","user_id": "787132","type": "instagram_highlights","id": "18268617304253172","title": "Wildlife","cover_media": "https://scontent.cdninstagram.com/v/t51.2885-15/thumb2_150x150.jpg","cover_media_full_res": "https://scontent.cdninstagram.com/v/t51.2885-15/full2_1080x1080.jpg","cover_media_expires_at": "2026-08-02T14:20:11+00:00","cover_media_archive_url": "https://api.apify.com/v2/key-value-stores/abc123/records/cover-18268617304253172.jpg","success": true,"error": null,"isSummary": false,"profile_highlight_count": null,"profile_titles": null,"profile_first_highlight_id": null,"profile_last_highlight_id": null,"profile_success_rate": null,"isLeaderboard": false,"leaderboard_rank": null,"timestamp": "2026-07-26T09:12:03+00:00"},{"input_url": "https://www.instagram.com/natgeo/","username": "natgeo","user_id": "787132","type": "instagram_highlights","id": "17937048210026598","title": "Expeditions","cover_media": "https://scontent.cdninstagram.com/v/t51.2885-15/thumb3_150x150.jpg","cover_media_full_res": "https://scontent.cdninstagram.com/v/t51.2885-15/full3_1080x1080.jpg","cover_media_expires_at": "2026-08-02T14:20:19+00:00","cover_media_archive_url": "https://api.apify.com/v2/key-value-stores/abc123/records/cover-17937048210026598.jpg","success": true,"error": null,"isSummary": false,"profile_highlight_count": null,"profile_titles": null,"profile_first_highlight_id": null,"profile_last_highlight_id": null,"profile_success_rate": null,"isLeaderboard": false,"leaderboard_rank": null,"timestamp": "2026-07-26T09:12:07+00:00"},{"input_url": "https://www.instagram.com/natgeo/","username": "natgeo","user_id": "787132","type": "instagram_highlights_profile_summary","id": null,"title": null,"cover_media": null,"cover_media_full_res": null,"cover_media_expires_at": null,"cover_media_archive_url": null,"success": true,"error": null,"isSummary": true,"profile_highlight_count": 3,"profile_titles": "Oceans | Wildlife | Expeditions","profile_first_highlight_id": "17895948565602293","profile_last_highlight_id": "17937048210026598","profile_success_rate": 1.0,"isLeaderboard": false,"leaderboard_rank": null,"timestamp": "2026-07-26T09:12:08+00:00"},{"input_url": "https://www.instagram.com/natgeo/","username": "natgeo","user_id": "787132","type": "instagram_highlights_leaderboard_entry","id": null,"title": null,"cover_media": null,"cover_media_full_res": null,"cover_media_expires_at": null,"cover_media_archive_url": null,"success": true,"error": null,"isSummary": false,"profile_highlight_count": 3,"profile_titles": null,"profile_first_highlight_id": null,"profile_last_highlight_id": null,"profile_success_rate": 1.0,"isLeaderboard": true,"leaderboard_rank": 1,"timestamp": "2026-07-26T09:12:20+00:00"}]
How can I use the data extracted with Instagram Highlights Scraper & Highlight Details Insights?
- Social-media and content teams: pull a competitor's or client's full highlight lineup —
titleandcover_media_full_resfor every highlight — to spot content gaps or repurpose formats, without opening each highlight in the app. - Brand and competitive monitoring analysts: compare
profile_highlight_count,profile_success_rate, andleaderboard_rankacross a watchlist of profiles in one run instead of manually opening and counting each profile's tray. - AI engineers and LLM developers: an agent issues a
profileTargetsquery, receives this Actor's structured JSON back, and grounds an answer about a brand's or creator's highlight content in live data instead of stale training data. - Archivists and researchers: use
cover_media_archive_url— a permanent Key-Value Store copy — to build a durable image archive that survives Instagram's CDN link expiring atcover_media_expires_at.
How do you monitor Instagram highlight activity over time?
Highlight monitoring here means re-running the same profileTargets list on a schedule and diffing the new rows against the previous run, since a profile's highlights tray changes as highlights are added, renamed, or removed. Because every profile gets a summary row keyed by username, repeated runs let you diff profile_highlight_count for a rising or falling highlight count, compare profile_titles against the prior run to spot a newly added or renamed highlight, and watch profile_first_highlight_id / profile_last_highlight_id shift as older highlights roll off or new ones are pinned. The leaderboard adds a second lens: diff leaderboard_rank across runs to see which profile in your watchlist is growing its highlight collection fastest relative to the others, and watch profile_success_rate for a profile that starts failing more often (a sign it went private, was suspended, or the run hit a persistent block).
A basic workflow: schedule this Actor against a fixed profileTargets list, store each run's summary and leaderboard rows keyed by username and timestamp in your own database, then diff the newest run's profile_highlight_count and profile_titles against the previous run's for the same username and alert when a new highlight title appears or the leaderboard rank changes. There is no actor-specific webhook built into this Actor, so pair a scheduled run with Apify's platform-level Schedule feature and the Apify API's dataset endpoints or run-finished webhooks to move each run's rows into your own pipeline for the diffing step.
Integrate Instagram Highlights Scraper & Highlight Details Insights and automate your workflow
Instagram Highlights Scraper & Highlight Details Insights works with any language or tool that can send an HTTP request.
REST API with Python
import requestsTOKEN = "<YOUR_APIFY_TOKEN>"url = "https://api.apify.com/v2/acts/scrapier~instagram-highlights-scraper-highlight-details-insights/run-sync-get-dataset-items"payload = {"profileTargets": ["https://www.instagram.com/natgeo/"],"enableProfileSummary": True,"enableLeaderboard": True,}resp = requests.post(url, params={"token": TOKEN}, json=payload, timeout=180)rows = resp.json() # highlight rows plus summary/leaderboard rows, as shown abovefor row in rows:print(row["type"], row.get("username"), row.get("title"))
MCP for query-grounded AI agents
The Actor is reachable through Apify's Actors MCP Server: run npx @apify/actors-mcp-server --tools scrapier/instagram-highlights-scraper-highlight-details-insights locally with an APIFY_TOKEN set, or connect the hosted server at https://mcp.apify.com. Register it with an MCP-compatible client — Claude Desktop, Claude Code, or Cursor — and an agent can call it as a tool: a user asks about a profile's highlight content, the agent runs the scrape, and grounds its answer in the returned highlight and summary fields.
Scheduled monitoring and delivery
There is no actor-specific webhook built into this Actor. Attach it to Apify's platform-level Schedule to trigger runs on an interval, and use the Apify API's run-finished webhooks or dataset export endpoints to deliver each run's rows into your own storage or pipeline.
Is it legal to scrape Instagram highlights?
Yes. This Actor returns only public profile data — highlight titles, IDs, and cover images — that any logged-out visitor to a public Instagram profile already sees; it does not access private accounts or bypass any login wall. username and user_id are profile-identifying data, so treat exports containing them under GDPR/CCPA if your use case involves EU or California residents — minimize what you store, and honor deletion requests tied to a username. Instagram's Terms of Service govern automated access to its platform, so review them for your specific use case. Scraping for periodic monitoring carries a different risk profile than scraping to train a model. Consult your legal team for commercial use cases involving bulk data storage.
Frequently asked questions
Does this Actor require an Instagram account or login?
No. Every request goes through Instagram's public, logged-out GraphQL query and embed-page endpoints — there is no sessionid cookie or credential field in the input schema.
Does this Actor extract real computed insights, or just raw highlight data?
Real computed insights. Alongside the raw per-highlight rows, it pushes an instagram_highlights_profile_summary row (isSummary: true) with profile_highlight_count, profile_titles, profile_first_highlight_id/profile_last_highlight_id, and profile_success_rate, then an instagram_highlights_leaderboard_entry row (isLeaderboard: true) with leaderboard_rank for every profile in the run. Both are controlled by enableProfileSummary/enableLeaderboard (default true) and are never charged.
Are the summary and leaderboard rows charged?
No. They're pushed without a charged_event_name, so only real highlight rows (type: instagram_highlights) count as billable row_result events — including failure rows for a profile that returned no highlights, which are still billed since they're pushed the same way as a successful highlight row.
How many highlights does this Actor return per profile?
All of them by default (maxHighlightsPerProfile: 0), fetched by following the tray's cursor pagination across pages, up to an internal 50-page-per-profile safety cap that guards against a runaway loop if Instagram's pagination ever reported has_next_page: true indefinitely. Set maxHighlightsPerProfile to a positive number to trim output after that pagination completes.
How does this Actor handle Instagram's anti-bot measures?
It escalates through a no-proxy → datacenter → sticky-residential proxy ladder whenever a request comes back HTTP 429 or 403, retrying residential up to 3 times with a fresh proxy URL each attempt, and stays in residential mode for the rest of the run once it's been used.
Can I pass a shortcode or a direct highlight link instead of a profile URL?
Yes. A /p/, /reel/, or /tv/ shortcode, or a bare shortcode-shaped token, is resolved to its owning profile via Instagram's public embed page; a direct .../stories/highlights/<id>/ link is resolved the same way and narrows the run to that single highlight instead of the full tray.
How do I monitor a profile's highlights over time?
Schedule this Actor against the same profileTargets list, store each run's summary rows keyed by username and timestamp, and diff profile_highlight_count and profile_titles between runs to catch a newly added, renamed, or removed highlight.
Does this Actor work with Claude, ChatGPT, and AI agent frameworks?
Yes — it's callable as a plain HTTP endpoint by any agent framework that can send a request, and it's also reachable through Apify's Actors MCP Server (npx @apify/actors-mcp-server --tools scrapier/instagram-highlights-scraper-highlight-details-insights, or the hosted https://mcp.apify.com) for MCP-native clients like Claude Desktop and Claude Code.
How does this Actor compare to other Instagram highlights scrapers?
Most highlights scrapers return only the first page of a profile's tray and the raw 150x150 tray thumbnail as the cover. This Actor paginates the entire tray via its cursor (has_next_page/end_cursor), resolves a genuinely full-resolution cover matched by CDN asset ID, archives that cover permanently to a Key-Value Store, and adds the uncharged profile-summary and leaderboard rows on top — layers a plain per-highlight export doesn't provide.
Can I use this Actor without managing proxies or an Instagram account?
Yes. No Instagram account or login is required, and proxy escalation across the no-proxy/datacenter/residential ladder happens automatically on a block — you only need to supply profileTargets.
Your feedback
Found a bug or a field that doesn't match what's documented here? Let us know through the Actor's Issues tab on Apify or Scrapier's support contact — reports like this go straight into fixing the extractor.