# ❤️💬 Instagram Likes Scraper with Comments (`scraperforge/instagram-likes-scraper`) Actor

📸 Instagram Likes Scraper extracts like lists from posts & Reels — usernames, user IDs, profile links, timestamps & engagement insights. 🔎 Export CSV/JSON, dedupe, and monitor changes. 🚀 Ideal for growth, analytics, competitor tracking & influencer research.

- **URL**: https://apify.com/scraperforge/instagram-likes-scraper.md
- **Developed by:** [ScraperForge](https://apify.com/scraperforge) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 23 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Instagram Likes Scraper with Comments — Likers, Commenters, Comment Text & Reply Threads

Extract **everyone who engaged with an Instagram post** — the people who liked it, the people who commented, and **what they actually wrote** — including reply threads, comment timestamps, comment like counts, tagged usernames and hashtags.

One combined dataset with a `row_type` column, so likers, commenters and replies arrive in a single flat table you can filter.

***

### What is Instagram Likes Scraper with Comments?

Most Instagram like scrapers return a list of usernames. That tells you *who* engaged, but not *why they mattered*.

This Actor returns both sides of engagement in one run:

- **Likers** — the full liker list from a post or Reel, with username, user ID, full name, verified and private flags, and profile picture.
- **Commenters** — the same identity fields, **plus the comment itself**: text, UTC timestamp, like count, tagged usernames, hashtags and whether it has replies.
- **Replies** — the child comments underneath, each as its own row with a `parent_comment_id` linking it back to the thread.

Every row carries an identical column set, with `row_type` (`liker` / `commenter` / `reply`) and `is_child` telling you which kind it is. That means a CSV export opens cleanly in a spreadsheet — no merging, no unnesting, no separate exports to reconcile.

Rows are saved live as they are collected, so an interrupted run still leaves you with everything gathered up to that point.

***

### What data can you extract?

#### 👤 Person fields (on every row)

| Field | Description |
| --- | --- |
| `username` | Instagram handle |
| `id` | Instagram user ID |
| `full_name` | Display name |
| `is_verified` | Blue-check flag |
| `is_private` | Private account flag |
| `is_new` | Instagram's new-user flag |
| `profile_pic_url` | Profile picture URL |
| `profile_pic_id` | Profile picture identifier |
| `latest_reel_media` | Latest story/reel media marker |
| `latest_reel_media_utc` | Timestamp for that marker |

#### 💬 Comment fields (populated on commenter and reply rows)

| Field | Description |
| --- | --- |
| `comment_text` | The full comment |
| `comment_id` | Comment identifier |
| `comment_url` | Direct link to the comment |
| `comment_created_at_utc` | UTC timestamp of the comment |
| `comment_like_count` | Likes on the comment |
| `child_comment_count` | Number of replies underneath |
| `has_replies` | Whether the comment has a thread |
| `tagged_usernames` | `@mentions` parsed from the text |
| `hashtags` | Hashtags parsed from the text |
| `is_covered` | Instagram's covered/hidden flag |

#### 🏷️ Row and post fields

| Field | Description |
| --- | --- |
| `row_type` | `liker`, `commenter` or `reply` |
| `is_child` | `true` on reply rows |
| `parent_comment_id` | The comment a reply belongs to |
| `post_url` / `liked_post` | The post this row came from |
| `total_likes` | Total likes on the post |
| `total_comments` | Total comments on the post |
| `comments_fetched_ratio` | What share of the comments this run covered |
| `scraped_at` | UTC time the row was collected |

On liker rows the comment fields are present but `null`, keeping the column set consistent across the whole export.

***

### Why teams scrape Instagram engagement

#### For influencer vetting

A liker list shows reach; comment text shows whether the audience is real. Twenty "🔥🔥" comments from the same pod read very differently from twenty questions about the product. `comments_fetched_ratio` tells you how much of the conversation you actually sampled.

#### For lead generation

People who comment questions on a competitor's product post are in-market right now. Filter `comment_text` for "price", "link", "where", "DM" and you have a qualified list with usernames attached.

#### For audience research

`hashtags` and `tagged_usernames` parsed out of comment text show what your audience associates with your content and who they pull into the conversation.

#### For growth analytics

Run the same post twice and diff on `id` to see who newly engaged. Compare `total_likes` against the likers you can actually retrieve to understand your real reachable audience.

#### For competitor tracking

Their commenters are your prospects. The reply threads show how they handle objections in public.

#### For community management

Reply rows with `parent_comment_id` reconstruct whole threads, so you can find the conversations that went unanswered.

***

### How to scrape likes and comments step by step

1. Copy the Instagram post or Reel URLs you want (e.g. `https://www.instagram.com/p/XXXXX/`).
2. Paste them into **Instagram Post URLs** — one per line, as many as you need.
3. Get your **Instagram session ID**: browser DevTools → Application → Cookies → `instagram.com` → `sessionid`. Paste it into **Instagram session ID**. This is required in practice — see the note below.
4. Set **Max users to collect** and **Max comments per post**.
5. Choose a **Comment sort order** (`popular` or `recent`) and set **Max replies per comment**.
6. Click **Start**, then export the **Output** tab as CSV, Excel or JSON.

> **The session ID is not optional in practice.** Instagram now serves a login-wall page to anonymous requests on the likers, comments and reply endpoints. Without a `sessionid`, runs will come back empty. Use an account you are comfortable using for this purpose.

***

### ⬇️ Input

#### Example input

```json
{
  "startUrls": [
    "https://www.instagram.com/p/DLm63qQpxvw/"
  ],
  "maxCount": 500,
  "maxCommentsPerPost": 200,
  "commentSortOrder": "popular",
  "includeReplies": true,
  "maxRepliesPerComment": 5,
  "sessionId": "<YOUR_INSTAGRAM_SESSIONID>"
}
```

#### Input reference

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | array | — (**required**) | Instagram post or Reel URLs. Likers, commenters and full comment content are collected from each. |
| `maxCount` | integer | `100` | Cap on unique **top-level users** (likers + commenters) across all posts, 1–10,000. Reply authors are not counted against it. |
| `maxCommentsPerPost` | integer | `100` | How many top-level comments to fetch full detail for, per post, 1–10,000. A **separate budget** from `maxCount`. |
| `commentSortOrder` | string | `popular` | How comments are ranked before the cap is applied. `popular` — highest like count first. `recent` — newest first. Sorted locally, because Instagram does not reliably honour a server-side sort. |
| `includeReplies` | boolean | `true` | Fetch reply threads for comments that have them. Adds extra requests per post. |
| `maxRepliesPerComment` | integer | `5` | Replies fetched per comment, 0–50. Replies are extra rows and are **not** counted against `maxCount`. |
| `sessionId` | string | `""` | Your Instagram `sessionid` cookie. Required in practice — anonymous requests hit a login wall. |
| `proxyConfiguration` | object | off | Optional. Leave off for direct requests; if Instagram blocks you the Actor **auto-escalates: direct → datacenter → residential**, with retries. |

> **The two budgets are independent.** `maxCommentsPerPost: 10` with `maxRepliesPerComment: 3` yields up to 10 comments and up to 30 replies per post, regardless of `maxCount`.

***

### ⬆️ Output

#### Example output — liker row

```json
{
  "row_type": "liker",
  "is_child": false,
  "username": "example_user",
  "id": "1234567890",
  "full_name": "Example User",
  "is_verified": false,
  "is_private": false,
  "profile_pic_url": "https://scontent.cdninstagram.com/%E2%80%A6",
  "post_url": "https://www.instagram.com/p/DLm63qQpxvw/",
  "liked_post": "https://www.instagram.com/p/DLm63qQpxvw/",
  "total_likes": 18420,
  "comment_text": null,
  "comment_like_count": null,
  "parent_comment_id": null,
  "scraped_at": "2026-08-10T09:14:02.000Z"
}
```

#### Example output — commenter row

```json
{
  "row_type": "commenter",
  "is_child": false,
  "username": "another_user",
  "id": "9876543210",
  "full_name": "Another User",
  "is_verified": true,
  "comment_id": "17900112233445566",
  "comment_url": "https://www.instagram.com/p/DLm63qQpxvw/c/17900112233445566",
  "comment_text": "Where can I buy this? @mybestie you need it 🔥 #musthave",
  "comment_created_at_utc": "2026-08-09T18:44:10.000Z",
  "comment_like_count": 214,
  "child_comment_count": 3,
  "has_replies": true,
  "tagged_usernames": ["mybestie"],
  "hashtags": ["musthave"],
  "total_comments": 1840,
  "comments_fetched_ratio": 0.108,
  "post_url": "https://www.instagram.com/p/DLm63qQpxvw/"
}
```

#### Example output — reply row

```json
{
  "row_type": "reply",
  "is_child": true,
  "parent_comment_id": "17900112233445566",
  "username": "brand_official",
  "comment_id": "17900998877665544",
  "comment_url": "https://www.instagram.com/p/DLm63qQpxvw/c/17900112233445566/r/17900998877665544",
  "comment_text": "Link is in our bio! 💛",
  "comment_created_at_utc": "2026-08-09T19:02:55.000Z",
  "comment_like_count": 12,
  "has_replies": false
}
```

*Illustrative values — a live run returns current Instagram data.*

***

### Usage recipes

#### Find buying intent in a competitor's comments

```json
{
  "startUrls": ["https://www.instagram.com/p/COMPETITOR_POST/"],
  "maxCommentsPerPost": 500,
  "commentSortOrder": "recent",
  "includeReplies": true
}
```

Filter `comment_text` for "price", "link", "where", "how much", "DM". Those usernames are in-market.

#### Vet an influencer before you pay them

Run one of their recent posts, then compare `total_likes` against the depth of `comment_text`. Generic one-word comments at scale are the classic engagement-pod signature.

#### Rebuild whole comment threads

Group by `parent_comment_id`: the `commenter` row is the parent, every `reply` row beneath it is the thread, ordered by `comment_created_at_utc`.

#### Likers only, fast

```json
{
  "startUrls": ["https://www.instagram.com/p/YOUR_POST/"],
  "maxCount": 900,
  "maxCommentsPerPost": 1,
  "includeReplies": false
}
```

#### Track who newly engaged

Run the same post on a schedule and diff on `id`. New IDs are new engagers, and `scraped_at` timestamps each pass.

#### Map the conversation vocabulary

Aggregate `hashtags` and `tagged_usernames` across a set of posts to see what your audience associates with your content.

***

### How does this compare to Instagram's official API?

The **Instagram Graph API** does not offer this. Liker identities are not exposed at all — you can read a like *count*, never the list of people. Comment reading is limited to accounts you own or manage, requires a Business or Creator account linked to a Facebook Page, an approved app, and a review process — and it still cannot show you a competitor's engagers.

This Actor reads **publicly visible engagement** through the same session a logged-in user has, which is the only route to liker lists and third-party comment data.

***

### Integrate and automate

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_API_TOKEN>")

run = client.actor("scraperforge/instagram-likes-scraper").call(run_input={
    "startUrls": ["https://www.instagram.com/p/DLm63qQpxvw/"],
    "maxCount": 500,
    "maxCommentsPerPost": 200,
    "sessionId": "<YOUR_INSTAGRAM_SESSIONID>",
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["row_type"] != "liker":
        print(row["row_type"], "|", row["username"], "|", row["comment_text"])
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_API_TOKEN>' });

const run = await client.actor('scraperforge/instagram-likes-scraper').call({
    startUrls: ['https://www.instagram.com/p/DLm63qQpxvw/'],
    maxCount: 500,
    sessionId: '<YOUR_INSTAGRAM_SESSIONID>',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.row_type === 'commenter'));
```

#### REST API

```bash
curl -X POST "https://api.apify.com/v2/acts/scraperforge~instagram-likes-scraper/runs?token=%3CYOUR_APIFY_API_TOKEN%3E" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":["https://www.instagram.com/p/DLm63qQpxvw/"],"maxCount":500,"sessionId":"<YOUR_INSTAGRAM_SESSIONID>"}'
```

#### n8n, Make, Zapier and AI agents

Call the Actor from **n8n**, **Make**, **Zapier** or an MCP-capable agent — a common pattern is comments → LLM intent classification → CRM.

#### Schedules and webhooks

Attach a **Schedule** to re-run key posts and deduplicate on `id` (or `comment_id`), then route results with **webhooks** or the **Google Sheets / Airtable / Slack** integrations.

***

### Pricing and what you are charged for

This Actor is a **flat monthly rental**: one fixed price per month, with no per-result charge. Run as many posts as you need within the platform's usage limits.

The current monthly price is on the **Pricing** tab of this Actor's page. Apify platform usage (compute units, and residential proxy traffic if the automatic escalation kicks in) is billed separately.

***

### Limits, reliability and blocking

- **A session ID is required in practice.** Instagram serves a login wall to anonymous requests on the likers, comments and reply endpoints.
- **Instagram caps liker retrieval.** The `likers_chrono` endpoint typically stops returning new likers after roughly **950 per post**, regardless of `maxCount`. A post with 50,000 likes will not yield 50,000 likers — no tool can change that.
- **`total_likes` and `total_comments` are the post's real totals**, so comparing them against your row count shows exactly how much you covered. `comments_fetched_ratio` states it directly.
- **Comment sorting is applied locally** before the cap, because Instagram does not reliably honour a server-side sort order.
- **Replies cost extra requests**, so `includeReplies: true` on a large comment budget makes runs noticeably longer. Set `maxRepliesPerComment: 0` or turn replies off to speed things up.
- **Reply authors bypass `maxCount`** by design — they are child rows budgeted only by `maxRepliesPerComment`.
- **Proxy escalation is automatic**: direct → datacenter → residential with retries, then it stays on residential.
- **Private posts are not accessible**, and hidden or filtered comments may not appear.
- **Profile picture URLs expire** — they point at Instagram's CDN.
- Default run options are 4 GB memory and a 1-hour timeout.

***

### Is it legal to scrape Instagram likes and comments?

This Actor collects **publicly visible engagement** on public posts — the likes and comments any logged-in user can see by opening the post.

Usernames, full names, profile pictures and comment text are **personal data** under GDPR and comparable laws. Have a lawful basis before you process them, keep only what you need, honour deletion requests, and do not use the output for unsolicited bulk DMs or spam. Comment text belongs to its author. Comply with Instagram's Terms of Use, and note that supplying a session ID means acting as that account.

***

### ❓ Frequently asked questions

#### Do I really need an Instagram session ID?

Yes, in practice. Instagram serves a login-wall page to anonymous requests on these endpoints, so runs without a `sessionid` come back empty.

#### Where do I find my session ID?

Browser DevTools → Application → Cookies → `instagram.com` → the `sessionid` value.

#### Why did I get far fewer likers than the post has likes?

Instagram's likers endpoint typically stops returning new results after around 950 per post. That is a platform limit, not an Actor setting.

#### What is `row_type` for?

It labels each row: `liker`, `commenter` or `reply`. Filter on it to split the export into the three kinds of engagement.

#### Do replies count against my user limit?

No. Replies are child rows budgeted only by `maxRepliesPerComment`; `maxCount` counts top-level users.

#### How do I rebuild a thread?

Match `reply` rows to their parent via `parent_comment_id`, and order by `comment_created_at_utc`.

#### Does `commentSortOrder` change what Instagram sends?

No — sorting is applied locally before the cap, because Instagram does not reliably honour a server-side sort.

#### Does it work on Reels?

Yes. Reel URLs are supported alongside standard post URLs.

#### Do I need a proxy?

Not to begin with. If Instagram blocks you the Actor escalates on its own: direct → datacenter → residential.

#### Which export format should I use?

CSV or Excel works well because the column set is consistent across row types. Use JSON if you want `tagged_usernames` and `hashtags` as real arrays.

***

### 🔗 Related scrapers

- [Facebook Group Posts and Details Scraper with Comments](https://apify.com/scraperforge/facebook-group-posts-and-details-scraper) — the same engagement question on Facebook.
- [Youtube Community Posts Scraper](https://apify.com/scraperforge/youtube-community-posts-scraper) — likes, comment counts and polls from YouTube.
- [X Posts Scraper (Twitter)](https://apify.com/scraperforge/Twitter-X-Posts-Scraper) — engagement metrics including views and bookmarks.
- [TikTok Trending Creator Insights Scraper](https://apify.com/scraperforge/tiktok-trending-creator-insights-scraper) — creator-level engagement for influencer vetting.

Browse the full collection on the [ScraperForge profile](https://apify.com/scraperforge).

***

### 💬 Feedback

Need deeper reply threads, comment-only output, or a custom engagement pipeline? Open an issue on the **Issues** tab of this Actor.

# Actor input Schema

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

🔗 Paste one or more Instagram post URLs (e.g. https://www.instagram.com/p/XXXXX/). Likers, commenters and full comment content are collected from each.

## `maxCount` (type: `integer`):

📈 Cap on unique top-level users (likers + commenters) across all posts. Reply authors are NOT counted against this cap (see 'Max replies per comment'). 1–10,000. Default: 100. Note: Instagram's likers\_chrono endpoint typically stops returning new likers after ~950 per post regardless of this setting.

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

📝 How many top-level comments to fetch full detail for (text, timestamp, like count, tagged users, hashtags) per post — a separate budget from 'Max users to collect'. Example: maxCommentsPerPost=10 + maxRepliesPerComment=3 → up to 10 comments and up to 30 replies per post. 1–10,000. Default: 100.

## `commentSortOrder` (type: `string`):

Order comments are ranked before the 'Max comments per post' cap is applied. Sorted locally (Instagram does not reliably honor a server-side sort). 'Most popular' = highest like count first. 'Most recent' = newest first.

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

Fetch reply threads for comments that have them (child\_comment\_count > 0). Adds extra requests per post. Default: true.

## `maxRepliesPerComment` (type: `integer`):

Cap on how many replies are fetched per comment when 'Include comment replies' is on. Replies are additional rows and are NOT counted against 'Max users to collect'. 0–50. Default: 5.

## `sessionId` (type: `string`):

Paste your Instagram sessionid cookie value (browser DevTools → Application → Cookies → instagram.com → sessionid). Required in practice — Instagram now serves a login-wall page to anonymous requests on the likers, comments and reply endpoints.

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

🛡️ Leave off for direct requests. If Instagram blocks you, the actor auto-escalates: direct → datacenter → residential (with retries).

## Actor input object example

```json
{
  "startUrls": [
    "https://www.instagram.com/p/DLm63qQpxvw/"
  ],
  "maxCount": 100,
  "maxCommentsPerPost": 100,
  "commentSortOrder": "popular",
  "includeReplies": true,
  "maxRepliesPerComment": 5,
  "sessionId": "",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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/p/DLm63qQpxvw/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraperforge/instagram-likes-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/p/DLm63qQpxvw/"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scraperforge/instagram-likes-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/p/DLm63qQpxvw/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scraperforge/instagram-likes-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraperforge/instagram-likes-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/0P8JDGPcebqEASwcX/builds/MPlDNGRN2VfyPs6hL/openapi.json
