# Instagram Competitor Benchmark | Engagement & Content Report (`feedminer/instagram-competitor-benchmark`) Actor

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.

- **URL**: https://apify.com/feedminer/instagram-competitor-benchmark.md
- **Developed by:** [FeedMiner](https://apify.com/feedminer) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

<div style="border-left:3px solid #1C1917;background:#FAFAF9;padding:15px 20px;border-radius:3px">
<strong>Your handle and up to nine competitors in — their recent posts benchmarked side by side, out.</strong> Engagement per post, posting cadence, format mix, top and flop posts, promo-hashtag share, and where you sit against the field's median. One row per post in the dataset, plus a ready-to-read HTML report. No Instagram account of yours is involved, and nothing has to be connected.
</div>

🔓 **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](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/instagram-competitor-benchmark-how-it-works-v1.png)

#### 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

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

##### Mark which handle is yours

```json
{ "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

```json
{ "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

```json
{
  "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

| Parameter | Type | Default | Description |
|---|---|---|---|
| `handles` | array | required | 2 to 10 Instagram usernames, yours and your competitors', with or without `@`. Case is folded and duplicates fold on read |
| `myHandle` | string | — | 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 |
| `postsPerAccount` | integer | `30` | How 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` |
| `debugMode` | boolean | `false` | Verbose 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**

| Field | Type | Description |
|---|---|---|
| `handle` | string | The account, as normalised: lowercased, `@` stripped |
| `is_my_handle` | boolean | Whether this is the handle you marked as yours |
| `account_followers` | integer | The account's follower count as read during this run |
| `account_media_count` | integer | The 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**

| Field | Type | Description |
|---|---|---|
| `post_shortcode` | string | The post's shortcode — `instagram.com/p/<shortcode>` opens it |
| `taken_at` | string | Publish 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_type` | string | `image`, `video` or `carousel` — and `other` for a container Instagram has not shown us yet, rather than one of the three guessed at |
| `is_reel` | boolean | Whether the post is a Reel, whatever container it was posted in |
| `carousel_len` | integer | Number of media in a carousel, `0` otherwise |
| `caption` | string | The caption as written |
| `thumbnail_url` | string | The post's first thumbnail, hotlinked — expires with Instagram's CDN |
| `page_index` | integer | Which page of the account's grid the post came from. Always `1`: the embedded grid is the only page an anonymous read reaches |

**Engagement**

| Field | Type | Description |
|---|---|---|
| `like_count` | integer | **Null 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_count` | integer | Comments on the post |
| `view_count` | integer | **Always 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_rate` | number | `(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**

| Field | Type | Description |
|---|---|---|
| `is_paid_partnership` | boolean | **Always 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_hashtags` | array | Which 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](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/instagram-competitor-benchmark-row-anatomy-v1.png)

##### Example row

```json
{
  "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](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/instagram-competitor-benchmark-coverage-v2.png)

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

| Event | What it bills |
|---|---|
| `post` | One 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

```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

```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`.

| Measure | Value | Measured on |
|---|---|---|
| Posts per run | 72 — twelve for each of six accounts | That run's dataset |
| Wall clock | 3 min 35 s (215.0 s) | That run's own duration |
| Reading speed | About 20 posts per minute | 72 posts in 215.0 s |
| Per account | About 36 seconds | Six accounts in 215.0 s, read one after another |
| Delivered against collected | 72 offered, 72 delivered, 0 dropped | The run's dataset push summaries |
| Depth reached | 12 posts per account, out of 30 asked for | Every account came back `partial` on that run |
| Report | One HTML page, 41 747 bytes | The 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.

### Legal compliance

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](https://apify.com/feedminer/instagram-seo-audit) · [All FeedMiner Actors](https://apify.com/feedminer)

# Actor input Schema

## `handles` (type: `array`):

2 to 10 Instagram usernames, yours and your competitors', with or without @.

## `myHandle` (type: `string`):

Optional. One of the handles above; the report marks it as yours and shows where it drops below the field.

## `postsPerAccount` (type: `integer`):

How many recent posts each account is benchmarked on. An anonymous read reaches the twelve the public profile page embeds; asking for more is served those twelve.

## `debugMode` (type: `boolean`):

Verbose log lines for support. Leave off.

## Actor input object example

```json
{
  "handles": [
    "nasa",
    "spacex"
  ],
  "postsPerAccount": 30,
  "debugMode": false
}
```

# Actor output Schema

## `report` (type: `string`):

No description

## `posts` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "handles": [
        "nasa",
        "spacex"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("feedminer/instagram-competitor-benchmark").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "handles": [
        "nasa",
        "spacex",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("feedminer/instagram-competitor-benchmark").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "handles": [
    "nasa",
    "spacex"
  ]
}' |
apify call feedminer/instagram-competitor-benchmark --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,feedminer/instagram-competitor-benchmark"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ufJUskEocAXIRc8QX/builds/FYylr6zNahg938oeh/openapi.json
