Skip to content

Instagram Reel Scraper

Try for free

Scrape public Instagram reels from a profile or reel URL. Get captions, play and like counts, comment counts, video URLs, durations, and timestamps for every reel.

🎬 Instagram Reel Scraper

Public Instagram reels, as clean dataset rows, from a username or a reel URL.

Built for influencer research, campaign checks, and competitive monitoring. Paste a profile, a numeric id, or a reel link, and each public reel comes back with the caption, timing, engagement, and media fields Instagram actually sent.

✨ Features

  • 🎥 Profiles and direct reels. username accepts usernames, @handles, profile URLs, numeric profile ids, reel URLs, and share URLs. Each entry is scraped on its own.
  • 📏 A cap per profile. resultsLimit stops a profile feed (default 20). A direct reel URL ignores that cap and returns that reel.
  • 📅 Newer-than filter. onlyPostsNewerThan keeps reels from a UTC date, an ISO timestamp, or a relative window such as 2 weeks. Pinned reels stay in the results unless you skip them.
  • 📌 Skip pinned reels. skipPinnedPosts drops reels Instagram marks as pinned, including older pins that would otherwise sit at the top of the feed.
  • 🧪 Skip marked trial reels. skipTrialReels drops a reel only when the payload itself marks it as a trial. Unmarked reels stay.
  • 💬 Preview comments on the reel. Up to 10 comments already attached to the reel: text, owner, timestamp, and like count. This is not a full comment crawl.
  • 🤝 People and music. Hashtags, mentions, tagged users, sponsors, co-authors, location, and music info when the reel includes them.
  • 🔢 Engagement that was on the reel. Likes, comments, views, plays, and reshares. likesCount is -1 when Instagram has disabled like and view counts. A real 0 stays 0.
  • 🔁 Shares when you ask. includeSharesCount adds sharesCount from the share or reshare count on the payload. reshareCount is written whenever Instagram sent it.
  • 💾 A saved MP4 when you ask. includeDownloadedVideo stores the video in the run key-value store after the file contains an ftyp box, then sets downloadedVideo to that record. A failed download keeps the reel and omits the field.
  • 🚫 Private profiles stop cleanly. A private profile becomes one error row and the run continues with the other inputs.

🚀 Why teams use this

Request-based scraping keeps the run on HTTP. There is no browser to start, so a profile list spends its time on Instagram’s public reel data instead of on a second session.

A private profile, a post that is not a reel, or a request that fails is a single dataset row with error and errorDescription. The rest of the list still finishes. A username or id Instagram does not publish is different: the run fails, and that name is not stored as a row. No profile is filled in for it.

Schedule it. Point it at the accounts you watch, set a newer-than window, and export JSON or CSV from the dataset. Missing values are left off the item, so a column appears because Instagram sent it, not because the actor filled one in.

Runs on Scrapely use the residential proxy group. Logged-out only: no session cookie and no account.

💡 Use cases

  • Collect a creator's reels with view, like, and comment counts.
  • Find the best-performing short videos in a niche.
  • Download reel metadata for video research or content planning.

🧪 Example input

{
  "resultsLimit": 20,
  "username": [
    "natgeo"
  ]
}

🧾 Sample output

One item from a real run of the example input, shortened. Long text is cut and lists show their first entries.

{
  "id": "4005771580272580688",
  "type": "Video",
  "shortCode": "DeXXAddgJhQ",
  "caption": "It’s snack time for these humpback whales. They use rings of bubbles like nets to concentrate fish and krill before surging through for a feast.\n\n#EuropeFrom…",
  "hashtags": [
    "EuropeFromAbove"
  ],
  "mentions": [
    "DisneyPlus"
  ],
  "url": "https://www.instagram.com/p/DeXXAddgJhQ/",
  "commentsCount": 170,
  "firstComment": "😍",
  "latestComments": [
    {
      "id": "17918751165452783",
      "text": "😍",
      "ownerUsername": "viajar_bien_2027",
      "ownerProfilePicUrl": "https://scontent-jnb2-1.cdninstagram.com/…",
      "timestamp": "2026-10-12T21:48:31.000Z",
      "likesCount": 0,
      "owner": {
        "id": "…",
        "username": "…",
        "is_verified": "…"
      }
    },
    {
      "id": "18199907509378238",
      "text": "Amazingly beautiful ❤️. Thanks for sharing this beautiful video clip 🙏. Rare moments of the Sea Giants 🐋🐋🐋🌊🌊.... Impressive 🤩",
      "ownerUsername": "dilmijayasuriya",
      "ownerProfilePicUrl": "https://scontent-jnb2-1.cdninstagram.com/…",
      "timestamp": "2026-10-12T21:18:27.000Z",
      "likesCount": 1,
      "owner": {
        "id": "…",
        "username": "…",
        "is_verified": "…"
      }
    }
  ],
  "dimensionsHeight": 1920,
  "dimensionsWidth": 1080,
  "originalHeight": 1920,
  "originalWidth": 1080,
  "displayUrl": "https://scontent-jnb2-1.cdninstagram.com/…",
  "videoUrl": "https://instagram.fmvd3-1.fna.fbcdn.net/…",
  "alt": "Video by National Geographic on October 11, 2026. May be an image of grey whale, humpback whale, whale and text.",
  "likesCount": 76931,
  "videoPlayCount": 1501380,
  "igPlayCount": 1501380,
  "timestamp": "2026-10-11T19:01:22.000Z",
  "ownerFullName": "National Geographic",
  "ownerUsername": "natgeo",
  "ownerId": "787132",
  "productType": "clips"
}

📥 Input

FieldRequiredWhat it does
usernameYesUsernames, profile URLs, numeric ids, reel URLs, or share URLs. Each item is processed on its own.
resultsLimitNoMaximum reels per profile. Default 20. Ignored for a direct reel URL.
onlyPostsNewerThanNoUTC YYYY-MM-DD, an ISO timestamp, or a relative window (1 day, 2 weeks, 3 months).
skipPinnedPostsNoDrop pinned reels. Default false.
skipTrialReelsNoDrop reels the payload marks as trial. Default false.
includeSharesCountNoAdd sharesCount when the payload has a share or reshare count. Default false.
includeDownloadedVideoNoSave the MP4 and set downloadedVideo. Default false.
{
  "username": ["natgeo"],
  "resultsLimit": 20
}

📤 Output

Each public reel is one dataset item. A field is omitted when Instagram did not send it. A real false or 0 is kept.

Identity and text: id, pk, type, shortCode, url, inputUrl, caption, hashtags, mentions, alt, productType, timestamp.

Counts: likesCount, commentsCount, videoViewCount, videoPlayCount, igPlayCount, fbLikeCount, fbPlayCount, reshareCount. sharesCount only when includeSharesCount is on and a count was present.

Media: displayUrl, videoUrl, audioUrl, videoDuration, dimensionsWidth, dimensionsHeight. originalWidth and originalHeight only when Instagram sent the original size. images and childPosts for carousel children. downloadedVideo only after a successful MP4 store.

People and context: ownerUsername, ownerId, ownerFullName, taggedUsers, sponsors, coauthorProducers, musicInfo, locationName, locationId, paidPartnership, affiliate, isPinned, isCommentsDisabled. facebookPage and threadsNetProfile only when the owner object includes them.

Comments: firstComment and latestComments (up to 10 preview comments, with id, text, ownerUsername, ownerProfilePicUrl, timestamp, likesCount, and owner).

A share URL that redirects records redirectedFromUrl.

A target that cannot be scraped, other than a username or id Instagram does not publish, is { "inputUrl", "error", "errorDescription" }. errorDescription is a status and code, or an exception type name. An unpublished username stores nothing and fails the run.

💰 Pricing

Pay per result, plus platform usage (compute and proxy traffic) at the normal rates.

EventWhen it is chargedPrice
ReelEach reel saved to the dataset$0.0017 ($1.70 per 1,000 reels)
Video downloadEach reel whose MP4 was saved, only when Include downloaded video is on$0.012

Example: 1,000 reels ≈ $1.70 in event fees plus platform usage. A 20-reel run of the prefilled profile used about $0.013 of platform usage in our tests. Downloading videos also adds the proxy traffic of each MP4 (about 13 MB per reel in our tests). The shares count option is free. Error rows (private profile, unsupported URL) are never charged. If you set a maximum charge for the run, the scraper stops cleanly when it is reached and keeps every reel it already saved.

▶️ Run

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pytest
python -m src

pytest checks mapping and URL parsing. A full scrape runs on Scrapely, where the residential proxy is available.

Related actors

G2
4.7/5
Excellent
Trustpilot

The internet is full of data.
Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.

No credit card. No setup calls.