How do I get a competitor’s Instagram engagement rate?
Read the public profile for metrics.followers, then the profile posts endpoint for the last 12 or so posts. Engagement rate is likes plus comments, averaged over those posts, divided by followers. Two calls with Openhandle. No account link, no Graph API.
Use only what is public. Reach, impressions, and saves live in the owner’s insights. A vendor that shows a competitor’s reach is estimating.
Checked September 2026 · request and response run against the API · no affiliate links
curl "https://api.openhandle.dev/v1/instagram/profiles/@northstar_forge_test/posts" \
-H "Authorization: Bearer $OPENHANDLE_API_KEY"import { OpenHandle } from '@openhandle/sdk';
const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });
const profile = openhandle.instagram.profile('northstar_forge_test');
const [{ data: account }, page] = await Promise.all([profile.get(), profile.posts.list()]);
const posts = page.data.filter(post => post.metrics.likes !== null);
const perPost = posts.reduce((sum, post) => sum + post.metrics.likes! + post.metrics.comments!, 0) / posts.length;
console.log((perPost / account.metrics.followers!) * 100); // percent{
"platform": "instagram",
"resource": "post",
"capturedAt": "2026-09-18T11:52:18Z",
"source": "live",
"data": [
{ "id": "910100000001", "metrics": { "likes": 840, "comments": 5, "views": 12000 } },
{ "id": "910100000002", "metrics": { "likes": null, "comments": 5, "views": 12700 } },
{ "id": "910100000003", "metrics": { "likes": 900, "comments": 5, "views": 13400 } }
],
"meta": { "cursors": { "next": "b3BhcXVlLWN1cnNvcg" } }
}Trimmed to metrics. The second post has hidden likes and returns null. Skip it, do not count it as zero. The example is a Test profile.
Define the rate before you compute it
- —Per follower. (likes + comments) per post, averaged, divided by followers. The common benchmark. Depends on follower count, so compare accounts of similar size.
- —Per view, for reels. (likes + comments) divided by
metrics.views. Better for video-first accounts and not skewed by dead followers. - —Window. Last 12 posts is the usual window. Skip the newest post if it is less than a day old, it has not settled.
What is public, and what is not
| Metric | Public | Where |
|---|---|---|
| Likes | Yes, unless hidden | metrics.likes, null when hidden |
| Comments | Yes | metrics.comments |
| Reel plays | Yes | metrics.views, null for images |
| Shares and saves | Sometimes | metrics.shares, metrics.saves where Instagram shows them |
| Reach, impressions | No | Owner insights only |
Track it over time
Run the two calls once a week, store the rate with capturedAt, and chart it. Use freshness=live so each row is a fresh read. Store the profile id, not the handle, so a rename does not break the series.
When this does not work
These answers are definitive. Store them, do not retry them.
| Situation | Status | Code |
|---|---|---|
| The account is private | 403 | PROFILE_PRIVATE |
| The account is deleted, banned, or never existed | 404 | PROFILE_NOT_FOUND |
{
"error": {
"code": "PROFILE_PRIVATE",
"message": "This profile is private.",
"requestId": "req_01j8…",
"retryable": false
}
}An account that hides likes on every post has no likes-based rate. Use comments per post, or the per-view rate on reels, and say which one you used.
Read next
More Instagram questions
Send your agent ahead.
Paste the prompt into your agent and it sets everything up. Or come yourself, it takes five minutes.