Instagram Comment Sentiment Analysis with an API
The comments under a brand's Instagram posts are unfiltered voice-of-customer data: what people love, what they complain about, which launches landed, and which fell flat. Read one post's comments by hand and you get anecdotes. Pull thousands programmatically and score them, and you get a trend line your marketing team can act on.
This guide shows how to build an Instagram comment sentiment pipeline with an Instagram API — the Instagram Cheapest API on RapidAPI. You'll fetch comments by post shortcode, score sentiment in Python, and aggregate the results into a voice-of-customer view. It runs on real-time, uncached public data at as little as $0.10 per 1,000 requests.
The pipeline in four stages
- Collect — pull the brand's recent posts and their shortcodes (
user_media). - Fetch comments — get all comments for each post (
media_comments). - Score — run each comment through a sentiment model.
- Aggregate — roll sentiment up by post, by week, and by theme.
Step 1: Collect the posts to analyze
Start from the brand's username, resolve it, and pull recent posts to get their shortcodes (the code field each comment call needs).
import requests
API_HOST = "instagram-cheapest.p.rapidapi.com"
BASE = f"https://{API_HOST}/api/v1/instagram"
API_KEY = "YOUR_RAPIDAPI_KEY"
HEADERS = {"x-rapidapi-host": API_HOST, "x-rapidapi-key": API_KEY}
def get_profile(username):
r = requests.get(f"{BASE}/user/{username}", headers=HEADERS)
r.raise_for_status()
return r.json()
def get_media(user_id, next_max_id=None):
params = {"user_id": user_id}
if next_max_id:
params["next_max_id"] = next_max_id
r = requests.get(f"{BASE}/user_media", headers=HEADERS, params=params)
r.raise_for_status()
return r.json()
profile = get_profile("some_brand")
user_id = profile.get("user_id") # confirm field from raw JSON
posts = get_media(user_id).get("items", []) # confirm key from raw JSON
codes = [p.get("code") for p in posts if p.get("code")]
To analyze a longer history, paginate user_media with the next_max_id cursor (see the pagination guide).
Step 2: Fetch all comments per post
The media_comments?code= endpoint returns comments for a post or Reel and paginates with an after cursor taken from page_info.end_cursor. Loop until there are no more pages to capture the full thread.
def get_comments_page(code, after=None):
params = {"code": code}
if after:
params["after"] = after
r = requests.get(f"{BASE}/media_comments", headers=HEADERS, params=params)
r.raise_for_status()
return r.json()
def all_comments(code, max_pages=10):
texts, after = [], None
for _ in range(max_pages):
data = get_comments_page(code, after)
for c in data.get("comments", []): # confirm key from raw JSON
if c.get("text"):
texts.append(c["text"])
page = data.get("page_info", {})
if not page.get("has_next_page"):
break
after = page.get("end_cursor")
return texts
Capping max_pages keeps cost predictable on viral posts with tens of thousands of comments — for sentiment, a representative sample is usually enough.
Step 3: Score sentiment
For a fast, free baseline, use VADER (tuned for short social text). For nuance — sarcasm, mixed sentiment, aspect-level opinions — send batches to an LLM instead.
# Baseline: VADER (pip install nltk)
from nltk.sentiment import SentimentIntensityAnalyzer
sia = SentimentIntensityAnalyzer()
def score(texts):
out = []
for t in texts:
s = sia.polarity_scores(t)["compound"] # -1 (neg) .. +1 (pos)
label = "positive" if s > 0.05 else "negative" if s < -0.05 else "neutral"
out.append({"text": t, "score": s, "label": label})
return out
scored = score(all_comments("ABC1234XYZ_"))
positives = sum(1 for s in scored if s["label"] == "positive")
print(f"{positives}/{len(scored)} comments positive")
VADER handles emoji and slang reasonably well, but it doesn't understand context. For brand work where a false "positive" on a sarcastic complaint matters, an LLM pass over the same comments gives much better labels — and can also extract themes (shipping, price, quality) in the same call.
Step 4: Aggregate into a voice-of-customer view
Per-comment scores are noise until you roll them up. The aggregations that matter to a marketing team:
- Sentiment over time — average sentiment per post, plotted by post date, reveals whether perception is trending up or down.
- Best and worst posts — which content drew the most positive (or negative) reaction.
- Theme breakdown — group comments by topic (extracted via keywords or an LLM) and score each theme separately, so you see what people are positive or negative about.
- Spike detection — a sudden jump in negative volume flags a PR issue or a botched launch early.
import statistics
def post_summary(code):
scored = score(all_comments(code))
if not scored:
return None
return {
"code": code,
"n": len(scored),
"avg_sentiment": round(statistics.mean(s["score"] for s in scored), 3),
"pct_negative": round(
sum(1 for s in scored if s["label"] == "negative") / len(scored) * 100, 1),
}
summaries = [post_summary(c) for c in codes]
# Sort by pct_negative to surface posts that need attention.
What you can build with this
- Brand health dashboard — a live sentiment trend line for your own account.
- Competitive sentiment benchmarking — run the same pipeline on competitors and compare.
- Launch monitoring — track reaction to a product drop in the hours and days after it posts.
- Social listening / agency reporting — package sentiment summaries for clients.
To screen which comments are genuine before scoring them, pair this with the fake-engagement detection checks. The raw comment-fetching mechanics are covered in the comments API tutorial.
What does it cost?
Analyzing one brand's last 30 posts with ~3 comment pages each ≈ 1 profile + 3 media pages + 30 × 3 ≈ ~94 requests — about a penny. Monitoring 100 brands weekly is ~40,000 requests/month, comfortably inside the Pro tier.
- Free Basic tier: 30 requests/month — enough to analyze a few posts while you build
- Pro tier ($59/mo): 150,000 requests included, then $0.13 per 1,000
- Ultra tier ($119/mo): 900,000 requests included, then $0.11 per 1,000
- Mega tier ($249/mo): 3,000,000 requests included, then $0.10 per 1,000
Use the optional fields parameter to return just the comment text (and timestamp) you need — that trims the raw JSON and keeps you inside the 10 GB/month bandwidth allowance even on comment-heavy posts.
Compliance and responsible use
This API returns public Instagram data only. Sentiment analysis of public comments is a common research and marketing use, but you are responsible for complying with Instagram's terms of service and applicable privacy laws (GDPR, CCPA) — especially if you store comment text alongside usernames. The API is not affiliated with or endorsed by Meta or Instagram.
Conclusion
Instagram comments are one of the richest, least-structured sources of customer opinion available — and they're public. With user_media to find posts and media_comments to pull the threads, you can build a sentiment pipeline that turns raw comments into a voice-of-customer trend line. At $0.10–$0.13 per 1,000 requests, monitoring sentiment across dozens of brands costs only a few dollars a month.
Compliance note: this API returns public Instagram data only. You are responsible for complying with Instagram's terms and applicable privacy law (GDPR/CCPA). Not affiliated with or endorsed by Meta/Instagram.