Back to all posts

How to Scrape Instagram Comments (2026 Guide)

Jonathan Geiger
Instagram APIComment ExtractionInstagram ScrapingSocial Media AnalyticsData Extraction

Need to extract Instagram post and reel comments programmatically? Whether you're building sentiment analysis tools, influencer vetting platforms, community management dashboards, or social listening systems, getting reliable Instagram comment data is essential.

In this guide, we'll show you the easiest way to scrape Instagram comments using the Instagram Comments API. No proxies, no Puppeteer, no scraping infrastructure required. Includes cursor-based pagination so you can walk the full comment thread on viral content.

What Data Can You Extract?

The Instagram Comments API provides comprehensive comment information:

  • Comment Content - Full comment text with emoji support
  • Author Information - Username, full name, profile picture URL
  • Verification Badges - Each comment includes the commenter's verified flag
  • Engagement Metrics - Like counts and reply counts per comment
  • Cursor Pagination - Walk thousands of comments on viral posts
  • Sort Options - popular (default) or recent ordering
  • Multi-Format URLs - Works with /p/, /reel/, /reels/, and /tv/

The Easy Way: Instagram Comments API

The simplest and most reliable method is using the Instagram Comments API. Here's why:

No Infrastructure Needed - No proxies, browsers, or anti-bot systems
Always Up-to-Date - API automatically handles Instagram changes
Cursor Pagination - Walk every comment on viral posts reliably
Fast & Reliable - Get comment data in seconds
Simple Integration - Just one API call with an Instagram URL
Structured Data - Clean JSON response ready for your application

API Endpoint

https://api.socialkit.dev/instagram/comments

Parameters

ParameterTypeRequiredDescription
urlstringYesInstagram post or reel URL (/p/, /reel/, /reels/, /tv/)
access_keystringYesYour API access key
limitnumberNoComments per request (max 100, default 10)
cursorstringNoCursor from a previous response to fetch the next page
sortBystringNopopular (default) or recent

Example Request

GET https://api.socialkit.dev/instagram/comments?access_key=<your-access-key>&url=https://www.instagram.com/reel/DRU4smMj0cu/&limit=20

Example Response

{
  "success": true,
  "data": {
    "url": "https://www.instagram.com/reel/DRU4smMj0cu/",
    "postUrl": "https://www.instagram.com/p/DRU4smMj0cu/",
    "shortcode": "DRU4smMj0cu",
    "commentCount": 486,
    "comments": [
      {
        "id": "17910074922340073",
        "username": "risfankhiyarulmizan",
        "fullName": "",
        "profilePicUrl": "https://scontent.cdninstagram.com/...",
        "verified": false,
        "text": "😂😂😂😂😂😂😂",
        "likes": 0,
        "replyCount": 0,
        "date": "11-21-2025",
        "timestamp": 1763744973,
        "parentCommentId": null
      },
      {
        "id": "18053470208695411",
        "username": "safiyabai",
        "fullName": "",
        "profilePicUrl": "https://scontent.cdninstagram.com/...",
        "verified": false,
        "text": "😍❤️❤️❤️",
        "likes": 12,
        "replyCount": 0,
        "date": "11-21-2025",
        "timestamp": 1763744981,
        "parentCommentId": null
      }
    ],
    "limit": 20,
    "hasMore": true,
    "cursor": "{\"server_cursor\": \"QVF...\", \"is_server_cursor_inverse\": true}"
  }
}

Code Examples

JavaScript / Node.js

const axios = require('axios');

async function getInstagramComments(postUrl, accessKey, options = {}) {
  const params = {
    access_key: accessKey,
    url: postUrl,
    limit: options.limit || 50,
  };
  if (options.cursor) params.cursor = options.cursor;
  if (options.sortBy) params.sortBy = options.sortBy; // 'popular' or 'recent'

  const response = await axios.get(
    'https://api.socialkit.dev/instagram/comments',
    { params }
  );
  return response.data;
}

// Usage
const postUrl = 'https://www.instagram.com/reel/DRU4smMj0cu/';
const accessKey = 'your-access-key';

getInstagramComments(postUrl, accessKey, { limit: 50 }).then((data) => {
  console.log(`Total comments on post: ${data.data.commentCount}`);
  console.log(`Returned in this page: ${data.data.comments.length}`);

  data.data.comments.forEach((c) => {
    const badge = c.verified ? ' ✓' : '';
    console.log(`\n@${c.username}${badge}: ${c.text}`);
    console.log(`  Likes: ${c.likes} | Replies: ${c.replyCount}`);
  });

  if (data.data.hasMore) {
    console.log(`\nNext cursor: ${data.data.cursor.slice(0, 60)}...`);
  }
});

Python

import requests

def get_instagram_comments(post_url, access_key, limit=50, cursor=None, sort_by=None):
    endpoint = 'https://api.socialkit.dev/instagram/comments'
    params = {'access_key': access_key, 'url': post_url, 'limit': limit}
    if cursor: params['cursor'] = cursor
    if sort_by: params['sortBy'] = sort_by  # 'popular' or 'recent'

    response = requests.get(endpoint, params=params)
    response.raise_for_status()
    return response.json()

# Usage
post_url = 'https://www.instagram.com/reel/DRU4smMj0cu/'
access_key = 'your-access-key'

data = get_instagram_comments(post_url, access_key, limit=50)
print(f"Total on post: {data['data']['commentCount']}")
print(f"Returned: {len(data['data']['comments'])}")

for c in data['data']['comments']:
    badge = ' ✓' if c['verified'] else ''
    print(f"\n@{c['username']}{badge}: {c['text']}")
    print(f"  Likes: {c['likes']:,} | Replies: {c['replyCount']}")

PHP

<?php

function getInstagramComments($postUrl, $accessKey, $limit = 50, $cursor = null, $sortBy = null) {
    $params = [
        'access_key' => $accessKey,
        'url' => $postUrl,
        'limit' => $limit,
    ];
    if ($cursor) $params['cursor'] = $cursor;
    if ($sortBy) $params['sortBy'] = $sortBy;

    $url = 'https://api.socialkit.dev/instagram/comments?' . http_build_query($params);
    $response = file_get_contents($url);
    return json_decode($response, true);
}

$data = getInstagramComments(
    'https://www.instagram.com/reel/DRU4smMj0cu/',
    'your-access-key',
    50
);
foreach ($data['data']['comments'] as $c) {
    $badge = $c['verified'] ? ' ✓' : '';
    echo "@{$c['username']}{$badge}: {$c['text']}\n";
    echo "  Likes: " . number_format($c['likes']) . " | Replies: {$c['replyCount']}\n\n";
}

cURL

curl -X GET "https://api.socialkit.dev/instagram/comments?access_key=your-access-key&url=https://www.instagram.com/reel/DRU4smMj0cu/&limit=50"

Walking the Full Thread with Cursor Pagination

Viral Instagram reels can have thousands of comments. The cursor field lets you walk the entire thread reliably:

async function getAllInstagramComments(postUrl, accessKey, maxComments = 500) {
  const all = [];
  let cursor = null;

  while (all.length < maxComments) {
    const remaining = maxComments - all.length;
    const params = {
      access_key: accessKey,
      url: postUrl,
      limit: Math.min(100, remaining),
    };
    if (cursor) params.cursor = cursor;

    const { data } = await axios.get(
      'https://api.socialkit.dev/instagram/comments',
      { params }
    );

    all.push(...data.data.comments);
    if (!data.data.hasMore || !data.data.cursor) break;
    cursor = data.data.cursor;
  }

  return all;
}

// Usage: pull up to 500 comments from a viral reel
const comments = await getAllInstagramComments(
  'https://www.instagram.com/reel/DRU4smMj0cu/',
  'your-access-key',
  500
);
console.log(`Pulled ${comments.length} comments across all pages`);
def get_all_instagram_comments(post_url, access_key, max_comments=500):
    all_comments = []
    cursor = None

    while len(all_comments) < max_comments:
        remaining = max_comments - len(all_comments)
        data = get_instagram_comments(
            post_url, access_key,
            limit=min(100, remaining),
            cursor=cursor,
        )
        all_comments.extend(data['data']['comments'])
        if not data['data']['hasMore'] or not data['data']['cursor']:
            break
        cursor = data['data']['cursor']

    return all_comments

Use Cases

1. Influencer Audience Authenticity Check

Before paying a creator, verify their comment quality:

async function checkInfluencerAuthenticity(reelUrls, accessKey) {
  let totalComments = 0;
  let verifiedCommentCount = 0;
  let templateLikeCount = 0;

  for (const url of reelUrls) {
    const data = await getInstagramComments(url, accessKey, { limit: 100 });
    const comments = data.data.comments;
    totalComments += comments.length;

    for (const c of comments) {
      if (c.verified) verifiedCommentCount++;
      // crude template detection: very short, all-emoji or fire/heart-only
      if (c.text.length < 6 && /^[🔥❤️😍👏🙌]+$/u.test(c.text)) {
        templateLikeCount++;
      }
    }
  }

  return {
    totalComments,
    pctVerified: (verifiedCommentCount / totalComments * 100).toFixed(1) + '%',
    pctTemplate: (templateLikeCount / totalComments * 100).toFixed(1) + '%',
  };
}

2. Sentiment Analysis Pipeline

Feed comments to OpenAI for sentiment scoring:

import openai

def analyze_post_sentiment(post_url, access_key, openai_key):
    data = get_instagram_comments(post_url, access_key, limit=50)
    comments = data['data']['comments']
    
    comments_text = '\n'.join(
        f"@{c['username']}: {c['text']} ({c['likes']} likes)"
        for c in comments
    )

    openai.api_key = openai_key
    response = openai.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{
            'role': 'user',
            'content': f'Analyze sentiment (positive/neutral/negative %) and 3 themes:\n\n{comments_text}'
        }],
    )
    return response.choices[0].message.content

3. Top Engagement Surfacing

Find the most-liked comments under a reel:

async function getTopComments(postUrl, accessKey, topN = 10) {
  const all = await getAllInstagramComments(postUrl, accessKey, 200);
  return all
    .sort((a, b) => b.likes - a.likes)
    .slice(0, topN)
    .map((c) => ({
      username: c.username,
      verified: c.verified,
      text: c.text,
      likes: c.likes,
      replyCount: c.replyCount,
    }));
}

4. Comment Moderation Alert System

Monitor your branded reels for comments needing attention:

def monitor_reels(reel_urls, access_key, flag_keywords):
    flagged = []
    for url in reel_urls:
        data = get_instagram_comments(url, access_key, limit=50)
        for c in data['data']['comments']:
            text_lower = c['text'].lower()
            for kw in flag_keywords:
                if kw.lower() in text_lower:
                    flagged.append({
                        'reel': url,
                        'username': c['username'],
                        'text': c['text'],
                        'likes': c['likes'],
                        'flagged_keyword': kw,
                    })
                    break
    return flagged

# Usage
keywords = ['scam', 'refund', 'broken', 'help', 'issue']
alerts = monitor_reels([
    'https://www.instagram.com/reel/abc/',
    'https://www.instagram.com/reel/def/',
], 'your-key', keywords)

Response Data Explained

Comment Object Fields

  • id - Unique comment identifier
  • username - Instagram handle (without @ prefix)
  • fullName - Display name (may be empty)
  • profilePicUrl - Profile picture URL (signed CDN link)
  • verified - true if commenter has a verified Instagram account
  • text - Comment text content (may contain emojis)
  • likes - Number of likes on the comment
  • replyCount - Number of threaded replies under this comment
  • date - Comment date in MM-DD-YYYY format
  • timestamp - Unix timestamp (seconds)
  • parentCommentId - ID of parent comment if this is a reply, otherwise null

Top-Level Fields

  • url - The URL you submitted
  • postUrl - Canonical Instagram post URL
  • shortcode - Post shortcode extracted from URL
  • commentCount - Total comments on the post
  • limit - Limit applied to this response
  • hasMore - true if more comments are available
  • cursor - Opaque token to pass back for the next page

Supported URL Formats

The API accepts various Instagram URL formats:

  • https://www.instagram.com/p/<shortcode>/ (regular posts)
  • https://www.instagram.com/reel/<shortcode>/ (Reels)
  • https://www.instagram.com/reels/<shortcode>/ (alternative reel format)
  • https://www.instagram.com/tv/<shortcode>/ (IGTV)

Error Handling

Implement retry logic for production reliability:

async function getInstagramCommentsWithRetry(
  postUrl, accessKey, options = {}, maxRetries = 3
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await getInstagramComments(postUrl, accessKey, options);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      // Exponential backoff
      await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, i)));
    }
  }
}

Common error responses:

StatusMeaningWhat to Do
400Missing url parameterCheck the request includes a valid Instagram post URL
403Out of creditsTop up at /pricing
404Post not found or comments disabledPost may be private, deleted, or the creator restricted comments
408TimeoutRetry with exponential backoff
500Server errorRetry; if persistent, check status

Pricing & Credits

The Instagram Comments API uses 1 credit per 50 comments returned (minimum 1 credit per request).

Monthly plans:

  • Free: 20 credits to start
  • Starter ($19/mo): 4,000 credits, good for ~200,000 comments
  • Standard ($29/mo): 12,000 credits, good for ~600,000 comments (most popular)
  • Ultimate ($95/mo): 50,000 credits, bulk research scale

Pay-as-you-go (one-time, never expires):

  • Starter Pack ($14): 1,000 credits
  • Growth Pack ($49): 20,000 credits
  • Scale Pack ($249): 150,000 credits

See full pricing.

Free Tools

Test the API quality without writing code first:

Conclusion

The Instagram Comments API gives you full access to Instagram post and reel comments without proxies, Puppeteer, or scraping infrastructure. Cursor pagination lets you walk the entire thread on viral content, verification badges help filter out template engagement, and a clean JSON response drops straight into any sentiment-analysis or audience-research pipeline.

Start with the free Instagram Comment Viewer to see what the response looks like, then grab 20 free API credits to wire it into your stack.

Related Resources: