Instagram Reel Scraper
Scrape reels from any public Instagram profile. Play counts, likes, comments, captions, duration, MP4 and cover links, audio. $0.35 per 1,000 reels.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
usernames,resultsLimit,onlyPostsNewerThan(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00035 per reel = $0.35 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Reel scraped | One reel returned from a profile reels tab: play count, likes, comments, caption, hashtags, mentions, duration, direct video URL, cover image, audio track, owner and collaborators. $0.35 per 1,000 reels. Sample rows and diagnostic rows are never charged. | $0.00035 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-16, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
usernames | The profiles to read the reels tab of. A handle (nasa), an @handle, a profile URL (https://www.instagram.com/nasa/) or a numeric profile id all work. Up to 100 per run. Public accounts only - a private account returns a free row saying so. | array |
resultsLimit | Maximum reel rows per profile. Pinned reels come first and use slots unless you skip them; the rest are the newest reels, newest first. | integer |
onlyPostsNewerThan | Keep reels published on or after this date. Pick a day in the calendar, or switch to a relative window such as 7 days or 2 weeks, which suits a scheduled run. Days are counted in UTC. Pinned reels have to meet the date too. Leave it empty for no date limit. | string |
skipPinnedPosts | Drop the reels the account pinned to the top of its tab. Off by default: pinned reels come first, marked with isPinned, the way the tab shows them. | boolean |
maxItems | Optional overall ceiling across every handle, useful as a spend guard when you pass a long list. Leave empty for no ceiling beyond the per-profile limit. | integer |
sessionCookies | Optional, and normally leave it empty. Runs are logged out and that is enough for a public reels tab. A handful of otherwise-public accounts are closed to logged-out visitors entirely - they come back as NOT_AVAILABLE - and an account cookie is the only thing that opens them. In Chrome: F12 > Application > Cookies > instagram.com. The sessionid cookie is the one that matters; csrftoken alongside it is better. Paste it as "sessionid=...; csrftoken=...", one entry per account. Prefer a throwaway account over your main one. Use an account you own and are authorised to automate. | array |
proxyUrls | Leave this empty for a normal run. Fill it in only if you want the traffic to leave through proxy servers you already pay for, one URL per line, in the form http://user:pass@host:port. | array |
What you get
A structured dataset — each result includes fields like:
inputUsernameshortCodeurlcaptionvideoPlayCountlikesCountcommentsCountvideoDurationtimestampvideoUrldisplayUrlaudioTitleownerUsernameisPinnedisPaidPartnershiplikesAndViewCountsDisabledisCommentsDisabledtaggedUserscoauthorProfilessponsorProfilesExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Social Media Scrapers
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
LinkedIn Post Search Scraper
Scrape public LinkedIn posts by keyword: author, text, exact date, reactions, comments and post URL. No login or cookies. $0.90 per 1,000 posts.
LinkedIn Profile Search Scraper
Find public LinkedIn profiles by keyword, title, company, school or location: name, headline, role, profile URL. No login. $0.50 per 1,000.
YouTube Shorts Scraper
Scrape YouTube Shorts by channel or keyword. Titles, ids, URLs, exact views and likes, publish dates, thumbnails. No API key. $0.40/1k.
TikTok Scraper - Profiles, Videos, Hashtags & Search
Scrape TikTok profiles, videos, hashtags and search. Play, like, comment and share counts. No login needed from you. $0.25 per 1,000.
Instagram Scraper - Profiles, Posts & Reels (No Login)
Scrape Instagram profiles, posts and reels as JSON: followers, caption, likes, comments, media URLs. No login or API key. $0.45 per 1,000 items.
Tweet Scraper
Scrape X (Twitter) tweets by handle or URL, no API key. Rows carry text, likes, retweets, views and author. Search needs your X cookie.
Where this tool sits
- Categories
- Social Media Scrapers
Instagram Reel Scraper: every reel on a public profile, no login
Name a public Instagram handle and get its reels tab back as rows. Play count, likes, comments, the caption with hashtags and mentions split out, duration, a direct video file, the cover image and the audio track behind the reel.
The thing that catches people out: a creator can pin reels to the top of their own tab, so the first rows are not the newest ones. Pinned reels are kept by default and flagged with isPinned, and every row carries its real publication time so you can sort however you like.
| Input | Instagram handles, profile URLs or numeric profile ids |
| Output | One row per reel |
| Ceiling | 1,000 reels per profile, 100 profiles per run |
| Account needed | None from you |
| Price | $0.35 per 1,000 reels, flat on every plan |
🔍 What Instagram Reel Scraper does
It reads the public reels tab of the handles you name, one row per reel, and stops when it reaches your limit or your date cut-off. Several profiles are read at once, so a list of thirty handles is not thirty times slower than one.
Nothing to log into. No API key, no cookie, no app review.
Collab reels are handled properly, which matters more than it sounds. A reel published by two accounts sits on both tabs, so ownerUsername is whoever actually posted it and inputUsername is the handle you asked for. Those two differ often. The same reel found under two of your handles is delivered once, not twice.
A handful of otherwise-public accounts are closed to visitors who are not signed in. Those come back as a labelled row rather than silently empty, and your own cookie in sessionCookies is the one thing that opens them.
📥 What you give it
{
"usernames": ["nasa", "natgeo", "https://www.instagram.com/nike/"],
"resultsLimit": 30,
"onlyPostsNewerThan": "3 months"
}
| Field | Default | What it is |
|---|---|---|
usernames | none | nasa, @nasa, a full profile URL or a numeric profile id. Mix them freely. Up to 100 per run. |
resultsLimit | none, the form starts at 30 | Rows per profile, 1 to 1,000. Pinned reels use these slots unless you skip them. |
onlyPostsNewerThan | none | A day (2026-05-01) or a window (3 months, 2 weeks, 10 days); the form gives you a calendar. Pinned reels are checked against their real publication date too. A value that is not a date stops the run with a BAD_INPUT row before anything is read. |
skipPinnedPosts | off | Drop the reels the account pinned. Leave it off to keep them, first in the list and marked with isPinned, the way the tab shows them. |
maxItems | none | An overall ceiling across every handle, up to 5,000. A useful guard when you paste a long list. |
sessionCookies | none | Optional. Your own sessionid (and csrftoken if you have it), for accounts that will not answer a signed-out visitor. |
proxyUrls | none | Optional. Servers of your own you want the run to use, as http://user:pass@host:port. |
Start a run with nothing filled in and you get one labelled sample row showing the exact output shape. That row is not charged.
📤 What you get back
A real row from a real run, cut down to the interesting fields. The long media links are trimmed with ..., and the caption ends with an emoji that has been cut out of this block:
{
"ok": true,
"recordType": "reel",
"inputUsername": "nasa",
"shortCode": "DdhFkS7KGkZ",
"url": "https://www.instagram.com/reel/DdhFkS7KGkZ/",
"caption": "Our first Leader of the Uprising ...",
"videoPlayCount": 5221170,
"likesCount": 34374,
"commentsCount": 260,
"videoDuration": 23.381000518798828,
"videoUrl": "https://scontent-dfw5-2.cdninstagram.com/o1/v/t2/f2/m86/...",
"displayUrl": "https://scontent-dfw6-1.cdninstagram.com/v/t51.82787-15/...",
"audioTitle": "Original audio",
"audioIsOriginal": true,
"audioDurationMs": 23000,
"ownerUsername": "ravens",
"ownerFullName": "Baltimore Ravens",
"ownerIsVerified": true,
"coauthorUsernames": ["astro_reid", "nasa"],
"mentions": ["paramountplus", "nfloncbs"],
"hashtags": [],
"isPinned": false,
"isPaidPartnership": false,
"likesAndViewCountsDisabled": false,
"timestamp": "2026-09-20T17:20:00.000Z",
"inputUrl": "https://www.instagram.com/nasa/reels/",
"scrapedAt": "2026-09-21T13:01:52.724Z"
}
That row is a good example of the collab case. It was found under nasa, but the Ravens posted it and NASA is one of the co-authors.
| Field | What it is |
|---|---|
shortCode, id | Both stable. Either works as a dedupe key across runs. |
videoUrl, displayUrl | Direct signed links to the video file and the cover frame. They expire within hours, so fetch them in the same job. The url field does not expire. |
videoPlayCount | Plays at the moment of reading. videoViewCount carries the same number. |
likesAndViewCountsDisabled, isCommentsDisabled | Tell you a missing count was switched off rather than being a real zero. |
coauthorProfiles, taggedUsers, sponsorProfiles | Full objects with id, name, profile link and picture. Tagged users also carry their tag position. |
audioIsOriginal | true for a sound the account made, false for a licensed track. |
isPaidPartnership | Instagram's own flag. sponsorProfiles stays empty when Instagram marks the partnership but names no sponsor. Nothing is guessed from the caption. |
🧾 Reading the output
Three kinds of row land in your dataset, and only the first kind is billed.
| Row | How to spot it | Billed |
|---|---|---|
| A reel | recordType: "reel" and a shortCode | yes |
| The sample row | _sample: true, and only on a run with no handles | no |
| A diagnostic | _diagnostic: true and an errorCode | no |
Filter on recordType == "reel" and you have your reels. Every row also carries a charged flag, which is how the actor labels its real rows against samples and diagnostics.
The errorCode on a diagnostic names the handle it belongs to and says what happened:
| Code | What it means |
|---|---|
BAD_INPUT | Not a handle. A single reel link is the usual cause. |
NOT_FOUND | Instagram says there is no such account, or the account is private. |
NOT_AVAILABLE | A real account that will not answer a signed-out visitor. Your own cookie opens it. |
NO_RESULTS | A public account with no reels in the window you asked for. |
LIMIT_REACHED | The run's maxItems was used up by other handles before this one's reels. Nothing was charged for it. |
BLOCKED | Instagram stopped answering for that handle this time. Whatever already arrived is yours. |
TIME_BUDGET | The run ran out of time before reaching that handle. |
DEAD_LIST | Six handles in a row returned nothing, so the run stopped rather than work through the rest. |
PROXY_INPUT_ADJUSTED | Something in proxyUrls could not be used as written. |
CHARGE_ERROR, UNEXPECTED_ERROR | Something went wrong that did not fit the list above. |
A bad handle never fails the run. It gets its row and the rest of your list carries on.
▶️ How to run it
1. Open Instagram Reel Scraper and click Try for free. 2. Put your handles into Instagram handles, one per line. 3. Set Reels per profile. Start at 10 while you look at the output shape. 4. Click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$0.35 per 1,000 reels. Flat on every Apify plan, no volume tiers.
One charge per reel row delivered. A reel filtered out by your date cut-off or by skipPinnedPosts never becomes a row, so it is never billed. The same reel found under two handles is billed once. Sample rows, diagnostic rows and a handle that turns out to have no reels are not billed for results.
💡 What people use it for
- Tracking a set of creators week by week, then diffing on
shortCodeto see what is new and how
the play counts moved.
- Working out what actually lands on an account before briefing a campaign: sort by
videoPlayCount and read the top ten captions.
- Building a reference library with the cover image and a playable video link already attached.
- Audio research.
audioIdandaudioIsOriginalshow which sounds an account leans on and which
of them it made itself.
🚧 What it does not do
- Reels tab only. No photo posts, carousels, stories or highlights, and a single reel link is
not valid input here.
- No private accounts, and no way around that.
- Counts are a snapshot. Two runs an hour apart will disagree, and both are right.
- Video and cover links expire within hours. Download what you want to keep.
- Deduplication is inside a run, not across runs. Two runs over the same handle return the same
reels again.
- Six empty handles in a row stop the run early, with a
DEAD_LISTrow saying so. It is there
to stop a list of dead handles quietly eating your time.
- No comment text, no liker lists, no follower counts. Those live in other actors.
- 100 handles and 1,000 reels per handle per run. Bigger jobs need splitting.
🧭 Which Instagram scraper do you need?
| If you want | Use |
|---|---|
| Reels from a profile's reels tab | This one |
| Everything a profile has posted | Instagram Profile Scraper |
| One post or reel you have the link for | Instagram Post Scraper |
| Reels found by keyword | Instagram Reels Search |
| The spoken words inside a reel | Instagram Transcript Scraper |
| Comments under a reel | Instagram Comments Scraper |
❓ Questions people ask
Do I need an account or an API key? No. Leave everything optional empty and it runs.
Then what is the cookie field for? The small number of accounts Instagram will not show to a signed-out visitor. They come back as NOT_AVAILABLE, and your own cookie is what opens them.
Why did I get a reel owned by someone else? Collab reels sit on both accounts' tabs. ownerUsername is who posted it, inputUsername is the handle you asked for.
How do I get only the newest reels? Set onlyPostsNewerThan. The run stops walking a profile once it passes your cut-off, so a daily schedule reads only what is new.
Is scraping Instagram legal? This reads public profiles only, never private accounts or messages. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
Can I run it on a schedule? Yes. Nothing carries over between runs, so the same input is safe to repeat hourly or daily.
🆘 If something breaks
Open the Issues tab on the actor page. Send the handles you used and the run ID. The errorCode on the diagnostic row usually explains it on its own.