# Instagram Comments Scraper by Post URL: Text, Likes, Authors (`neverempty/instagram-post-comments-scraper`) Actor

This Instagram comments scraper takes post and reel URLs and returns one row per comment: text, likes, date, author username, profile link, verified badge, GIF link and mentions. Filter by date, set a limit per post. No login, no cookies, no start fee. You pay only for comments returned.

- **URL**: https://apify.com/neverempty/instagram-post-comments-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Social media, Automation
- **Features:** Limited permissions
- **Stats:** 12 total users, 8 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.65 / 1,000 comment returneds

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 by Post URL: Text, Likes, Authors

For sentiment analysis, giveaway picking and competitor research: this Instagram comments scraper takes post and reel URLs and returns one row per comment (text, likes, date, mentions, GIF link, and the commenter's username, profile link and verified badge) as CSV, Excel or JSON. No login, no cookies, no start fee. Free plan runs read as deep as paid plans, up to your `maxCommentsPerPost` (500 by default), not just the first 15. You pay **$2.50 per 1,000 comments** on the Free plan, down to **$1.65** on Gold and above, and only for comments returned.

### What can I do with this Instagram comments scraper?

- **Read what people say about a post.** Collect the comments on your own posts, a campaign or a competitor's launch, and sort them by likes to see what stands out.
- **Run sentiment analysis and topic research.** Get clean comment text with dates and likes, ready for a spreadsheet, an AI model or a dashboard.
- **Pick giveaway entrants.** Get the usernames and profile links of people who commented, and the accounts they tagged in `mentions`.
- **Check reels and carousels too.** Reels, video posts, image posts and carousels all work with the same input.
- **Follow up on new comments only.** Set `onlyNewerThan` to `7 days` and pay only for recent comments.

### What data do you get?

| Group | Fields |
|---|---|
| Comment | `commentId`, `position`, `text`, `commentType` (text, gif, no-text), `gifUrl`, `likesCount`, `createdAt`, `createTime`, `mentions`, `isCovered` |
| Commenter | `authorUsername`, `authorProfileUrl`, `authorIsVerified`, `authorProfilePicUrl` |
| Post | `postUrl`, `postShortCode`, `postId`, `postOwnerUsername`, `postCommentCount`, `inputUrl` |
| Run | `status`, `note`, `source`, `scrapedAt`. The last row can also hold `notCheckedUrls` (URLs to put in a new run) |

`position` is the place of the comment in the list Instagram showed for that post, starting at 1. `postCommentCount` is the comment count Instagram shows on the post.

### How to scrape Instagram comments from a post URL

1. Paste your post and reel URLs into `urls`. Links with tracking parameters, `/reels/` links, links with the username in the path and bare shortcodes all work. `directUrls` and `postUrls` are accepted as other names for `urls`.
2. Set `maxCommentsPerPost` to the most comments you want from each post.
3. If you only want recent comments, set `onlyNewerThan` to a date such as `2026-10-01` or a span such as `7 days`.
4. Press **Start**, then download the rows as JSON, CSV or Excel, or read them through the API.

### Input

| Field | What it does | Default |
|---|---|---|
| `urls` | Instagram post and reel URLs, one per line. Up to 1,000 are read per run. | One free sample post when no URLs are given |
| `maxCommentsPerPost` | Reading a post stops after this many comment rows (1 to 100,000). | 500 |
| `onlyNewerThan` | Return only comments newer than a date (`2026-10-01`) or a span back from now (`12 hours`, `7 days`, `2 weeks`, `3 months`). Older comments are skipped and not charged. | Empty (any date) |

```json
{
    "urls": [
        "https://www.instagram.com/p/DeuOR-CjKE9/",
        "https://www.instagram.com/reel/DeTUk4sDSp-/"
    ],
    "maxCommentsPerPost": 500,
    "onlyNewerThan": "30 days"
}
```

### Output example

```json
{
    "status": "ok",
    "inputUrl": "https://www.instagram.com/reel/DeTUk4sDSp-/",
    "postUrl": "https://www.instagram.com/reel/DeTUk4sDSp-/",
    "postShortCode": "DeTUk4sDSp-",
    "postId": "4004634989362489982",
    "postOwnerUsername": "nasa",
    "postCommentCount": 7655,
    "commentId": "18085123456789012",
    "position": 1,
    "text": "This view never gets old @space_fan",
    "commentType": "text",
    "gifUrl": null,
    "likesCount": 412,
    "createdAt": "2026-10-12T15:04:31.000Z",
    "createTime": 1791817471,
    "mentions": ["space_fan"],
    "authorUsername": "orbit.watcher",
    "authorProfileUrl": "https://www.instagram.com/orbit.watcher/",
    "authorIsVerified": false,
    "authorProfilePicUrl": "https://scontent.cdninstagram.com/v/...",
    "isCovered": false,
    "source": "instagram-comment",
    "scrapedAt": "2026-10-31T09:12:44.000Z"
}
```

The comment, IDs and counts in this example are made up to show the shape of a row.

### How much does it cost?

**$2.50 per 1,000 comments** on the Free plan, with lower prices on paid Apify plans:

| Apify plan | Price per 1,000 comments |
|---|---|
| Free | $2.50 |
| Bronze | $2.20 |
| Silver | $1.95 |
| Gold and above | $1.65 |

There is no start fee and no charge per post. You are charged only for rows with `status: "ok"`, and each comment is returned once per run. Every other row is free, and the [list is below](#rows-you-are-not-charged-for).

To keep a run inside a budget, set `maxCommentsPerPost`, or set a maximum total charge when you start the run. The run stops at that amount and says so in a `budget-reached` row.

### FAQ

**How do I export Instagram comments to Excel or CSV?**
Paste the post URL into `urls` and run the Actor. When the run ends, open the **Output** tab and download the dataset as CSV or Excel. Each comment is one row.

**Can I scrape Instagram comments without logging in?**
Yes. You don't need an Instagram account, a cookie or an API key.

**How many comments can I get from one post?**
As many as Instagram lists for that post to visitors who are not logged in, up to your `maxCommentsPerPost`. This is usually fewer than the count shown on the post, on small posts too; see [Limitations](#limitations).

**Do I get the same depth on the Free plan?**
Yes. Free and paid plans read to the same depth, up to your `maxCommentsPerPost`. Only the price per 1,000 comments changes.

**Can I scrape comments from Instagram reels?**
Yes. Use the reel URL, such as `https://www.instagram.com/reel/DeTUk4sDSp-/`. Reels and posts return the same fields.

**Can I run this from an API or an AI agent?**
Yes. Call the Actor through the Apify API, or from an AI agent through the Apify MCP server, with a list of URLs. The rows come back as JSON.

**How do I scrape comments from many posts at once?**
Paste a list of URLs (the limit is 1,000 per run). Every post the run reaches returns the comments Instagram lists for it, or one free row that says why there are none. If Instagram stops answering, the run ends early, and the posts it did not reach are listed in `notCheckedUrls` in the last row, ready for a new run a few hours later.

**What happens if a run reaches its timeout?**
The run stops about 90 seconds before its timeout. Comments already returned stay in the dataset. A post that was cut short gets a `stopped-reading` row, and posts it did not start are listed in `notCheckedUrls` in the last row. To read them, start a new run with those URLs, or set a longer timeout.

**Why is `text` empty on some rows?**
`commentType` tells you why. `gif` means the comment is a GIF, and `gifUrl` links to it. `no-text` means Instagram gave the comment without text or a GIF. These rows are still real comments and are charged like any other.

### Rows you are not charged for

A post that was read but did not return comments gets its own row, so you can see what happened to it. Posts the run did not check (past the 1,000 URL limit, past the maximum total charge, stopped because Instagram refused most requests, or stopped before the run timeout) are counted in one last row, and `notCheckedUrls` lists them for a new run.

| `status` | What it means |
|---|---|
| `sample` | No URLs were given, so up to 20 comments of one sample post were read to show the output. Add your own URLs to `urls`. |
| `no-public-post` | Instagram shows no public post at this address. It may be deleted, private, not shown in the country the run connects from, or mistyped. |
| `comments-not-shown` | Instagram shows the post but lists no comments to visitors who are not logged in, for example because comments are turned off. The row still has the post's details. |
| `no-comments-listed` | The post has no comments listed, or none newer than `onlyNewerThan`. |
| `max-comments-reached` | `maxCommentsPerPost` comments were returned and Instagram showed that the post may list more. Raise the limit to read further. |
| `stopped-reading` | Reading stopped part way, because Instagram did not answer the next page or the run was about to reach its timeout. The comments before that point are in the dataset. |
| `blocked` | Instagram did not let this run open the post. Run the URL again later. |
| `unreadable` | The page loaded, but the comment data was not in the expected form. Nothing is guessed. |
| `invalid-input` | The entry is not an Instagram post or reel URL, such as a profile link. For a `/share/` link, open the link and paste the URL of the post. |
| `duplicate` | The same post was already in this run's list. |
| `not-checked` | One row at the end: how many posts were not read and why. The URLs are in `notCheckedUrls`. |
| `budget-reached` | The run reached the maximum total charge you set. Comments that did not fit are not in the dataset and were not charged. |

### Limitations

- The Actor returns the comments Instagram lists to visitors who are not logged in. This is usually fewer than the count shown on the post (`postCommentCount`). In our tests, posts with about 1,200 to 10,000 comments returned 38% to 80% of that count, and posts with 15 or fewer comments returned 75% of it in total. The list can also change between runs: one post with a count of 240 listed 30 comments in one run and 145 in a run a day later.
- Only comments directly under the post are returned. Answers posted under another comment are not in the output.
- Comments come in the order Instagram lists them, which was newest first in every post we checked. No other sort order can be chosen.
- The commenter's full name and whether their account is private are not shown without a login, so they are not in the output. Numeric account IDs are not collected.
- Only public posts can be read. Private accounts and deleted posts return a free `no-public-post` row.
- On long lists Instagram may stop answering, so the run can end early. The rest are not charged and are listed in `notCheckedUrls`.
- Picture and GIF URLs come from Instagram's CDN and expire after a while, so download the files soon after the run.
- Email addresses and phone numbers in comment text are masked on a best-effort basis. Not every way of writing them can be caught, so some may remain. Masking can also go too far: a long number such as a reference code may be masked as well.
- Use the data in line with the rules that apply to you, including privacy law for the personal data in comments.

### Need help or a missing field?

Open the **Issues** tab and tell us what you need. If a row looks wrong, include the run ID.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `urls` (type: `array`):

Instagram post or reel addresses, one per line, such as https://www.instagram.com/p/DeuOR-CjKE9/ or https://www.instagram.com/reel/DeTUk4sDSp-/. A bare shortcode also works. Up to 1,000 per run. Several posts are read at the same time.

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

Reading a post stops after this many comment rows. The charge follows the comment rows returned.

## `onlyNewerThan` (type: `string`):

Leave empty to return comments of any date. Otherwise a date such as 2026-10-01, or a span back from now such as 7 days, 2 weeks, 3 months or 12 hours. Older comments are skipped and not charged.

## Actor input object example

```json
{
  "urls": [
    "https://www.instagram.com/p/DeuOR-CjKE9/",
    "https://www.instagram.com/reel/DeTUk4sDSp-/"
  ],
  "maxCommentsPerPost": 500
}
```

# Actor output Schema

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

One row per Instagram comment: text, likes, date, author username, profile link, verified badge, profile picture, GIF link, mentions and the post it belongs to. URLs that show no public post, posts without listed comments and limits come back as free rows that say why.

# 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 = {
    "urls": [
        "https://www.instagram.com/p/DeuOR-CjKE9/",
        "https://www.instagram.com/reel/DeTUk4sDSp-/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/instagram-post-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 = { "urls": [
        "https://www.instagram.com/p/DeuOR-CjKE9/",
        "https://www.instagram.com/reel/DeTUk4sDSp-/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/instagram-post-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 '{
  "urls": [
    "https://www.instagram.com/p/DeuOR-CjKE9/",
    "https://www.instagram.com/reel/DeTUk4sDSp-/"
  ]
}' |
apify call neverempty/instagram-post-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/instagram-post-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/4EfPi3wKALj6YYeke/builds/IcYbbvklS2Sdocpvq/openapi.json
