Instagram Competitor Benchmark | Engagement & Content Report avatar

Instagram Competitor Benchmark | Engagement & Content Report

Pricing

Pay per event

Go to Apify Store
Instagram Competitor Benchmark | Engagement & Content Report

Instagram Competitor Benchmark | Engagement & Content Report

Benchmark your Instagram competitors in one run: engagement rate, posting cadence, top posts and content mix for up to 5 handles side by side. Export the full report to JSON, CSV or Excel. Pay-per-result pricing β€” you only pay for the posts delivered.

Pricing

Pay per event

Rating

0.0

(0)

Developer

FeedMiner

FeedMiner

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

πŸ”“ Nothing to connect, and nothing borrowed either. No Instagram login of yours, no cookies to paste, no API key. Every read here is anonymous β€” unlike the rest of this suite, this Actor needs no logged-in session at all, so there is no account anywhere in the loop that can expire on you.

πŸ“Š The comparison, not the raw feed. Other scrapers hand you posts. This one computes each account's engagement medians, cadence, format mix and promo-tag share, ranks its top and flop posts, and puts the accounts side by side. Mark one handle as yours and it also lists every metric where you sit below the field's median, with the leader's name and value β€” fixed rules over measured numbers, never generated prose.

⚑ A market read in under four minutes. Measured on a real run: six brands benchmarked in 3 minutes 35 seconds, 72 posts, about 20 posts a minute. Accounts are read one after another, so the clock follows the number of handles.

🧾 Every unread read says so. A hidden like count ships null, never a zero that would read as "nobody liked it". The two fields Instagram publishes to nobody anonymously β€” the play count and the declared-partnership flag β€” are named as unread on this page rather than dressed up as measurements.

How the Instagram Competitor Benchmark works: your handle and your competitors' in, one row per post and a comparative HTML report out

FeedMiner Β· Instagram suite β€’ Search rank, leads, competitor benchmarks, event reports
Instagram Competitor Benchmark
You are here
Instagram SEO Audit
Where your account ranks for the words you want to be found for
Instagram B2B Lead Generator
Describe your target, get business contacts with real channels

Copy to your AI assistant

feedminer/instagram-competitor-benchmark on Apify. Benchmarks 2 to 10 Instagram accounts against each other on their recent posts, anonymously β€” no login, no cookies, no pooled session. For each handle it reads the public profile page and the twelve posts that page's grid embeds, then opens each post's own page for its counters. One dataset row per post (handle, is_my_handle, account_followers, account_media_count, post_shortcode, taken_at, media_type, is_reel, like_count, comment_count, view_count, engagement_rate, caption, is_paid_partnership, promo_hashtags, carousel_len, thumbnail_url, page_index) plus a self-contained comparative HTML report at key-value record report.html. Three measured limits to respect when you use it: twelve posts per account is the anonymous ceiling whatever postsPerAccount asks for, view_count is always null because no anonymous surface carries a play count, and is_paid_partnership is always false meaning UNREAD rather than "not sponsored" β€” use promo_hashtags for the sponsored signal. Call ApifyClient("TOKEN").actor("feedminer/instagram-competitor-benchmark").call(run_input={"handles": ["nasa", "spacex"], "myHandle": "nasa"}), then client.dataset(run["defaultDatasetId"]).list_items().items. Required: handles (string[], 2 to 10 usernames, with or without @, case-insensitive, duplicates fold). Optional: myHandle (string, must be one of handles, turns on the gap analysis), postsPerAccount (integer 12-96, default 30), debugMode (bool, default false). Full spec: GET https://api.apify.com/v2/acts/feedminer~instagram-competitor-benchmark/builds/default (Bearer TOKEN) β†’ inputSchema, actorDefinition.storages.dataset, readme. Token: https://console.apify.com/account/integrations

How to benchmark Instagram accounts

Paste the handles you already compete with. That is the whole input.

Two accounts, the smallest run

{ "handles": ["nasa", "spacex"] }

Mark which handle is yours

{ "handles": ["nasa", "spacex", "natgeo"], "myHandle": "nasa" }

The mark is what turns on the gap analysis: without it you get the field table and one card per account, with it you also get the section listing every metric where your handle sits below the field's median.

However the handles were sent to you

{ "handles": ["@nasa", "SpaceX", "natgeo"], "myHandle": "@NASA" }

A leading @ is stripped, case is folded, and duplicates fold away on read β€” so a list pasted out of a spreadsheet works unedited.

Six brands, the reference run

{
"handles": ["nasa", "spacex", "natgeo", "nike", "adidas", "starbucks"],
"myHandle": "nasa",
"postsPerAccount": 30
}

This is run IZNES9KrHFMNz09ZH (6 September 2026, build 0.1.8), the run every measurement on this page comes from: 72 rows, twelve per account, in 3 minutes 35 seconds. Up to ten handles fit in one run.


Input parameters

ParameterTypeDefaultDescription
handlesarrayrequired2 to 10 Instagram usernames, yours and your competitors', with or without @. Case is folded and duplicates fold on read
myHandlestringβ€”Optional. One of the handles above, marked as yours: the report highlights your row and turns on the gap analysis. A handle that is not in the list stops the run rather than silently ignoring the mark
postsPerAccountinteger30How many posts each account is benchmarked on, 12 to 96. An anonymous read reaches the twelve the public profile page embeds β€” the account's pinned posts first, then its most recent. Ask for more and you are served those twelve, with the account marked partial
debugModebooleanfalseVerbose logs for support. Leave off

The two together bound the run: at most ten accounts, at most twelve posts each in practice, so nothing is read that you did not ask for and nothing runs away with your bill.


The report

One self-contained HTML page, written to the run's Key-value store under the record report.html β€” open the store tab of the run, or follow the output's report link. In run IZNES9KrHFMNz09ZH it was 41 747 bytes for six accounts. It carries, in order:

  • The field table β€” one line per account: handle, your mark, read state, followers, posts read, median engagement, median engagement rate, posts per week, format shares and promo-hashtag share, with the field's medians as a reference line.
  • One card per account that delivered posts β€” the metrics in full, including the median gap in days between consecutive posts, then the three top and three flop posts with their thumbnail, shortcode link, per-post numbers and caption excerpt.
  • The gap analysis, when myHandle is set β€” each metric where your handle sits below the field's median, with the numbers and its rule reading; the engagement gap also shows the leader's top posts.

Thumbnail images are hotlinked from Instagram's CDN and expire with it. The numbers stay readable whatever happens to the images, and every one of them is also in the dataset.


What data can you extract from Instagram?

One row per post read, in the run's dataset, written as it is read.

The account the post belongs to

FieldTypeDescription
handlestringThe account, as normalised: lowercased, @ stripped
is_my_handlebooleanWhether this is the handle you marked as yours
account_followersintegerThe account's follower count as read during this run
account_media_countintegerThe account's post count, at Instagram's own rounding. 0 when the profile page's summary line did not carry one β€” observed on adidas in run IZNES9KrHFMNz09ZH

The post itself

FieldTypeDescription
post_shortcodestringThe post's shortcode β€” instagram.com/p/<shortcode> opens it
taken_atstringPublish time, ISO 8601 UTC. This is what every cadence figure is computed from, and reading it down the rows is what hints at a pinned post
media_typestringimage, video or carousel β€” and other for a container Instagram has not shown us yet, rather than one of the three guessed at
is_reelbooleanWhether the post is a Reel, whatever container it was posted in
carousel_lenintegerNumber of media in a carousel, 0 otherwise
captionstringThe caption as written
thumbnail_urlstringThe post's first thumbnail, hotlinked β€” expires with Instagram's CDN
page_indexintegerWhich page of the account's grid the post came from. Always 1: the embedded grid is the only page an anonymous read reaches

Engagement

FieldTypeDescription
like_countintegerNull when the account hides likes on the post β€” a measured fact, not a missing value. Those posts are left out of every engagement figure and cannot rank in top or flop
comment_countintegerComments on the post
view_countintegerAlways null. A video's play count is on no surface an anonymous read reaches β€” including for Reels, as the row-anatomy plate below shows
engagement_ratenumber(like_count + comment_count) Γ· account_followers, as a fraction β€” 0.05 is 5%. Null when likes are hidden or the follower count was unread

Sponsored content

FieldTypeDescription
is_paid_partnershipbooleanAlways false, and that means unread, never not sponsored. Instagram's own declared-partnership flag is on no surface an anonymous read reaches. Use promo_hashtags
promo_hashtagsarrayWhich of the fixed promo tags the caption carries β€” #ad, #ads, #sponsored, #sponsor, #sponsoredpost, #partnership, #partner, #partnered, #paidpartnership, #collab, #collaboration, #affiliate, #affiliation, #ambassador. Null when the caption carries none of them

What one post row of the Instagram Competitor Benchmark carries, field by field

Example row

{
"handle": "nasa",
"is_my_handle": true,
"account_followers": 104404296,
"account_media_count": 4913,
"post_shortcode": "DcuQVFLvJMX",
"taken_at": "2026-08-31T23:23:27Z",
"media_type": "video",
"is_reel": true,
"like_count": 190557,
"comment_count": 971,
"view_count": null,
"engagement_rate": 0.0018344838990150367,
"caption": "Roman is on her way, and the Golden Age of Exploration is just the beginning.",
"is_paid_partnership": false,
"promo_hashtags": null,
"carousel_len": 0,
"page_index": 1
}

That row is from run IZNES9KrHFMNz09ZH, verbatim but for thumbnail_url, which is a signed Instagram CDN link some five hundred characters long and is left out here to keep the example readable. It is a video row, and its view_count is null β€” that is the shape of every video row, not an accident of this one.


What this Actor covers

What the Instagram Competitor Benchmark reaches, and what it does not

This Actor compares accounts you already name. Finding accounts you do not know about is out of scope β€” where you rank for a keyword and who outranks you is Instagram SEO Audit; business contacts behind the accounts is Instagram B2B Lead Generator; posts tagged at a venue over a window is Instagram Event Report. One run is one snapshot: there is no monitoring, alerting or history between runs, so schedule the Actor again to compare two moments.


Limits, said plainly

These are measured facts about what an anonymous read of Instagram can see, not product decisions, and they are on this page so you learn them before you pay rather than after.

  • Twelve posts per account is what an anonymous read reaches. That is the grid Instagram embeds in a public profile page, and no surface pages past it without a logged-in session. Asking for thirty gets you those twelve and marks the account partial β€” that is what all six accounts of run IZNES9KrHFMNz09ZH did.
  • view_count is always null. Reach, impressions and video views are given away to nobody anonymously, Reels included. Engagement here is likes plus comments, and nothing on this page will call it reach.
  • is_paid_partnership is always false, and it means unread. Instagram's declared-partnership flag sits behind the same wall. The promo-hashtag scan reads captions for the fixed tag list above and catches the posts that label themselves β€” it is a floor on sponsored content, never a count of it. On run IZNES9KrHFMNz09ZH that floor was zero for all six brands: not one of the 72 captions carried a tag from the list, so promo_hashtags was null on every row. Six major brands at 0 % is what this metric looks like when nobody labels their posts, and it is worth knowing before you price a decision on it.
  • Posting cadence is read off a grid that serves pinned posts first, so read it beside the median gap. Instagram puts a profile's pinned posts at the head of its grid whatever their date, and they count towards the twelve. In run IZNES9KrHFMNz09ZH three of the six brands served a pinned block: adidas opened on posts from 19 July, 6 July and 7 May, which stretched its read span to 118 days and reported 0.7 posts per week for an account whose nine other posts on that grid all landed inside the six days to 2 September. Posts per week divides the gaps between the posts read β€” one fewer than the posts β€” by the span in weeks between the oldest and the newest of them, so a single old pin flattens it. The median gap between consecutive posts is not pulled the same way β€” nasa came back at 3.3 posts per week beside a median gap of 0.8 days, and where the two disagree the median gap is the one to trust. Reading taken_at down the rows in dataset order shows a pinned block at the head, but it is a hint rather than a proof: one brand in that run also served two ordinary posts a few days out of order mid-grid. The same pinning reaches top and flop: a pinned post is one the brand chose to pin, so it is high-engagement by construction, and 5 of the 18 top-three slots in that run were pinned posts.
  • account_media_count is 0 when the profile page did not carry a post count, which is not the same as an account with no posts. It happened to one brand in six on run IZNES9KrHFMNz09ZH β€” adidas β€” and it is the one delivered field whose failure looks like a measurement. The account's own posts still ship their rows; only the account-level total is missing.
  • Hidden likes read as null. Some accounts hide like counts; those posts are excluded from the engagement figures, counted as hidden in the report, and cannot rank in top or flop.
  • Thumbnails expire. Instagram's CDN links die after a while. The report and the dataset keep every number.
  • A handle Instagram has no page for, or a private account, is reported as such and the run carries on with the others. A grid that stops serving mid-read leaves that account partial with the posts it kept.

Pricing

EventWhat it bills
postOne delivered dataset row β€” one benchmarked post

Price: set at publication. One event, and only delivered rows bill: you are billed on what the dataset actually stored, never on what the run collected. A handle that could not be read ships no row and costs nothing; a run stopped mid-walk bills the posts it had already delivered and nothing else. The HTML report rides the run and is not billed separately.

A run of six accounts delivers 72 rows β€” twelve per account β€” whatever postsPerAccount asked for, so that is what such a run bills. Measured on run IZNES9KrHFMNz09ZH: 72 rows offered, 72 delivered, none dropped.

What this replaces

The comparative read a brand does before a quarter is agency work today, done by hand. The Apify Store sells the parts and not the whole β€” from a survey of the Store taken on 31 August 2026:

  • patient_discovery sells raw cookieless posts by username at $0.002 per run plus $0.00217 per post, about $2.17 per thousand. It hands back posts; the comparison is yours to build.
  • easy_scraper sells profile engagement analytics at roughly $0.001 per run, and simpleapi sells Reels and engagement analytics from profiles at $0.00299 per result β€” one profile's numbers per result, never several set against each other.
  • tempting_finch sells a trend analyzer with HTML reports and a gap analysis at $0.0008 per result, but from queries rather than from a set of handles you name.
  • Nobody sells the benchmark itself: several named accounts side by side, each with its own medians, cadence, formats and top posts, in one report you can hand to a client.

Those are that survey's prices, not necessarily today's.


Advanced usage

Your market in one run, then your own row read last

Put every account you compete with into one run and mark yours. A median engagement figure means nothing on its own and everything against its neighbours: across the six brands of run IZNES9KrHFMNz09ZH the medians ran from 34,842 to 146,034 over the same twelve-post window. The field is the yardstick, and the gap section reads it for you.

Re-derive the report yourself

Every figure in the report comes from the rows, and the rows are delivered. Filter the dataset by handle, recompute the median of like_count + comment_count, weigh Reels against carousels with is_reel and media_type, or drop the posts you consider outliers β€” nothing in the report is a number you have to take on trust.

Before and after a change of format

One run is one snapshot with nothing carried over, so two runs a month apart compare cleanly: the same accounts, the same twelve-post window, the format mix and rhythm on either side of whatever you changed. Compare the median gap rather than posts per week if either account pins β€” a pin that moves between the two runs moves posts per week on its own.

The sponsored floor, read as a floor

Sort by promo_hashtags across the field. It catches the posts that label themselves, so a competitor showing more tagged posts than you is a fact; a competitor showing none is not evidence that they run no partnerships, because the declared flag is unread on every row.


Integrate Instagram benchmarks into your stack

Results flow through the Apify API into Python, JavaScript, Google Sheets, Make, Zapier, n8n, Airtable or Slack. Runs can be scheduled and chained with other Actors.

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("feedminer/instagram-competitor-benchmark").call(run_input={
"handles": ["nasa", "spacex", "natgeo"],
"myHandle": "nasa",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["handle"], row["post_shortcode"], row["like_count"], row["engagement_rate"])
report = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("report.html")

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('feedminer/instagram-competitor-benchmark').call({
handles: ['nasa', 'spacex', 'natgeo'],
myHandle: 'nasa',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const mine = items.filter((row) => row.is_my_handle);
console.log(`${items.length} posts benchmarked, ${mine.length} of them yours`);

Performance

Every row is from platform run IZNES9KrHFMNz09ZH, 6 September 2026, build 0.1.8: six public brands, postsPerAccount 30, launched from the API and finished SUCCEEDED.

MeasureValueMeasured on
Posts per run72 β€” twelve for each of six accountsThat run's dataset
Wall clock3 min 35 s (215.0 s)That run's own duration
Reading speedAbout 20 posts per minute72 posts in 215.0 s
Per accountAbout 36 secondsSix accounts in 215.0 s, read one after another
Delivered against collected72 offered, 72 delivered, 0 droppedThe run's dataset push summaries
Depth reached12 posts per account, out of 30 asked forEvery account came back partial on that run
ReportOne HTML page, 41 747 bytesThe run's key-value record report.html

Reads are paced one at a time through the platform's residential exits, which is why a run scales with the number of accounts rather than finishing all at once. A ten-account run is therefore about ten times one account, not ten times faster.


FAQ

Do I need an Instagram account, cookies or an API key? No. There is nothing to connect and nothing to keep alive on your side. Every read this Actor makes is anonymous β€” it does not even borrow a session the way the rest of this suite does.

How many posts does it actually read per account? Twelve. That is the grid Instagram embeds in a public profile page, and it is the whole of what an anonymous read reaches. postsPerAccount can ask for more, up to 96; you are served those twelve and the account is marked partial so the report never passes an account off as that small.

Why is view_count always null? Because Instagram publishes a play count on no surface a logged-out visitor can reach, Reels included. Rather than shipping a zero you would read as "nobody watched", the field ships null on every row and this page says so.

A competitor shows no sponsored posts. Do they run no partnerships? Unknown, and the Actor will not pretend otherwise. is_paid_partnership is always false because Instagram's declared flag is unread anonymously; promo_hashtags catches only the posts that tag themselves. Read the promo share as a floor, never as a count.

Some posts came back with a null like_count. Is that a failure? No β€” that account hides its like counts on those posts. They are excluded from the engagement medians, counted as hidden in the report, and cannot rank in top or flop. A null is a measurement here, not a gap.

One of my handles came back not found, private or unreadable. Those are three different answers and the report words them apart. not found means Instagram has no page for that handle β€” deleted, renamed, or mistyped; check the spelling. private means the account is private and publishes no grid, so there is nothing public to benchmark. unreadable means the account's page would not serve on this run, or served with an empty grid while the account's own summary says it has posts β€” the handle may well be perfectly fine, and running again often works. In all three cases the account delivers no row, so it bills nothing, the run carries on with the other handles, and the field table names the state. The two states that do deliver are complete and partial.

Is the data live? Yes. Every run reads Instagram at that moment. Nothing is cached or resold, and nothing is kept between runs.

What does it not do? It does not find accounts for you, does not follow accounts over time, does not read Stories, and does not reach reach, impressions or views. It compares handles you name, on the posts a public profile page carries.


Support

  • Found something off in the output, or need a field that is missing? Open the Issues tab on this Actor's page with what you ran and what you expected. Issues are read daily.
  • Need a custom variant of this benchmark for your pipeline β€” a different metric, a different report shape? Ask in the Issues tab, FeedMiner builds on request.

This Actor collects only public data, the same information any visitor can see on instagram.com. Profiles and captions can contain personal data: processing information about people in the EU, the UK or California requires a lawful basis under GDPR or CCPA. Use the data for competitive research, analytics and business intelligence, not for spam or harassment.


FeedMiner Β· Fast, honestly priced scrapers, kept alive when platforms change.

Instagram Competitor Benchmark Β· Instagram SEO Audit Β· All FeedMiner Actors