# Instagram Comments Scraper with Replies — CSV Export, No Login (`afanasenko/instagram-comments-scraper`) Actor

Instagram comments scraper: export Instagram comments to CSV, JSON or Excel from any public post or reel — comment text, author, likes, reply threads, @mentions and #hashtags, optional comment likers, no duplicates, no login. Filter by comment date; only new comments on repeat runs.

- **URL**: https://apify.com/afanasenko/instagram-comments-scraper.md
- **Developed by:** [Andrey Afanasenko](https://apify.com/afanasenko) (community)
- **Categories:** Lead generation, Social media, Automation
- **Features:** Limited permissions
- **Stats:** 87 total users, 24 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.82 / 1,000 comments

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 Comments Scraper with Replies — CSV Export, No Login

[![Apify Actor](https://apify.com/actor-badge?actor=afanasenko/instagram-comments-scraper)](https://apify.com/afanasenko/instagram-comments-scraper)

> **Paste an Instagram post or reel link. Get every comment Instagram serves as a spreadsheet row: who wrote it, what they said, when, and how many likes it has.**
> Replies come as their own rows. @mentions and #hashtags get their own columns. Public posts only, no login, no cookies. Export to CSV, JSON or Excel.

> **🆓 Free to start:** 50 comments per run · 15 runs a month · replies, mentions and both views included · no card, no login.

### 🎯 What it does

**You give** links to public Instagram posts or reels, one per line — up to 50 per run on a paid plan, 3 on the free one. Leave the box empty and it reads a demo post instead.

**You get** one row per comment: text, time, likes, author. Replies are rows too, each pointing at the comment it answers. @mentions and #hashtags get their own columns. Optional: who liked each comment.

**What you won't get: every comment the counter shows.** The number on the post counts replies, hidden and deleted comments. Instagram hands over fewer — a bit under half on a typical post. Every post gets a free summary row: what arrived, and why reading stopped.

Comments by **private accounts are included** — about six in ten on a busy post. Their comment is public.

### 📦 Output sample

Every comment is one row. Here is what a row holds:

- **The comment** — Comment Text, Posted At, Likes, Replies, Is Reply, Parent Comment ID, Mentions, Hashtags.
- **Who wrote it** — Account, Full Name, Author ID, Author Is Verified, Author Is Private, Profile Picture.
- **Which post** — Source, Post URL, Post Owner, Declared Comments.
- **Coverage and notices** — Delivered Top-Level, Delivered Replies, Stop Reason, Analysis Status, Why Not Analyzed, Comment Likers.

A real row from a recent run (likers switched on):

```json
{
  "Account": "https://instagram.com/marie.dubois",
  "Source": "DccbeHGPj3T",
  "Analysis Status": "analyzed",
  "Why Not Analyzed": "N/A",
  "Post URL": "https://www.instagram.com/p/DccbeHGPj3T/",
  "Post Owner": "natgeo",
  "Declared Comments": 173,
  "Delivered Top-Level": null,
  "Delivered Replies": null,
  "Stop Reason": null,
  "Comment ID": "17912345678901234",
  "Parent Comment ID": null,
  "Is Reply": false,
  "Comment Text": "This is stunning 😍 @jules_martin you have to see this",
  "Posted At": "2026-08-29T14:22:07.000Z",
  "Likes": 34,
  "Replies": 2,
  "Full Name": "Marie Dubois",
  "Author ID": "51234567890",
  "Author Is Private": true,
  "Author Is Verified": false,
  "Profile Picture": "https://scontent.cdninstagram.com/v/...",
  "Mentions": ["jules_martin"],
  "Hashtags": [],
  "Comment Likers": []
}
```

The coverage columns are filled on the `post_summary` row, not on comment rows.

**Views** — two ways to look at the same rows, in the **Storage → Dataset** tab:

| View | What each row is | Best for |
|---|---|---|
| **Comments** (default) | One comment, plus one `post_summary` row per post with its totals | Reading the discussion, sentiment work, export |
| **Commenters** | The same rows, trimmed to the person and who they tagged; someone who commented twice appears twice — dedupe by handle | Giveaway entrant lists |

Full per-field schema: [`.actor/dataset_schema.json`](.actor/dataset_schema.json) — what AI agents see through Apify's MCP server too.

### ⚡ Quick start

1. Open the **Input** tab.
2. Paste one or more post links into **Post Links**, one per line. Reel links work too.
3. Click **Start**. Rows appear in **Storage → Dataset** as they arrive; download CSV, JSON or Excel there.

A minimal input that works on the **free plan**:

```json
{
  "postUrls": ["https://www.instagram.com/p/CA2aJYrg6cZ/"],
  "maxCommentsPerPost": 50
}
```

### 🧭 When to use it

- **Giveaway entrant lists** — every entry as a row with the friends they tagged already in `Mentions`.
- **Comment sentiment analysis** — full text, time and likes, ready to score.
- **Competitor comment research** — what people say under a rival's posts, reply threads included.
- **Reply-thread export** — every reply as a row that names the comment it answers.
- **Finding who engages** — handle, name, verified and private flags on every row.
- **Watching a post over time** — run it on a schedule with **Skip comments already delivered to you**, and each run returns only what is new.
- **Comments from one week or month** — set a date range and get only the comments posted inside it.

### 🛠 Input

Three sections in the form: **🎯 Posts to export**, **📅 Which comments** and **▶️ Run & Storage Options**.

| Field | What it does | Default |
|---|---|---|
| **Post Links** | Post or reel links, one per line — up to 50 on a paid plan, 3 on the free one. Empty = demo run. | empty |
| **Max comments per post (cost control)** | Cost ceiling per post, in comments. A reply is a comment. `0` = no cap (paid plans). | `1000` |
| **Include reply threads** | Return each reply as its own row. | on |
| **Include who liked each comment** | Adds the accounts that liked each comment; a separate, cheaper event. | off |
| **Max likers per comment** | How deep to read each comment's liker list. | `50` |
| **Only comments posted on or after** | Keep comments posted from this moment on, UTC — a date (`2026-10-01`) or a span back from now (`7 days`, `3 weeks`). Replies too. | empty |
| **Only comments posted on or before** | Keep comments posted up to this moment, UTC — `2026-10-31` includes that whole day. | empty |
| **Skip comments already delivered to you** | Leave out comments and replies this Actor already gave you in an earlier run: in the last 7 / 30 / 90 / 180 / 365 days, or ever. | Off |
| **Start a Fresh Run** | Uncheck to resume the previous run. | on |

An unreadable link — not a post, deleted, or inside a private account — comes back as a **free row** with the reason.

### 💰 How much will scraping Instagram comments cost?

You pay per comment, not per run. Two events, priced by your Apify plan:

| Event (per 1,000) | Free | Bronze | Silver | Gold, Platinum & Diamond |
|---|---|---|---|---|
| **Comment** (a reply is a comment) | $2.60 | $2.34 | $2.08 | $1.82 |
| **Comment liker** (optional) | $0.43 | $0.39 | $0.34 | $0.30 |

| You ask for | Plan | Approx. cost |
|---|---|---|
| 50 comments — all a free run reads | Free | $0.13 |
| 1,000 comments | Bronze | $2.34 |
| 5,000 comments | Gold | $9.10 |

- Duplicates are removed **before** charging — you pay once per comment.
- Comments **outside your date range** or **already delivered to you** are not charged and do not count toward **Max comments per post**.
- Free rows: unreadable links, comments-off posts, and every `post_summary`.
- **Delivered free:** when likes, reply counts and replies cannot be read at the time of a run, the comments still come back — text, time and author — with those columns empty and `Why Not Analyzed` starting with "Delivered free". They are not charged and not counted as delivered to you, so a later run returns the complete rows.

**Replies count toward the cap** — 200 top-level comments with busy threads is closer to 400 rows, so set the cap for both. **Likers add work, not rows** — one lookup per comment, off by default.

### 🆓 Free vs paid plan

| | Free plan | Paid plan |
|---|---|---|
| Comments per run | 50 | as many as you ask for |
| Runs per month | 15 | unlimited |
| Post links per run | 3 | up to 50 |
| Reply threads | ✅ | ✅ |
| Comment likers | ✅ | ✅ |
| Resume from checkpoint | ✅ | ✅ |

Nothing else is held back: every column, both views and every option work the same on either plan. One depth differs: with a date range or **Skip comments already delivered to you** on, a free run leaves a post after 20 pages in a row with nothing new for you (a paid run after 400). Links past the third come back as free rows and cost nothing. A run **you abort** still uses up a slot.

While an unusually large number of new free accounts run this Actor at once, free runs from new accounts may be reduced for a short while to one post and up to 10 comments, without replies or comment likers. The run says so in its message and still counts as one of the 15. Paid plans are never affected.

All fifteen runs together cost $1.95 of the $5 monthly credit Apify gives a free account, so the allowance is really yours to spend.

### 🧪 Recipes

**A giveaway entrant list** — replies off (giveaway rules count top-level comments, and you pay for fewer rows), then open the **Commenters** view and dedupe by handle.

```json
{ "postUrls": ["https://www.instagram.com/p/YOUR_GIVEAWAY_POST/"],
  "includeReplies": false, "maxCommentsPerPost": 0 }
```

**A full discussion, threads and all** — sort the sheet by `Parent Comment ID` and every thread reads top to bottom.

```json
{ "postUrls": ["https://www.instagram.com/p/YOUR_POST/"],
  "includeReplies": true, "maxCommentsPerPost": 0 }
```

**Several posts, bounded spend** — posts are read in turn, so one viral post cannot starve the others.

```json
{ "postUrls": ["https://www.instagram.com/p/POST_ONE/",
               "https://www.instagram.com/reel/POST_TWO/"],
  "maxCommentsPerPost": 500 }
```

**Only last week's comments** — the date is the comment's own, in UTC. Once the list reaches comments older than the start, reading stops, so a short range on an old post costs little.

```json
{ "postUrls": ["https://www.instagram.com/p/YOUR_POST/"],
  "postedAfter": "7 days" }
```

**Only new comments since your last run** — schedule it daily. Comments you already have are skipped, not charged, and do not use up the cap; a new reply under a comment you already have still comes back.

```json
{ "postUrls": ["https://www.instagram.com/p/YOUR_POST/"],
  "skipDelivered": "forever" }
```

The record of what you were given is a key-value store named `ig-delivered-…` in your own **Storage**, kept by every run from version 0.0.27 on, with the option on or off. Delete it to start over. Two runs that overlap in time may both return the same comment.

### 🔁 Resume / checkpoint

Uncheck **Start a Fresh Run** to pick up where the last run stopped.

- Posts already finished are skipped.
- A post that hit a cap or an error is read again.
- A post cut off part-way carries on from where it stopped.

A resumed run gets a fresh allowance and spends a monthly slot.

### 📡 Live status & storage records

The run's **Storage → Key-value store** tab holds a live status page and these records:

| Record | What it holds |
|---|---|
| `status.html` | Live progress and cost |
| `RUN_SUMMARY` | Everything about the run, incl. declared vs delivered per post |
| `COMMENT_COVERAGE` | The coverage record alone, for integrations |
| `USER_MESSAGE` | The one thing this run most needs to tell you |
| `UNREAD_LINKS` | Every link that could not be read, with the reason |
| `API_USAGE` | Request count for this run |
| `FREE_LIMITS_APPLIED` | Free-plan ceilings that applied |

### 🤖 Programmatic / API use

**REST API:**

```bash
curl -X POST "https://api.apify.com/v2/acts/afanasenko~instagram-comments-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"postUrls":["https://www.instagram.com/p/CA2aJYrg6cZ/"],"maxCommentsPerPost":200}'
```

**MCP / agentic clients:** the actor is a tool on Apify's [MCP server](https://docs.apify.com/platform/integrations/mcp) at `mcp.apify.com`. Any AI assistant with your token can find it, read its schemas and run it — just ask: *"get the comments on this Instagram post, replies included, as CSV"*.

A run ends `SUCCEEDED` even with nothing to deliver; the reason is in `USER_MESSAGE` — branch on that.

### 💡 Tips & Best Practices

#### Getting maximum results

- Read a post soon after it goes up; Instagram serves less of an old thread.
- Judge coverage by **Declared** vs **Delivered** on the summary row.
- Paste several posts into one run; one viral post cannot starve the others.

#### Cost optimization

- **Max comments per post** bounds each post's bill, replies included.
- Turn replies off for giveaways; you pay for fewer rows.
- Keep likers off unless you need them; they multiply lookups, not rows.

#### Performance

- Small posts finish in under a minute; thousands of comments take several.
- Stop a long run any time; continue with **Start a Fresh Run** unchecked.
- Bound a huge post with the comment cap, not the run timeout — a cap ends cleanly.

#### Data quality

- Spot-check five rows against the post before scaling up.
- Sort by `Parent Comment ID` to rebuild threads in a sheet.
- `Author Is Private` is information, not a filter.

### ❓ FAQ

**Q: How do I get the comments on an Instagram post?**
A: Paste the post link into **Post Links** and click **Start**. Download the table from **Storage → Dataset**.

**Q: Is there a free Instagram comment scraper?**
A: Yes — 50 comments per run from up to 3 links, 15 runs a month, replies and both views included. No card needed.

**Q: Can I use the Instagram API instead?**
A: Instagram's Graph API returns comments only on your own business account's posts. This actor reads any public post or reel.

**Q: What are the best Instagram comment scraper alternatives?**
A: Check for replies as rows, duplicates removed before you pay, and declared vs delivered per post. This actor does all three.

**Q: Why did I get fewer comments than the post shows?**
A: The counter includes replies, hidden and deleted comments, and Instagram serves only some. Posts read to the very end returned 39–75% of it, median **44%** across eight posts. Totals sit on the `post_summary` row.

**Q: Does it work on private accounts?**
A: No — a post inside a private account comes back as a free row saying so. Comments *written by* private accounts are included.

**Q: Are duplicate comments possible?**
A: No. Instagram sometimes serves a comment on two pages; the actor drops the repeat by id before charging, also after a restart.

**Q: Can I sort comments by newest or most popular?**
A: No — Instagram offers no sort order for this data, so no tool can honestly promise one. Rows arrive in the order served — usually a post's top comments first, then newest to oldest. Sort the sheet by `Posted At` for time order.

**Q: Can I get only the comments from a date range?**
A: Yes — set **Only comments posted on or after** and/or **on or before** (`postedAfter`, `postedBefore`): a date like `2026-10-01` or a span like `3 weeks`, UTC. Comments outside the range are not charged. A reply is looked for only under a comment inside the range.

**Q: Can I get only the comments that are new since my last run?**
A: Yes — set **Skip comments already delivered to you** (`skipDelivered`: `"off"`, a number of days such as `"30"`, or `"forever"`). Comments you already got from this Actor are skipped before the charge, and the run reads on for new ones. A run where everything was already delivered costs nothing and says so in `USER_MESSAGE`.

**Q: What is the `post_summary` row?**
A: One free row per post with the declared count, what was delivered, and Stop Reason: `end` (list ran out — with a date range, the comments inside it ran out) · `cap` (your limit, the free ceiling, or page after page with nothing new for you) · `error` (source stopped answering) · `disabled` (comments off).

**Q: Why do I see `null` for missing values?**
A: `null` means Instagram did not give it — or, on a row marked "Delivered free" in `Why Not Analyzed`, that it could not be read at the time of that run (never zero). Only `Why Not Analyzed` uses `N/A`. Every key is present except `Comment Likers`, which appears only when likers are on.

### 🔗 Other Instagram scrapers (same author)

| You start with… | You want to find… | Use this actor |
|---|---|---|
| A post or reel link | Its comments and replies, as rows | **This actor** |
| A post or reel link | Who liked or commented, as full profiles | [Instagram Likes Scraper](https://apify.com/afanasenko/instagram-post-likers-scraper) |
| Handles, links, keywords or places | Profiles via 6 discovery modes | [Instagram Profile Scraper](https://apify.com/afanasenko/instagram-profile-scraper) |
| One known account | Its followers and following | [Instagram Followers & Following Extractor](https://apify.com/afanasenko/instagram-followers-scraper) |
| One known account | Who followed and unfollowed **over time** | [Instagram Follower Tracker](https://apify.com/afanasenko/instagram-follower-tracker) |
| 1–5 seed handles | Similar profiles via «Suggested for You» | [Instagram Related Profiles Scraper](https://apify.com/afanasenko/instagram-related-profiles-scraper) |
| A keyword or a hashtag | The accounts in that niche | [Instagram Influencer Search](https://apify.com/afanasenko/instagram-influencer-search) |
| A reel link or a creator handle | What the reels **say** — transcript, on-screen text | [Instagram Reel Script Extractor](https://apify.com/afanasenko/instagram-reel-script-extractor) |
| An AI agent | The profile scraper's modes as MCP tools | [Instagram Profile Scraper MCP Server](https://apify.com/afanasenko/instagram-profile-scraper-mcp-server) |

People behind a post as profiles → Instagram Likes Scraper. What they **said** → this one.

### 🛟 Support & feedback

- **Open an issue** on the actor's [Issues tab in Apify Console](https://console.apify.com/actors/dNo2eHsgX7nec70EF/issues) — paste the run URL.
- **Feature requests** in the same tab; we read every one.
- **Ratings & reviews** on the [Apify Store page](https://apify.com/afanasenko/instagram-comments-scraper) help other users find the actor.

### ⚖️ Is it legal to scrape Instagram comments?

Yes — the actor reads **publicly available** comments and does not log in, bypass authentication, read private accounts, or interact with content on your behalf. You are responsible for how you use the data, including GDPR, CCPA and Instagram's terms.

# Changelog

This Actor's version history is a separate document: https://apify.com/afanasenko/instagram-comments-scraper/changelog.md

# Actor input Schema

## `postUrls` (type: `array`):

Instagram post or reel links, one per line — e.g. https://www.instagram.com/p/CA2aJYrg6cZ/. Reel links work too. A link that is not a post link, a deleted post, and a post inside a private account cannot be read — each one comes back as its own free row naming the link and why. Leave empty to run a small demo on a public post.

## `maxCommentsPerPost` (type: `integer`):

Hard cost ceiling per post — each comment returned is one paid event, and a reply is a comment. A post with 30,000 comments costs 30,000 events unless you cap it here. 0 = no cap, paid plans only. Free plan ceiling: 50 comments per run, from up to 3 post links. Default 1000.

## `includeReplies` (type: `boolean`):

Read the replies under each comment and return them as their own rows, marked as replies and carrying the comment they answer. Replies are billed like any other comment. Posts with reply threading switched off are detected before any reply call is made, so this costs nothing on them.

## `includeCommentLikers` (type: `boolean`):

Add the accounts that liked each comment. This is a separate, cheaper paid event and is off by default because it multiplies the work: a post with 1,000 comments means up to 1,000 extra lookups. Posts with comment likes switched off are detected first and cost nothing.

## `maxLikersPerComment` (type: `integer`):

How deep to read each comment's liker list. Instagram serves them 50 at a time. Only used when the option above is on. Default 50.

## `postedAfter` (type: `string`):

Keep only comments (and replies) posted on or after this moment, by the comment's own time in UTC. A date such as 2026-10-01 means from the start of that day; a span such as "7 days" or "3 weeks" counts back from when the run starts. Comments outside the range are read past and not charged, and do not count toward "Max comments per post". Leave empty for no start date.

## `postedBefore` (type: `string`):

Keep only comments posted on or before this moment, UTC. A date such as 2026-10-31 includes the whole of that day; a span such as "1 week" counts back from when the run starts. A reply is only looked for under a comment inside the range. Leave empty for no end date.

## `skipDelivered` (type: `string`):

Leave out comments and replies this Actor already delivered to your Apify account in an earlier run. Skipped comments are not charged and do not count toward "Max comments per post"; the run reads on for new ones. A new reply under a comment you have still comes back. From the API: any number of days, e.g. "45". The record is a key-value store named ig-delivered-… in your Storage; delete it to start over. Runs that overlap in time may still share a comment.

## `clearSavedData` (type: `boolean`):

Check this to clear saved data from previous runs and start clean. Uncheck to resume a previous run from where it left off.

## Actor input object example

```json
{
  "postUrls": [],
  "maxCommentsPerPost": 1000,
  "includeReplies": true,
  "includeCommentLikers": false,
  "maxLikersPerComment": 50,
  "skipDelivered": "off",
  "clearSavedData": true
}
```

# Actor output Schema

## `liveStatus` (type: `string`):

No description

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

No description

## `runSummary` (type: `string`):

No description

## `commentCoverage` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("afanasenko/instagram-comments-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("afanasenko/instagram-comments-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 '{}' |
apify call afanasenko/instagram-comments-scraper --silent --output-dataset

```

## MCP server setup

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