# Instagram Scraper API — Posts, Comments, Reels, No Login (`yugenox/instagram-scraper`) Actor

Scrape Instagram with no login: posts, reels, profiles, hashtags, locations, audio. Plus all public comments (up to ~4,800/post), reel transcripts at $0.004/min, AI summaries, bio emails and Trends. Works in Claude, Cursor and AI agents via MCP. $1.90 per 1,000.

- **URL**: https://apify.com/yugenox/instagram-scraper.md
- **Developed by:** [Yugenox Corp](https://apify.com/yugenox) (community)
- **Categories:** Social media, Developer tools, Lead generation
- **Features:** Limited permissions
- **Stats:** 68 total users, 30 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 results

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 Scraper — No Login · All Comments, Transcripts, Trends & Creator Reports

Scrape public Instagram **posts, reels, comments, profiles, hashtags, locations and audio** with no login and no cookies. On top of the usual data (likes, plays, captions, media, owners with follower counts, co-authors, tagged users, sponsors, music, locations) you can get **every public comment on a post**, **speech-to-text transcripts** for $0.004 a minute, **Instagram's own Trends list** and a **Creator Report Card** for influencer vetting.

### Why this one

- 🔑 **No Instagram login, no cookies, no account at risk.** Paste URLs and run.
- 💬 **All comments, not the first page.** Comments mode pages to the end of the thread, sorts by likes if you want, and filters by likes, keywords and date before billing.
- 🗣️ **Transcripts at $0.004 per minute** of audio, in any language. Reels set to a licensed song are skipped free.
- 📈 **Things other Instagram scrapers don't sell:** Instagram Trends (about 400 trending keywords and rising profiles, with post counts), a Creator Report Card (median reel plays, engagement by views, posting cadence, brand partners, price band, comment-pod signals), and monitor mode that returns only what's new.
- 💰 **$1.90 per 1,000 results, with volume discounts by Apify plan down to $1.10.** Comments, AI summaries and view counts are included. Rows your filters drop are free, and a per-input run report tells you exactly what happened to each URL.

### How it compares

| | **This actor** | Apify Instagram Scraper | Apify Instagram Comments Scraper | apidojo Instagram Scraper |
|---|---|---|---|---|
| Price per 1,000 results | **$1.90 Free · $1.90 Bronze · $1.50 Silver · $1.10 Gold** | $2.70 Free · $2.30 Bronze · $1.90 Silver · $1.50 Gold | $2.60 Free · $2.30 Bronze · $2.10 Silver · $1.90 Gold | about $0.50 |
| Comments per post | **All public comments** | One page (~15) on the Free plan | Public comments | Separate actor |
| Sort comments by likes; filter by likes, keyword, date | **Yes, before billing** | No | No | No |
| Video transcripts | **$0.004 per minute** | $0.034–0.048 per started minute of each reel (Instagram Reel Scraper add-on, Silver–Free plans) | — | — |
| Instagram's AI title & summary per post | **Included** | — | — | — |
| Instagram Trends (trending keywords, rising profiles) | **Yes** | — | — | — |
| Creator Report Card (influencer vetting) | **Yes, opt-in (free for now, then $0.01 per report)** | — | — | — |
| Only new posts on scheduled runs | **Monitor mode** | — | — | — |
| Input format | apidojo-style (`startUrls`, `keywords`, `until`, `maxItems`) | Own format | Own format | apidojo |

Competitor prices are their public Store prices as of September 2026, per 1,000 results except for transcripts. Free, Bronze, Silver and Gold are Apify's discount tiers for the Free, Starter, Scale and Business plans. A 30-second reel's transcript costs $0.004 here and $0.048 with the Instagram Reel Scraper on the Free plan ($0.034 on Silver). apidojo is cheaper per plain post row; this actor includes comments, owner follower counts, AI summaries and view counts in the same price and adds the features in bold.

### What you can scrape

| Input | Example | What you get |
|---|---|---|
| 👤 Profile | `https://www.instagram.com/nasa/` or `nasa` | The profile's posts, newest first, as deep as the profile goes |
| 🎬 Reels tab | `https://www.instagram.com/nasa/reels/` | The profile's reels, with play counts |
| #️⃣ Hashtag | `https://www.instagram.com/explore/tags/travel/` or `#travel` | Top posts for the hashtag |
| 🔍 Keyword | `keywords: ["toronto"]` or `/explore/search/keyword/?q=toronto` | Top posts for the keyword |
| 📍 Location | `https://www.instagram.com/explore/locations/213131048/` | Top and most recent posts at the place (paused since October 2026, see Good to know) |
| 🎵 Audio | `https://www.instagram.com/reels/audio/271328201351336/` | Reels using that sound |
| 🖼️ Post or reel | `https://www.instagram.com/p/DRvit9Ejgel/` or a `/share/` link | That post, or all its comments |
| 📈 Trends | `https://www.instagram.com/popular/` | Instagram's ranked trending keywords and rising profiles |
| 🔢 User ID | `528817151` | That profile's posts |

#### Three result types (`resultsType`)

- **posts** (default): posts and reels, one row each.
- **details**: one row per source:
  - **Profiles**: bio, all bio links, followers and following, highlights, category (e.g. "Bakery"), account type (personal, business or creator), Threads username, HD profile picture, **emails and phones found in the bio**, story activity, Meta Verified status, optionally up to 50 **related accounts** and the **Creator Report Card**.
  - **Hashtags and keywords**: Instagram's topic description with sources, plus up to 100 related keywords.
  - **Locations**: category, coordinates, address, price range, opening status, the place's Instagram account and its post count.
- **comments**: one row per comment (text, author, likes, date), from post URLs or from every post a profile, hashtag or location returns.

### 💬 All comments, sorted and filtered

Instagram shows every public comment to logged-out visitors; this actor keeps paging until the thread ends, up to about 4,800 comments per post (tested: all 617 of 617 comments on one reel). Set **What to scrape** to **Comments** and paste post URLs, profiles, hashtags or locations.

| Option | Does |
|---|---|
| `maxComments` | Comments to save per post (with filters: matching comments) |
| `commentsSort` | `newest` (default) or `top` — most-liked first, picked from up to `commentsScanLimit` comments per post (default 2,000, up to ~4,800) |
| `minCommentLikes` | Only comments with at least this many likes |
| `commentKeywords` | Only comments containing any of these words (case-insensitive) — questions, complaints, product names |
| `commentsNewerThan` | Only comments newer than a date or period (`2 days`); paging stops at the first older one |

You pay only for comments saved; comments your filters skip cost nothing. The same filters apply to `commentsPerPost` (latest comments attached to posts) when you set them. Replies to comments are only visible to logged-in accounts, so neither the replies nor their counts are included (`replyCount` is always `null`). Expect fewer rows than the post's `commentCount`: Instagram's count includes those replies, plus hidden and deleted comments. For example, one reel showing 672 comments has 523 public top-level comments.

### 📈 Instagram Trends

Paste `https://www.instagram.com/popular/` into **Instagram URLs** to get Instagram's own Trends page: about 400 ranked entries in 8 sections — Trending now, Trending this month, Entertainment, Celebrities (rising profiles with follower counts), Browse categories, Get inspired, Learn something new and Shop the trends. Each row has the section, rank, keyword, the number of posts Instagram counts for it, a thumbnail, a featured reel and, for profiles, the account with its follower count.

- `trendSections`: keep only some sections (default: all).
- `trendPostsPerKeyword`: also scrape up to N top posts for every trending keyword. Those posts carry `source: { type: "trend", keyword, section }`.
- Every trending keyword is a public Instagram page, so it is also a keyword that works in `keywords`.

The list is global — Instagram shows the same Trends to every country. A full snapshot is about 400 rows ($0.76). Scheduled daily with monitor mode, each trend row gains `changes` (`isNew`, `previousRank`, `rankChange`, `postCountDelta`), which turns it into a time series.

### 📊 Creator Report Card

Turn on `includeCreatorReport` with **Details** mode (or with `includeDetails` in Posts mode) and every profile row gets a `creatorReport` built from the creator's recent posts and reels:

- **Reach:** `medianReelPlays`, `avgReelPlaysTrimmed`, `medianLikes`, `medianComments`
- **Engagement:** `engagementRateByFollowers`, `engagementRateByViews`, `engagementConsistency` (lower = steadier)
- **Activity:** `postsPerWeek`, `lastPostAt`, `daysSinceLastPost`, `formatMix` (reels / carousels / images), `storyActive`, `hiddenLikesShare`
- **Top content:** `topPosts` with an `outlierScore` (plays or likes ÷ the creator's median)
- **Brand work:** `sponsoredShare`, `brandPartners` (from paid-partnership labels, co-authors on paid posts and disclosure tags like #ad #sponsored #anzeige #publi), `sponsoredVsOrganicER`
- **Price band:** `estimatedPostPriceUsd` `{ low, high }` from a $10–30 CPM on median reel plays — an estimate, clearly labelled
- **Authenticity signals** (`creatorReportComments` 1–6): repeat commenters across posts, generic comments and the comment-to-like ratio from the latest public comments. These are signals, not a fake-follower percentage.

Posts by a reported creator carry `outlierScore`, and `minOutlierScore` keeps only the posts that beat the creator's own median (e.g. `3` = three times their typical plays). The report adds about 3 requests per profile. It's **free for now**. It will cost **$0.01 per report** on top of the profile row, starting 14 days after Apify emails users about the price change. Private profiles and profiles with no posts or reels will stay free. If a report can't be built, the row is still saved with `creatorReport: null` and the report isn't charged.

What `creatorReport` looks like (NASA, September 2026, shortened):

```json
{
  "sample": { "posts": 30, "reels": 24, "pinnedExcluded": 3, "from": "2026-08-30T12:58:34.000Z", "to": "2026-09-25T14:13:11.000Z" },
  "followerCount": 104335370,
  "medianReelPlays": 5694506.5,
  "avgReelPlaysTrimmed": 5930920,
  "medianLikes": 187695.5,
  "medianComments": 743,
  "engagementRateByFollowers": 0.1812,
  "engagementRateByViews": 2.3482,
  "engagementConsistency": 0.723,
  "postsPerWeek": 7.77,
  "daysSinceLastPost": 0,
  "formatMix": { "reels": 0.4, "carousels": 0.2, "images": 0.4 },
  "hiddenLikesShare": 0,
  "topPosts": [{ "code": "DdCHVu3CVzd", "url": "https://www.instagram.com/p/DdCHVu3CVzd/", "type": "post", "likes": 640658, "outlierScore": 3.41 }],
  "sponsoredShare": 0,
  "brandPartners": [],
  "estimatedPostPriceUsd": { "low": 56945, "high": 170835, "currency": "USD", "method": "$10-30 CPM × median reel plays (estimate)" },
  "storyActive": true,
  "metaVerified": false
}
```

Engagement rates are percentages. With `creatorReportComments`, an `authenticity` block is added.

### 🛰️ Monitor mode — only what's new

For scheduled runs, set `monitor: true` and a `monitorKey` (one per watchlist). The actor remembers what earlier runs saved and returns only **new posts and comments** — repeats are skipped and not charged. Profile rows gain `changes` (`followerDelta`, `followerDeltaPct`, `followingDelta`, `previousFollowerCount`, `bioChanged`, `externalUrlChanged`, `nameChanged`, `verifiedChanged`, `previousCheckAt`; `null` on the first check), and trend rows gain rank changes. On profiles, paging stops at the newest post an earlier run delivered, so repeat runs are fast. The memory lives in a key-value store in your own Apify account (`instagram-monitor-<key>`).

### 🧾 Run report — no silent failures

Every run saves a `RUN_REPORT` record (Storage → Key-value store, or the **Run report** link in the Output tab) with one entry per input: `ok`, `private`, `not_found`, `login_only`, `capped`, `empty`, `filtered`, `duplicate`, `not_video`, `partial`, `blocked` or `failed`, with its row count and a note. A private account, a hashtag Instagram keeps behind a login or an audio page capped at 12 posts no longer looks like a quiet success. It is free (not a dataset row).

### Add-ons for posts

| Option | Adds |
|---|---|
| `commentsPerPost` | `latestComments`: the newest N comments on each post (or the top ones, with the comment options above) |
| `includeTranscript` | `transcript` and `transcriptLanguage`: speech-to-text for every video, in any language (up to 15 minutes; $0.004 per minute) |
| `includeAiSummary` | `aiTitle` and `aiSummary`: Instagram's own AI description of the post |
| `includeVideoViews` | `video.viewCount`: Instagram's "views" metric, alongside `video.playCount` |
| `includeDetails` | The profile, keyword and place rows described above, alongside the posts |

### Discovery and filters

- `scrapeRelatedProfiles`: also scrape up to N accounts similar to each profile you give. Useful for finding competitors or lookalike creators.
- `expandRelatedKeywords`: go past Instagram's ~60 top posts per hashtag by also pulling related keywords.
- `minFollowers`, `maxFollowers`, `verifiedOnly`, `businessOnly`, `withContactOnly`, `minLikes`, `minPlays`, `minOutlierScore` and `skipPinnedPosts`: rows that don't match are skipped and not billed.
- `videosOnly`: keep only videos and reels. Photos and carousels are skipped and not billed, and the run report names them (`not_video`).

### Input

| Field | Type | Description |
|---|---|---|
| `startUrls` | array | Instagram URLs, handles or #hashtags (see table above) |
| `keywords` | array | Keywords to search. Each keyword is a separate query |
| `maxItems` | integer | Maximum number of results across the whole run |
| `resultsType` | string | `posts` (default), `details` or `comments` |
| `maxItemsPerQuery` | integer | Maximum number of results per URL or keyword |
| `until` | string | Only posts created on or after this date (`YYYY-MM-DD`) or within a period like `7 days` or `3 months`. Profile scraping stops as soon as it reaches older posts, so you don't pay for them |
| `includeDetails` | boolean | Adds profile, keyword and place rows alongside the posts |
| `commentsPerPost` / `maxComments` | integer | Latest comments attached to each post / comments per post in comments mode |
| `commentsSort`, `minCommentLikes`, `commentKeywords`, `commentsNewerThan`, `commentsScanLimit` | | Comment sorting and filters (see above) |
| `includeTranscript`, `includeAiSummary`, `includeVideoViews` | boolean | Post add-ons (see above) |
| `includeCreatorReport`, `creatorReportComments` | | Creator Report Card (see above) |
| `trendSections`, `trendPostsPerKeyword` | | Instagram Trends (see above) |
| `includeRelatedProfiles`, `scrapeRelatedProfiles`, `expandRelatedKeywords` | | Discovery (see above) |
| `minFollowers`, `maxFollowers`, `verifiedOnly`, `businessOnly`, `withContactOnly`, `minLikes`, `minPlays`, `minOutlierScore`, `skipPinnedPosts`, `videosOnly` | | Filters |
| `monitor`, `monitorKey` | | Monitor mode (see above) |
| `customMapFunction` | string | Temporarily disabled: accepted but ignored (items are saved unmodified, with a log warning) |
| `maxConcurrency` | integer | Number of parallel requests (default 20) |

```json
{
  "startUrls": ["https://www.instagram.com/nasa/", "https://www.instagram.com/explore/tags/travel/"],
  "keywords": ["toronto"],
  "until": "2026-09-01",
  "maxItems": 200
}
```

### Output

One row per post (`dataType: "post"`):

```json
{
  "dataType": "post",
  "id": "3991849403537918302_13460080",
  "pk": "3991849403537918302",
  "code": "Ddl5eH-u4le",
  "url": "https://www.instagram.com/reel/Ddl5eH-u4le/",
  "createdAt": "2026-09-22T14:00:04.000Z",
  "caption": "Just a normal day for @caitlinclark22 …",
  "hashtags": [],
  "mentions": ["caitlinclark22"],
  "likeCount": 25582,
  "commentCount": 487,
  "mediaType": "video",
  "productType": "clips",
  "isVideo": true,
  "isCarousel": false,
  "isPinned": false,
  "isPaidPartnership": false,
  "isLikeAndViewCountsDisabled": false,
  "commentsDisabled": false,
  "owner": {
    "id": "13460080", "username": "nike", "fullName": "Nike", "isVerified": true, "isPrivate": false,
    "profilePicUrl": "https://…", "followerCount": 291000000, "followingCount": 266,
    "biography": "…", "externalUrl": "https://…"
  },
  "coowners": [{ "id": "306787899", "username": "nikebasketball", "fullName": "Nike Basketball", "isVerified": true }],
  "taggedUsers": [{ "id": "1466972266", "username": "caitlinclark22", "fullName": "Caitlin Clark", "isVerified": true }],
  "location": { "id": "213131048", "name": "Berlin, Germany", "slug": "berlin-germany", "address": null, "city": null, "lat": 52.518, "lng": 13.401 },
  "audio": { "id": "…", "title": "Original audio", "artist": "nike", "isOriginal": true },
  "image": { "url": "https://…", "width": 1080, "height": 1920 },
  "video": { "url": "https://….mp4", "duration": 30.03, "playCount": 915165, "width": 1080, "height": 1920 },
  "carousel": [],
  "carouselCount": null,
  "accessibilityCaption": "Video by Nike on September 22, 2026.",
  "sponsors": [],
  "engagementRate": 0.0113,
  "latestComments": [{ "id": "18195039400344668", "text": "Nike & Caitlin have revealed…", "createdAt": "2026-09-22T14:21:03.000Z", "likeCount": 12, "owner": { "username": "…" } }],
  "transcript": "Caitlyn Clark is just a normal girl from Iowa…",
  "transcriptLanguage": "en",
  "aiTitle": "Normal Life of Iowa's Caitlin Clark",
  "aiSummary": "…",
  "source": { "type": "user", "input": "https://www.instagram.com/nike/" }
}
```

Carousel posts list every slide in `carousel` (`type`, `url`, `videoUrl`, `width`, `height`).

A comment row (`dataType: "comment"`):

```json
{
  "dataType": "comment",
  "id": "18195039400344668",
  "text": "Nike & Caitlin have revealed…",
  "createdAt": "2026-09-22T14:21:03.000Z",
  "likeCount": 12,
  "replyCount": null,
  "owner": { "id": "…", "username": "…", "isVerified": false, "profilePicUrl": "https://…" },
  "postId": "3991849403537918302",
  "postCode": "Ddl5eH-u4le",
  "postUrl": "https://www.instagram.com/reel/Ddl5eH-u4le/",
  "postOwnerUsername": "nike",
  "isPostOwner": false
}
```

A trend row (`dataType: "trend"`):

```json
{
  "dataType": "trend",
  "section": "TRENDING_NOW",
  "sectionTitle": "Trending now",
  "rank": 1,
  "kind": "keyword",
  "keyword": "noreaster",
  "displayName": null,
  "postCount": 1220294,
  "url": "https://www.instagram.com/popular/noreaster/",
  "thumbnailUrl": "https://…",
  "featuredReel": { "code": "…", "url": "https://www.instagram.com/reel/…/", "videoUrl": "https://…" },
  "profile": null,
  "scrapedAt": "2026-09-26T14:00:00.000Z",
  "source": { "type": "trends", "input": "https://www.instagram.com/popular/" }
}
```

Fields that are always present on posts are `id`, `code`, `url`, `createdAt` and `owner.username`. Fields that can be `null` include:

- `likeCount`, when the creator hid counts
- `video.playCount`, on some feed videos where Instagram doesn't expose plays, and on a pinned reel from months back (see "Good to know")
- `location`, `audio` and `video`, when they don't apply to the post
- `isPaidPartnership`, when Instagram doesn't report it for that post

### Pricing

**$1.90 per 1,000 results ($0.0019 each), with volume discounts by Apify plan.** A result is any saved row: a post, a comment, a trend, or a profile, place or keyword row.

| Your Apify plan (discount tier) | Per result | Per 1,000 results |
|---|---:|---:|
| Free (FREE) | $0.0019 | $1.90 |
| Starter (BRONZE) | $0.0019 | $1.90 |
| Scale (SILVER) | $0.0015 | $1.50 |
| Business (GOLD) | $0.0011 | $1.10 |
| Enterprise (PLATINUM) | $0.0011 | $1.10 |
| Enterprise (DIAMOND) | $0.0011 | $1.10 |

- **Included at no extra cost:** latest comments on each post, AI summaries and video view counts.
- **Creator Report Card** (optional) is **free for now**. It will cost **$0.01 per report** on every plan, on top of the profile row, starting 14 days after Apify emails users about the price change. Private profiles, profiles with no posts or reels, and reports that can't be built will stay free.
- **Video transcripts** (optional) cost **$0.004 per started minute** of audio on every plan, so a typical 30-second reel adds $0.004. Reels set to a licensed song have no speech to transcribe; they're skipped and not charged.
- **You only pay for rows you get.** Queries that find nothing, login-only sources, rows removed by your filters and posts monitor mode has already seen cost nothing.
- **Your spending limit is respected up front:** the run stops exactly at the number of results your limit covers.

**Examples** (Free and Starter prices):

- 1,000 posts from any mix of profiles, hashtags and locations: **$1.90** ($1.50 on Scale, $1.10 on Business)
- 2,000 comments from one viral post: **$3.80**
- 100 profiles in details mode with the Creator Report Card: **$0.19** while reports are free (100 results), then **$1.19** (100 results plus 100 reports)
- A full Instagram Trends snapshot (about 400 rows): **$0.76**

Free Apify plans are limited to 100 results per run.

### Use it from n8n, Make, Zapier, AI agents or code

**API (one call, results back):**

```bash
curl -X POST "https://api.apify.com/v2/acts/yugenox~instagram-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"startUrls":["https://www.instagram.com/p/DRvit9Ejgel/"],"resultsType":"comments","maxComments":500,"commentsSort":"top"}'
```

- **n8n:** the Apify node → *Run an Actor and get dataset* → `yugenox/instagram-scraper`, or an HTTP Request node with the URL above.
- **Make / Zapier:** the Apify app → *Run an Actor* → pick this actor and paste the input JSON.
- **AI agents (MCP):** add `https://mcp.apify.com/?actors=yugenox/instagram-scraper` to Claude, Cursor or any MCP client, or run `npx @apify/actors-mcp-server --actors yugenox/instagram-scraper` with `APIFY_TOKEN` set.
- Python and Node.js: the `apify-client` packages, with the same input.

### Good to know

- **Hashtags and keywords.** Instagram shows logged-out visitors top posts only for popular terms (e.g. `travel`, `nyc`, `toronto`), typically up to about 60 posts. For terms Instagram keeps behind a login, the run report says `login_only` and nothing is charged. Trending keywords from the Trends page all work.
- **Locations.** Since October 2026 Instagram doesn't serve location pages or place details to logged-out visitors. Location inputs return nothing for now: the run report says `login_only` and nothing is charged. Posts keep their place name and coordinates, but `location.address` and `location.city` stay empty. Both come back on their own if Instagram reopens them (before that, locations returned about 70 top and recent posts).
- **Audio pages** show logged-out visitors only the first 12 reels. The run report marks those inputs `capped`.
- **Profiles** page through the whole public feed, newest first.
- **Play counts on pinned reels.** Instagram shows a reel's play count only on the profile's reels tab, and pinned reels are often months older than the rest of a run. A pinned reel with its own original sound gets its play count from that sound's page (one request); otherwise the reels tab is read back to the reel's date, up to 12 extra pages. A pinned reel further back than that keeps `video.playCount: null`, the run report names it, and `minPlays` (or `minOutlierScore`) skips it with a log warning.
- **Private accounts** have no public posts. They are skipped, and the run report marks them `private`.
- **Overlapping inputs are saved once.** When two inputs reach the same post (a reel URL plus its own audio page, two audio pages, a collab post on two profiles you scrape), it is saved and charged once per run, for the input that reached it first. The run report counts the skipped repeats (`duplicatesSkipped`).

### What only logged-in Instagram accounts can see

This actor never logs in, so these are not available — from this actor or any other no-login scraper:

- Follower and following lists, and who liked a post
- Stories and the contents of highlights (highlight titles and covers are included on profile rows)
- Posts a profile is tagged in
- Replies to comments, and how many replies a comment has
- Instagram's search for profiles, places and hashtags
- Hashtags and keywords that have no public Instagram page (e.g. `#food`)
- The "About this account" panel and the email / call buttons of business profiles (emails and phones written in the bio are included)

The `getStories` and `handles` inputs are accepted for compatibility and skipped at no charge.

### Custom map function

> **Temporarily disabled for a security review:** the `customMapFunction` input is accepted and ignored, and items are saved unmodified. The log shows a warning starting with `Your "customMapFunction" input was rejected:`. Existing tasks that set it keep running; they just get the original items. It will come back in a sandboxed form.

### FAQ

**Do I need an Instagram account or cookies?** No.

**How fresh is the data?** It's live. Every run reads Instagram at that moment.

**How much does it cost?** $1.90 per 1,000 results on the Free and Starter plans, $1.50 on Scale and $1.10 on Business and enterprise plans (see Pricing). Video transcripts are $0.004 per minute. The Creator Report Card is free for now and will cost $0.01 per report, starting 14 days after Apify emails users about the change. Rows your filters drop and inputs that return nothing are free.

**Can I try it on the Free plan?** Yes. Free Apify plans get up to 100 results per run, paid from the plan's monthly usage credit. Paid plans have no cap beyond your `maxItems` and your spending limit.

**Why do I get fewer comments than the post's comment count?** Instagram's count includes replies, plus comments that are hidden, restricted or deleted. None of those are visible without logging in, so they can't be scraped.

**Can I schedule it?** Yes. Use Apify schedules with monitor mode to get only new posts and comments each run, or with `until` to limit by date.

**Can I use it from code or an AI agent?** Yes, through the Apify API, the Python and Node.js clients, webhooks, n8n, Make, Zapier or MCP (see above).

**Is it legal to scrape Instagram?** This Actor only collects publicly available data: posts, reels and profiles from public Instagram accounts, which anyone can see without logging in. Collecting publicly available data is generally legal, but you're responsible for how you use it. Results can include usernames, profile details, captions and comments from public accounts, and that counts as personal data. You must follow privacy laws such as GDPR, PIPEDA and CCPA, as well as Instagram's terms. If you're unsure, check with a lawyer. More on this: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?** No. Everything comes from pages Instagram shows to any visitor without logging in. It never uses a login, never touches private or restricted accounts, and never reaches password-protected areas. Private accounts are never accessed.

**Can I email the contacts I find?** Only in line with anti-spam and privacy law: CASL in Canada, CAN-SPAM in the US and GDPR / ePrivacy in the EU and UK, which generally require consent or a legitimate basis, a clear sender identity and a working opt-out.

### Also by us

- [YouTube Scraper](https://apify.com/yugenox/youtube-scraper)

### Changelog

- **October 2026**
  - A post reached by more than one input in the same run is saved and charged once (it was once per input). The run report counts the repeats as `duplicatesSkipped`.
  - New `videosOnly` filter: photos and carousels are skipped before they are charged.
- **September 2026**
  - Pricing: volume discounts by Apify plan ($1.90 per 1,000 results on Free and Starter, $1.50 on Scale, $1.10 on Business and enterprise). The Creator Report Card is free for now and will cost $0.01 per report, starting 14 days after Apify emails users about the change. Free plans get 100 results per run, up from 10.
  - Comments mode reads every public comment, with top-comments sorting and like, keyword and date filters applied before billing. Comment rows gain `postOwnerUsername` and `isPostOwner`.
  - New: Instagram Trends (`https://www.instagram.com/popular/`), the Creator Report Card, monitor mode, the per-input `RUN_REPORT` and the `minLikes`, `minPlays` and `minOutlierScore` filters.
  - Profiles scrape with far fewer requests and results start streaming within seconds; rows are saved in batches, and a run stops exactly at your spending limit.
  - Fixed: `isPinned` is now reported on profile photos and carousels (it was `null`), so `skipPinnedPosts` works for them too.
  - Pinned reels get their play count from their own audio page or a bounded extra walk of the reels tab. A pinned reel from many months back can have `video.playCount: null` (the run report names it); the old version walked the whole reels tab for it, which took up to a minute on busy accounts.
  - The run report no longer calls an input `empty` or `capped` when the run was stopped by an Instagram-wide block or a stall; it says `partial`, `blocked` or `failed`, with the reason.
  - `customMapFunction` is temporarily disabled for a security review: it is accepted and ignored, and items are saved unmodified.
  - Fixed: `reelsCount` on profile rows is `null` when Instagram only reports "has reels" (it showed a false `1`). New profile fields: `latestStoryAt`, `hasActiveStory`, `metaVerified`, `metaVerifiedBenefits`, `instagramGraphId` (the account's id in Meta's Instagram Graph API, not a Facebook Page id), `transparencyLabel`.
- **23 September 2026** — first release.

# Actor input Schema

## `startUrls` (type: `array`):

Profiles (https://www.instagram.com/nasa/), reels tabs (/nasa/reels/), hashtags (/explore/tags/travel/), locations (/explore/locations/213131048/), audio (/reels/audio/<id>/), keyword search (/explore/search/keyword/?q=toronto), posts and reels (/p/<code>/), /share/ links, and Instagram's Trends page (https://www.instagram.com/popular/). Bare handles (nasa), #hashtags and numeric user IDs work too.

## `keywords` (type: `array`):

Search posts by keyword. Each keyword runs its own search.

## `resultsType` (type: `string`):

Posts: posts and reels from each source. Details: one row per profile (bio, followers, category, business type, contacts, related accounts, optional Creator Report), hashtag/keyword (topic description, related keywords) or location. Comments: all public comments of each post found (or of the post URLs you give) — no 15-comment cap.

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

Maximum number of posts across the whole run. Leave empty for no limit. Free Apify plans get up to 100 per run.

## `maxItemsPerQuery` (type: `integer`):

Cap for each individual profile, hashtag, keyword, location or audio. Leave empty for no per-source limit.

## `until` (type: `string`):

A date (YYYY-MM-DD) or a period like "7 days", "2 weeks", "3 months". On profiles, scraping stops as soon as older posts are reached.

## `skipPinnedPosts` (type: `boolean`):

Leave out posts pinned to the top of a profile (they are often old).

## `commentsPerPost` (type: `integer`):

Attach up to this many of the newest comments (text, author, likes, date) to each post as latestComments. 0 = none. Included in the price.

## `includeTranscript` (type: `boolean`):

Transcribe the speech in every video and reel (any language, up to 15 minutes). Billed per started minute of audio ($0.004/min). Reels set to a licensed song are skipped free.

## `includeAiSummary` (type: `boolean`):

Add Instagram's own AI-written title and summary of each post (aiTitle, aiSummary).

## `includeVideoViews` (type: `boolean`):

Add video.viewCount (Instagram's "views" metric, which differs from plays). Adds one small request per video.

## `maxComments` (type: `integer`):

When What to scrape = Comments: how many comments to save per post. Instagram shows every public comment to logged-out visitors, so there is no 15-comment cap — up to about 4,800 per post. With filters, this counts matching comments.

## `commentsSort` (type: `string`):

Newest: newest first, as Instagram lists them. Top: the most-liked comments first — scans up to "Comments to scan" comments per post and keeps the top ones.

## `minCommentLikes` (type: `integer`):

Only keep comments with at least this many likes.

## `commentKeywords` (type: `array`):

Only keep comments containing any of these words or phrases (case-insensitive). Handy for questions ("price", "where"), complaints or product mentions.

## `commentsNewerThan` (type: `string`):

A date (YYYY-MM-DD) or a period like "2 days", "1 week". Paging stops at the first older comment, so old threads cost nothing extra.

## `commentsScanLimit` (type: `integer`):

With "Most liked first" or a filter, how many comments to read per post while looking for matches. You are only charged for the comments saved.

## `includeDetails` (type: `boolean`):

In Posts mode, also save one details row per profile, hashtag/keyword and location. Rows carry dataType "profile" / "keyword" / "place"; posts carry "post".

## `includeCreatorReport` (type: `boolean`):

Add creatorReport to every profile row: median reel plays, engagement by followers and by views, consistency, posting cadence, format mix, top posts with outlier scores, sponsored share, brand partners and an estimated post price band. Posts by that creator get an outlierScore (plays or likes ÷ the creator's median). Works in Details mode or with "Add profile rows". About 3 extra requests per profile. Free for now; it will cost $0.01 per report on top of the profile row, starting 14 days after Apify emails users about the price change. Private profiles, profiles with no posts or reels, and reports that can't be built stay free.

## `creatorReportComments` (type: `integer`):

Creator Report: also sample the latest comments of this many recent posts (0–6) for engagement-pod signals — repeat commenters across posts, generic comments, comment-to-like ratio. Signals only, not a fake-follower percentage.

## `includeRelatedProfiles` (type: `boolean`):

Add up to 50 similar accounts Instagram suggests (relatedProfiles) to each profile row.

## `scrapeRelatedProfiles` (type: `integer`):

For each profile you give, also scrape up to this many of its related accounts (one level deep). Great for finding similar creators or competitors.

## `expandRelatedKeywords` (type: `integer`):

Instagram shows about 60 top posts per hashtag or keyword. Set this to also pull posts from up to N related keywords, for many more results.

## `trendSections` (type: `array`):

For the Trends page input (https://www.instagram.com/popular/): which of Instagram's trend sections to save. Leave empty for all 8 (about 400 ranked keywords and rising profiles, with post counts).

## `trendPostsPerKeyword` (type: `integer`):

Also scrape up to this many top posts for every trending keyword in the selected sections (0 = trend rows only). Posts carry source.type "trend" with the keyword and section.

## `minFollowers` (type: `integer`):

Only keep posts / profiles whose owner has at least this many followers.

## `maxFollowers` (type: `integer`):

Only keep posts / profiles whose owner has at most this many followers.

## `verifiedOnly` (type: `boolean`):

Only keep posts / profiles from verified accounts.

## `businessOnly` (type: `boolean`):

Profile rows only: keep business and creator accounts.

## `withContactOnly` (type: `boolean`):

Profile rows only: keep profiles that list an email or phone number in their bio.

## `minLikes` (type: `integer`):

Only keep posts with at least this many likes. Posts with hidden like counts are skipped.

## `minPlays` (type: `integer`):

Only keep videos and reels with at least this many plays. Photos, and videos without a public play count (including a pinned reel from months back, see the run report), are skipped.

## `videosOnly` (type: `boolean`):

Only keep posts that are videos or reels: photos and carousels are skipped and not charged, and the run report names them. For one profile's videos, its /reels/ URL (e.g. https://www.instagram.com/nasa/reels/) is faster than filtering its whole grid.

## `minOutlierScore` (type: `number`):

Only keep posts that beat the creator's own median by this factor (e.g. 3 = three times their typical plays or likes). Needs the Creator Report Card, and applies to posts of profiles you scrape with profile rows on.

## `monitor` (type: `boolean`):

For scheduled runs: remember what earlier runs saved and return only new posts and comments, plus follower / bio changes on profile rows and rank changes on trend rows. Items already seen are skipped and not charged. State is kept in a key-value store in your own Apify account.

## `monitorKey` (type: `string`):

Names this watchlist's memory (letters, digits and dashes). Use a different name for each schedule you monitor. Default: "default".

## `customMapFunction` (type: `string`):

Temporarily disabled for security review: the function is accepted but not run, and items are saved unmodified (a warning is logged). Optional JavaScript function that transforms each post, e.g. (item) => ({ ...item, username: item.owner?.username }). For transformation only, not filtering. If the function is unusable, it is ignored with a warning and original posts are saved.

## `maxConcurrency` (type: `integer`):

How many requests run in parallel. Higher is faster.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy works well and is the default. Blocked IPs are rotated automatically, with a residential fallback.

## `getStories` (type: `boolean`):

Stories are only visible to logged-in Instagram accounts, so they are not available in this scraper. Accepted for input compatibility; no charge.

## `handles` (type: `array`):

Accepted for input compatibility (see Get stories).

## `userIds` (type: `array`):

Numeric Instagram user IDs to scrape as profiles. (Also the stories input, which is not available.)

## Actor input object example

```json
{
  "startUrls": [
    "https://www.instagram.com/nasa/",
    "https://www.instagram.com/explore/tags/travel/"
  ],
  "resultsType": "posts",
  "maxItems": 50,
  "maxItemsPerQuery": 25,
  "skipPinnedPosts": false,
  "commentsPerPost": 0,
  "includeTranscript": false,
  "includeAiSummary": false,
  "includeVideoViews": false,
  "maxComments": 50,
  "commentsSort": "newest",
  "commentsScanLimit": 2000,
  "includeDetails": false,
  "includeCreatorReport": false,
  "creatorReportComments": 0,
  "includeRelatedProfiles": false,
  "scrapeRelatedProfiles": 0,
  "expandRelatedKeywords": 0,
  "trendPostsPerKeyword": 0,
  "verifiedOnly": false,
  "businessOnly": false,
  "withContactOnly": false,
  "videosOnly": false,
  "monitor": false,
  "maxConcurrency": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "getStories": false
}
```

# Actor output Schema

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

All scraped rows (posts, comments, profiles, places, keywords, trends).

## `runReport` (type: `string`):

What happened to each input (ok, private, not found, login-only, capped, empty) with row counts and request stats.

## `run` (type: `string`):

Status and statistics for 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 = {
    "startUrls": [
        "https://www.instagram.com/nasa/",
        "https://www.instagram.com/explore/tags/travel/"
    ],
    "maxItems": 50,
    "maxItemsPerQuery": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/instagram-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 = {
    "startUrls": [
        "https://www.instagram.com/nasa/",
        "https://www.instagram.com/explore/tags/travel/",
    ],
    "maxItems": 50,
    "maxItemsPerQuery": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/instagram-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 '{
  "startUrls": [
    "https://www.instagram.com/nasa/",
    "https://www.instagram.com/explore/tags/travel/"
  ],
  "maxItems": 50,
  "maxItemsPerQuery": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call yugenox/instagram-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yugenox/instagram-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/JWobb5RZ2tA5WckR1/builds/6VaNeaEUKbuAaYf0g/openapi.json
