How to Build an Instagram Competitor Monitoring Dashboard with an API
Knowing what your competitors post — and which of those posts actually land — is one of the highest-leverage inputs a social or marketing team has. Doing it by hand means opening a dozen profiles every morning and eyeballing like counts. A monitoring dashboard does it automatically: it snapshots each competitor on a schedule, records engagement over time, and flags the posts that break out.
This guide shows how to build the data layer for that dashboard with an Instagram API — the Instagram Cheapest API on RapidAPI. You'll poll a watchlist of accounts, store engagement history, compute share-of-voice, and detect viral posts — all on real-time, uncached public data at as little as $0.10 per 1,000 requests.
The architecture in one paragraph
A competitor monitor is a scheduled job, not a live API. It runs (say) once a day, pulls each competitor's latest posts and Reels, writes a row per post into a database, and compares against yesterday's snapshot. The dashboard reads from your database, never from Instagram directly — so the UI is instant even though each fetch takes a few seconds. Because the data is real-time and uncached, every snapshot reflects the true current state.
Step 1: Resolve your watchlist to user IDs
Store competitors as usernames, but most endpoints key off the numeric user_id. Resolve each once with user/{username} and cache the ID (it doesn't change).
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 resolve(username):
r = requests.get(f"{BASE}/user/{username}", headers=HEADERS)
r.raise_for_status()
p = r.json()
return {
"username": username,
"user_id": p.get("user_id"), # confirm field from raw JSON
"followers": p.get("follower_count"), # confirm field from raw JSON
}
WATCHLIST = ["competitor_a", "competitor_b", "competitor_c"]
profiles = [resolve(u) for u in WATCHLIST]
Re-running user/{username} on each cycle also gives you a follower-count time series — useful for spotting growth spurts or follower drops.
Step 2: Snapshot posts and Reels each cycle
For every competitor, pull the most recent page of user_media and user_reels. You usually don't need full history every run — just the latest page is enough to catch new posts and update engagement on recent ones.
def latest_media(user_id):
r = requests.get(f"{BASE}/user_media", headers=HEADERS,
params={"user_id": user_id})
r.raise_for_status()
return r.json().get("items", []) # confirm key from raw JSON
def latest_reels(user_id):
r = requests.get(f"{BASE}/user_reels", headers=HEADERS,
params={"user_id": user_id})
r.raise_for_status()
return r.json()
def snapshot(profile):
posts = latest_media(profile["user_id"])
rows = []
for p in posts:
rows.append({
"username": profile["username"],
"code": p.get("code"),
"likes": p.get("like_count", 0),
"comments": p.get("comment_count", 0),
"taken_at": p.get("taken_at"),
})
return rows
Write each row to your database keyed on (code, snapshot_date). Storing the same post across multiple days is what lets you watch engagement accumulate and compute velocity.
If you need a competitor's full back catalogue (for a one-time baseline), paginate with the next_max_id cursor for posts and the after cursor for Reels — the full looping pattern is in the pagination guide.
Step 3: Detect viral posts with engagement velocity
A "viral" post isn't just one with high total engagement — it's one engaging fast relative to the account's norm. Compare a post's engagement to the competitor's recent average:
def viral_flags(rows, threshold=3.0):
by_user = {}
for r in rows:
by_user.setdefault(r["username"], []).append(r)
alerts = []
for username, posts in by_user.items():
engagements = [p["likes"] + p["comments"] for p in posts]
if not engagements:
continue
avg = sum(engagements) / len(engagements)
for p in posts:
eng = p["likes"] + p["comments"]
if avg and eng > avg * threshold:
alerts.append({"username": username, "code": p["code"],
"engagement": eng, "x_avg": round(eng / avg, 1)})
return alerts
# alerts = viral_flags(all_rows) # e.g. "competitor_a post is 4.2x their average"
Wire these alerts to Slack or email and your team learns about a competitor's breakout post the same day it happens — not a week later.
Step 4: Track user-generated content and collaborations
The user_tag_media endpoint returns posts a competitor is tagged in — a window into their UGC, ambassador activity, and brand collaborations. Poll it to see who's promoting them and how often.
def tagged_media(user_id, after=None):
params = {"user_id": user_id}
if after:
params["after"] = after
r = requests.get(f"{BASE}/user_tag_media", headers=HEADERS, params=params)
r.raise_for_status()
return r.json() # paginates with the `after` cursor (page_info.end_cursor)
A spike in tagged posts often signals a paid campaign or influencer push — exactly the kind of competitive move worth knowing about early.
Step 5: Compute share-of-voice and benchmarks
With snapshots flowing into your database, the dashboard metrics fall out of simple aggregation:
- Posting frequency — new posts per competitor per week
- Average engagement rate — engagement ÷ followers, comparable across accounts of different sizes
- Share-of-voice — each competitor's total engagement as a percentage of the tracked set
- Format mix — Reels vs in-feed posts, and which performs better for each account
- Top content — the highest-velocity posts across the whole watchlist this week
To go deeper on any single account — comment sentiment, audience authenticity — combine this with the influencer analysis and fake-engagement detection workflows.
What does monitoring cost?
Per competitor per daily cycle you need roughly: 1 profile + 1 media page + 1 Reels page (+ optionally 1 tagged-media page) ≈ 3–4 requests. Tracking 50 competitors daily is ~50 × 4 × 30 = 6,000 requests/month — comfortably inside the Pro tier's included quota.
- Free Basic tier: 30 requests/month — enough to monitor a couple of accounts 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 on every call to trim the raw JSON to just the metrics you store — that keeps you inside the 10 GB/month bandwidth allowance even with a large watchlist.
Compliance and responsible use
This API returns public Instagram data only. Competitive benchmarking from public profiles is a standard business use, but you remain responsible for complying with Instagram's terms of service and applicable privacy laws (GDPR, CCPA). The API is not affiliated with or endorsed by Meta or Instagram.
Conclusion
A competitor monitoring dashboard is fundamentally a scheduled snapshot job plus a database. With user/{username}, user_media, user_reels, and user_tag_media, you can track posting cadence, engagement trends, collaborations, and viral breakouts across an entire watchlist — and at $0.10–$0.13 per 1,000 requests, monitoring dozens of competitors daily costs just 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.