Back to Blog
Guide

Instagram Engagement Rate Calculator: How to Calculate & What the Numbers Mean

March 26, 2026
11 min read
S
By SociaVault Team
InstagramEngagement RateCalculatorAnalyticsInfluencer MarketingSocial Media Data

Instagram Engagement Rate Calculator: How to Calculate & What the Numbers Mean

Everyone talks about engagement rate. Most people calculate it wrong.

Some divide by reach. Some divide by impressions. Some include saves, some don't. Some count Story interactions, some only count feed posts. Marketing blogs contradict each other. Tools give different numbers for the same account.

This guide straightens it out. You'll learn:

  • The standard formula (and why there are multiple)
  • How to calculate it manually
  • How to automate it with code for any public account
  • What the numbers actually mean for your tier and niche
  • When a "low" number is actually fine

No fluff, just math.


The Formula (And Why There Are 4 Versions)

There's no single "official" engagement rate formula. Different people use different ones. Here are the four most common:

Formula 1: Engagement Rate by Followers (ERF)

ER = (Likes + Comments) / Followers × 100

Use this when: You want to compare across accounts, especially competitors. This is the industry standard for influencer marketing because follower count is public. Our engagement rate benchmarks use this formula.

Formula 2: Engagement Rate by Reach (ERR)

ER = (Likes + Comments + Saves + Shares) / Reach × 100

Use this when: You're analyzing your own account and have access to Instagram Insights. More accurate because it measures engagement from people who actually saw the post. But you can only calculate this for your own content — reach data isn't public.

Formula 3: Engagement Rate by Impressions (ERI)

ER = (Likes + Comments) / Impressions × 100

Use this when: You're focused on content performance. Impressions include repeat views, so this number is always lower than ERR. Rarely used.

Formula 4: Engagement Rate by Views (for Reels/Video)

ER = (Likes + Comments) / Views × 100

Use this when: You're evaluating Reels or video content specifically. A Reel can get views from millions of non-followers, so dividing by followers makes no sense. This is more common for TikTok analysis.

Which One Should You Use?

SituationBest Formula
Comparing your account to competitorsERF (by followers)
Evaluating your own content strategyERR (by reach)
Vetting an influencer before a dealERF (by followers)
Analyzing Reels/video contentER by Views
Reporting to a clientERR (by reach) — shows true performance

For this guide, we'll use ERF (by followers) because it's the only one you can calculate for any public account.


Calculate It Manually (5 Minutes)

No tool, no API, no money. Just arithmetic.

Step 1: Pick 12 Recent Posts

Go to the account's profile. Pick the 12 most recent feed posts (not Reels, not Stories — we'll get to those). Why 12? It gives you roughly a month of content, enough to smooth out outliers.

Step 2: Record Likes and Comments

For each post, write down:

  • Likes count (visible unless hidden)
  • Comments count

Step 3: Calculate Per-Post ER

For each post:

Post ER = (Likes + Comments) / Followers × 100

Step 4: Average Them

Add all 12 post ERs together, divide by 12.

Example: @natgeo

Let's say National Geographic has 285M followers. A recent post has 450K likes and 1,200 comments:

Post ER = (450,000 + 1,200) / 285,000,000 × 100 = 0.16%

That looks low, but for a 285M-follower account, it's on par. Engagement rates drop dramatically with scale. Check our full benchmarks by tier for context.


Calculate It With Code (Any Account, Seconds)

Manual calculation works for one account. If you're checking competitors, vetting influencers, or running an agency, you need code.

JavaScript

const axios = require('axios');

const API_KEY = process.env.SOCIAVAULT_API_KEY;
const BASE_URL = 'https://api.sociavault.com';

async function engagementRate(username) {
  // Get profile — provides follower count
  const profile = await axios.get(`${BASE_URL}/v1/scrape/instagram/profile`, {
    params: { handle: username, trim: true },
    headers: { 'X-API-Key': API_KEY }
  });

  const user = profile.data.data.data.user;
  const followers = user.edge_followed_by.count;
  const following = user.edge_follow.count;
  const isVerified = user.is_verified;

  // Get recent posts — provides likes + comments per post
  const posts = await axios.get(`${BASE_URL}/v1/scrape/instagram/posts`, {
    params: { handle: username, trim: true },
    headers: { 'X-API-Key': API_KEY }
  });

  const edges = posts.data.data.data.user.edge_owner_to_timeline_media.edges;

  if (edges.length === 0) {
    console.log(`@${username} has no posts`);
    return null;
  }

  // Calculate per-post engagement rate
  let totalER = 0;
  const postData = [];

  for (const edge of edges) {
    const node = edge.node;
    const likes = node.edge_liked_by?.count || 0;
    const comments = node.edge_media_to_comment?.count || 0;
    const er = ((likes + comments) / followers) * 100;

    postData.push({
      url: `https://instagram.com/p/${node.shortcode}`,
      likes,
      comments,
      er: er.toFixed(3) + '%',
      date: new Date(node.taken_at_timestamp * 1000).toLocaleDateString()
    });

    totalER += er;
  }

  const avgER = totalER / edges.length;

  // Determine tier
  let tier = 'Nano';
  if (followers >= 500000) tier = 'Mega';
  else if (followers >= 100000) tier = 'Macro';
  else if (followers >= 50000) tier = 'Mid';
  else if (followers >= 10000) tier = 'Micro';

  console.log(`\n@${username} ${isVerified ? '✓' : ''}`);
  console.log(`Tier: ${tier} (${followers.toLocaleString()} followers)`);
  console.log(`Following: ${following.toLocaleString()}`);
  console.log(`Posts analyzed: ${edges.length}`);
  console.log(`Average Engagement Rate: ${avgER.toFixed(2)}%`);
  console.log(`\nPer-post breakdown:`);
  postData.forEach(p => {
    console.log(`  ${p.date} | ${p.likes.toLocaleString()} likes, ${p.comments.toLocaleString()} comments → ${p.er}`);
  });

  return { username, tier, followers, avgER: avgER.toFixed(2), posts: postData };
}

// Calculate for any account
await engagementRate('cristiano');

Python

import requests
import os

API_KEY = os.getenv('SOCIAVAULT_API_KEY')
BASE_URL = 'https://api.sociavault.com'
headers = {'X-API-Key': API_KEY}

def engagement_rate(username):
    """Calculate engagement rate for any public Instagram account"""

    # Get profile
    profile = requests.get(
        f'{BASE_URL}/v1/scrape/instagram/profile',
        params={'handle': username, 'trim': 'true'},
        headers=headers
    ).json()

    user = profile['data']['data']['user']
    followers = user['edge_followed_by']['count']
    following = user['edge_follow']['count']
    verified = user.get('is_verified', False)

    # Get posts
    posts = requests.get(
        f'{BASE_URL}/v1/scrape/instagram/posts',
        params={'handle': username, 'trim': 'true'},
        headers=headers
    ).json()

    edges = posts['data']['data']['user']['edge_owner_to_timeline_media']['edges']

    if not edges:
        print(f"@{username} has no posts")
        return None

    # Calculate
    rates = []
    for edge in edges:
        node = edge['node']
        likes = node.get('edge_liked_by', {}).get('count', 0)
        comments = node.get('edge_media_to_comment', {}).get('count', 0)
        er = ((likes + comments) / followers) * 100
        rates.append(er)

    avg_er = sum(rates) / len(rates)

    # Determine tier
    if followers >= 500_000:
        tier = 'Mega'
    elif followers >= 100_000:
        tier = 'Macro'
    elif followers >= 50_000:
        tier = 'Mid'
    elif followers >= 10_000:
        tier = 'Micro'
    else:
        tier = 'Nano'

    print(f"\n@{username} {'✓' if verified else ''}")
    print(f"Tier: {tier} ({followers:,} followers)")
    print(f"Posts analyzed: {len(edges)}")
    print(f"Average Engagement Rate: {avg_er:.2f}%")

    return {'username': username, 'tier': tier, 'followers': followers, 'avg_er': round(avg_er, 2)}

engagement_rate('cristiano')

Cost: 2 API credits per account (1 profile + 1 posts).


Comparing Multiple Accounts Side by Side

This is where the code approach really pays off. Want to compare 5 competitors in your niche? Don't manually check 60 posts. Do this:

async function compareAccounts(usernames) {
  const results = [];

  for (const username of usernames) {
    const result = await engagementRate(username);
    if (result) results.push(result);
  }

  // Sort by engagement rate
  results.sort((a, b) => parseFloat(b.avgER) - parseFloat(a.avgER));

  console.log('\n\n=== ENGAGEMENT RATE COMPARISON ===\n');
  console.log('Rank | Account           | Followers    | Avg ER');
  console.log('-----|-------------------|-------------|-------');
  results.forEach((r, i) => {
    console.log(`  ${i + 1}  | @${r.username.padEnd(16)} | ${r.followers.toLocaleString().padStart(11)} | ${r.avgER}%`);
  });

  return results;
}

// Compare fitness influencers
await compareAccounts([
  'kayla_itsines',
  'blogilates',
  'whitneyysimmons',
  'jeffnippard',
  'megsquats'
]);

Cost: 2 credits per account × 5 accounts = 10 credits total. In a paid analytics tool, this comparison would cost $30-100/month.


Including Reels in the Calculation

Feed post engagement and Reels engagement are very different. Reels reach non-followers, so their engagement rate (by followers) looks different.

To include Reels:

async function fullEngagementRate(username) {
  const profile = await axios.get(`${BASE_URL}/v1/scrape/instagram/profile`, {
    params: { handle: username, trim: true },
    headers: { 'X-API-Key': API_KEY }
  });

  const followers = profile.data.data.data.user.edge_followed_by.count;

  // Get feed posts
  const posts = await axios.get(`${BASE_URL}/v1/scrape/instagram/posts`, {
    params: { handle: username, trim: true },
    headers: { 'X-API-Key': API_KEY }
  });

  // Get Reels
  const reels = await axios.get(`${BASE_URL}/v1/scrape/instagram/reels`, {
    params: { handle: username },
    headers: { 'X-API-Key': API_KEY }
  });

  const postEdges = posts.data.data.data.user.edge_owner_to_timeline_media.edges;
  const reelItems = reels.data.items || [];

  // Feed post ER
  const postRates = postEdges.map(e => {
    const likes = e.node.edge_liked_by?.count || 0;
    const comments = e.node.edge_media_to_comment?.count || 0;
    return ((likes + comments) / followers) * 100;
  });

  // Reel ER (by followers, for consistency)
  const reelRates = reelItems.map(item => {
    const likes = item.media?.like_count || 0;
    const comments = item.media?.comment_count || 0;
    return ((likes + comments) / followers) * 100;
  });

  const avgPostER = postRates.length ? postRates.reduce((a, b) => a + b, 0) / postRates.length : 0;
  const avgReelER = reelRates.length ? reelRates.reduce((a, b) => a + b, 0) / reelRates.length : 0;
  const combinedER = [...postRates, ...reelRates];
  const avgCombined = combinedER.reduce((a, b) => a + b, 0) / combinedER.length;

  console.log(`\n@${username} — Full Engagement Breakdown`);
  console.log(`Followers: ${followers.toLocaleString()}`);
  console.log(`Feed Post ER: ${avgPostER.toFixed(2)}% (${postRates.length} posts)`);
  console.log(`Reels ER: ${avgReelER.toFixed(2)}% (${reelRates.length} reels)`);
  console.log(`Combined ER: ${avgCombined.toFixed(2)}%`);

  return { avgPostER, avgReelER, avgCombined };
}

await fullEngagementRate('garyvee');

Cost: 3 credits (profile + posts + reels). Worth it when you need the full picture.


What "Good," "Bad," and "Great" Actually Mean

Here's the context most calculators don't give you. Quick reference by follower tier:

TierFollowersBelow AverageAverageGoodGreat
Nano1K-10KUnder 2.5%2.5-4.0%4.0-6.0%6.0%+
Micro10K-50KUnder 1.5%1.5-2.8%2.8-4.0%4.0%+
Mid50K-100KUnder 1.0%1.0-1.9%1.9-3.0%3.0%+
Macro100K-500KUnder 0.7%0.7-1.4%1.4-2.0%2.0%+
Mega500K+Under 0.4%0.4-0.9%0.9-1.5%1.5%+

These benchmarks come from our analysis of 50,000 Instagram accounts. They're filtered for accounts with genuine, organic engagement — no bots, no pods, no purchased followers.

Important: Niche matters just as much as tier. An Education account at 3.8% is average. A Beauty account at 3.8% is exceptional. See the full breakdown by niche.


Common Mistakes

Mistake 1: Including Your Own Likes

If the account owner likes their own posts (common), that like is counted. For most accounts, this is negligible. For a nano account with 50 likes per post, one self-like doesn't matter. Don't worry about it.

Mistake 2: Using Too Few Posts

Calculating from 3 posts is meaningless. One viral post skews everything. Use at least 12, ideally 20-30.

Mistake 3: Comparing Across Tiers

A 2% ER for a micro account (15K followers) is below average. A 2% ER for a macro account (300K followers) is excellent. Context matters.

Mistake 4: Ignoring Content Type

Reels and carousels get fundamentally different engagement than single images. If you're comparing two accounts, make sure you're comparing similar content mixes.

Mistake 5: Not Accounting for Fake Followers

High follower count + low engagement doesn't always mean bad content. It often means purchased followers diluting the denominator. Our fake follower study found 37.2% of influencer followers are fake. That directly destroys engagement rates.


FAQ

Should I include saves and shares?

Not for public comparisons. Saves and shares are only visible to the account owner. If you include them for your own account, your ER will look higher than anyone else's because you have data they don't. Use likes + comments for apples-to-apples comparison.

My engagement rate dropped. Is that bad?

Check if your follower count grew. If you gained 20K followers but engagement stayed flat, your ER drops — that's normal growth, not a problem. If followers are flat and engagement dropped, then your content is underperforming.

How often should I calculate it?

Weekly for your own account. Monthly for competitors. Before every influencer deal.

Does engagement rate affect the algorithm?

Yes. Instagram uses engagement signals (especially saves and shares in 2026) to decide how widely to distribute your content. Higher engagement = more reach = more engagement. It's a flywheel.


Get Started

Calculate engagement rates for any public Instagram account.

Sign up free — 100 credits gives you 50 engagement rate calculations (2 credits each: profile + posts).

Full API docs: docs.sociavault.com/api-reference/instagram


Found this helpful?

Share it with others who might benefit

Ready to Try SociaVault?

Start extracting social media data with our powerful API. No credit card required.