# Instagram Campaign Performance Benchmark (`zinin/instagram-campaign-performance-benchmark`) Actor

Benchmark Instagram posts within each account and format using observed likes and comments. Get cohort medians and transparent post benchmarks with sample size and missing-data limits.

- **URL**: https://apify.com/zinin/instagram-campaign-performance-benchmark.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** Social media, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.40 / 1,000 post benchmarks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Instagram Campaign Performance Benchmark — turn an existing Instagram post export into per-post cohort benchmarks

Feed it an Instagram post export you already have and get back one benchmark per post — a robust median/percentile against that same account's other posts of the same format, an honest basis (`combined`, `likes_only`, or `comments_only`), and the exact evidence behind the number — never a guess, and never a claim about reach, conversion, or audience.

![Instagram campaign performance benchmark — hero diagram](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/a2f86b716f96fa3d68ca68b66945b34b6efdb65e/value-add-20260923/instagram-campaign-performance-benchmark/readme-hero.webp)

This Actor does not scrape Instagram. It reads post rows you already have — from an upstream Instagram-scraper Actor's Dataset, from an Integrations payload, or pasted in directly — and, for every unique post, compares it only against the **same account's** (case-insensitive) other posts of the **same format** (`type`, exact match — an Image is never benchmarked against a Reel or a Sidecar). A post only gets a real benchmark when its cohort has at least 3 comparable posts and its own metric is known; everything else is an honest free diagnostic, never a fabricated "typical" score. It is a research and prioritization tool for social teams comparing a fresh campaign export against an account's own recent history — not a reach estimate, an engagement-rate-vs-followers claim, a bot/fraud detector, or an audience-demographic tool.

### What you get

For every unique post found in your source batch that has a computable benchmark, you get one record containing:

- **`entityId`** — `id:<id>` when a valid post `id` is present in the alias cluster, otherwise `shortCode:<shortCode>` (rows connected by a shared `id` or `shortCode` are bridged into one entity first; disconnected aliases cannot be inferred to be the same post).
- **`benchmarkBasis`** — `combined` (likes+comments, the strongest read), `likes_only`, or `comments_only` — whichever metric this post actually had enough comparable data to be scored on. Anything other than `combined` always sets `partial: true`.
- **`groupKey`** and **`comparableCohortSize`** — the `<owner>|<format>` cohort this post was scored against, and how many non-conflicted posts in your batch had that basis's metric known (always ≥ 3 for a billed result).
- **`likesPercentile` / `commentsPercentile` / `combinedPercentile`** — a tie-safe mid-rank percentile (0–100) per metric, wherever that metric's cohort qualifies. An all-tied cohort reads `50`, never a spurious `0`.
- **`likesRelativeIndex` / `commentsRelativeIndex` / `combinedRelativeIndex`** — this post's value divided by its cohort's median, e.g. "2.5× the account's usual Sidecar engagement."
- **`action`** — `top_performer` (percentile ≥ 75), `weak_performer_review` (percentile ≤ 25), or `typical_performer`, suffixed with the basis name whenever it isn't `combined`.
- **`evidence`** — an entry on every billed post naming the basis, compared value, cohort size, median, and percentile — plus entries for anything unusual (a hidden count, a duplicate row, a metric from a different row than owner/type/url, an overflowing sum, an invalid URL).
- **Honest diagnostics for everything else** — a too-small cohort, disagreeing duplicate rows, a row with neither `id` nor `shortCode`, or a row the source itself reported as failed, are all free (no charge). The combined diagnostic-plus-notice list writes at most 200 entries per run; later result-size/cap notices can add free rows beyond that.

What this Actor is explicitly **not**: a reach/impressions estimate or follower-adjusted engagement rate (no follower count is read); proof of a successful paid campaign, ROI, or conversion; bot/fraud or audience-demographic inference. It never exposes commenter identities, `ownerId`, or media/photo URLs.

### Who uses it

Social media managers and paid-campaign analysts use these records to see, post by post, which pieces of a fresh export actually out- or under-performed that same account's own recent baseline — before spending time on a manual spreadsheet comparison. The output states its own sample size, basis, and confidence explicitly; it is a prioritization aid, not a live analytics dashboard and not a substitute for Instagram's own Insights (which this Actor never reads).

### How to run

1. **Console (fastest for a one-off run).** Open Input and either leave the prefilled **Source records (inline)** — six real, dated `@nasa` posts spanning two formats — or fill in **Source Dataset** with your own Instagram-scraper Dataset ID. Leave everything else at its default and hit **Start**.
2. **From an existing Instagram-scraper Dataset.** Put your Dataset ID in `datasetId` — read with your own run's permissions, no separate authorization step. Verified live against the public example Dataset `fuFnFcE7LnzPL0xLc` (9 real posts, run `h0Siy97GERQyvC1QV`): all 9 benchmarked on the `combined` basis, cohort sizes 6 (Image) and 3 (Sidecar).
3. **Chained after an upstream Instagram-scraper Actor via Integrations.** Add this Actor as an "Actor/task run" integration; Apify's UI auto-populates the payload with `{{resource.defaultDatasetId}}` — map that value explicitly into `datasetId` (see **Integration recipes**) to request `READ` access under `LIMITED_PERMISSIONS`; a payload reference alone does not grant access.
4. **Via the API.** Call `POST /v2/acts/HpnuTSqBZvFAe70CI/runs` (or `run-sync-get-dataset-items` for one synchronous call) with a JSON body containing `datasetId` (or `items`) and, for a hard spending ceiling, the run option `maxTotalChargeUsd`.
5. **Read the results.** One row per unique, benchmarked post lands in the run's default Dataset; a matching `OUTPUT`/`SUMMARY` Key-value record reports how many benchmarks were delivered, how many rows were free diagnostics, and whether a cap ended the run early.

### Pricing

Pay-per-event, one event type: **`result-found`** — one delivered post benchmark. No start fee; every free diagnostic (undersized cohort, conflicting duplicate, budget stop, empty batch) requests no charge event at all.

| Tier | Price per post benchmark | Discount |
|---|---|---|
| Free (default) | $0.012 | — |
| Bronze | $0.0108 | 10% |
| Silver | $0.0096 | 20% |
| Gold | $0.0084 | 30% |
| Platinum | $0.0084 | 30% |
| Diamond | $0.0084 | 30% |

These are Apify account pricing tiers; your applicable account plan determines the charge. One "post benchmark" is one unique, non-conflicted post with a computable basis; a conflicting-duplicate post or a too-small cohort is never billed. Upstream scraping costs (running the Instagram-scraper Actor that produced your batch) are entirely separate from this price.

Set the platform's own **Max total charge (USD)** run option to cap total spend. A positive `maxTotalChargeUsd` below the price of one benchmark correctly delivers zero paid results and one free `budget_stopped` diagnostic — see Example 3, a real verified run.

### Input contract

| Field | Type | Default | Notes |
|---|---|---|---|
| `items` | array (JSON editor), max 1000 entries | prefilled real example (6 rows) | Inline source records. Ignored if `datasetId`, `runId`, or a resolvable `payload.resource` is also given. |
| `datasetId` | string (Dataset picker, READ) | — | Dataset ID from an Instagram post export. Read with your own run's permissions. Overrides inline `items`. Public example: `fuFnFcE7LnzPL0xLc`. |
| `runId` | string, max 64 chars | — | An Actor run ID to read instead of a Dataset ID; its default Dataset resolves automatically, no elevated access. |
| `payload` | object (JSON editor) | — | Optional `ACTOR.RUN.SUCCEEDED`-shaped payload carrying `resource.defaultDatasetId`/`resource.id`. The `datasetId` resource picker is the recommended way to grant private-Dataset access — a bare payload reference alone does not grant it. |
| `maxInputRows` | integer | 100 | Hard cap on source rows examined before grouping (1–1000); still bounded to 4 MiB total / 64 KiB per row regardless. |
| `maxResults` | integer | 10 | Max useful post benchmarks this run can deliver (1–1000), independent of the platform's Max total charge run option. |

**Source precedence, exactly:** an explicit `datasetId` or `payload.resource.defaultDatasetId` (must agree if both present) beats a `runId` or `payload.resource.id`, which beats inline `items`. Never merged with inline rows. A malformed or conflicting reference is rejected as invalid input, never silently downgraded.

**Accepted row fields:** `id`/`shortCode` — string (≤190 chars, trimmed) or non-negative safe integer, joined via union-find so one post split across two rows is bridged before counting. `ownerUsername`/`type` — non-empty string ≤190 chars, cohort keys (`ownerUsername` case-insensitive for grouping; `type` exact match, `Image`/`Sidecar`/`Video`/`Reel` never mixed); non-string rejected outright. `likesCount`/`commentsCount` — a finite, non-negative **safe integer**; negative treated as unknown (Instagram sometimes hides counts), never zero; non-integer or beyond `Number.MAX_SAFE_INTEGER` is `invalid`. `timestamp` — ≤64 chars, strict calendar-valid ISO-8601 (real leap-year/day/hour/minute/second/timezone-offset ranges, never a loose regex plus `Date.parse()`). `url` — http(s) only, ≤2000 chars, echoed only when genuinely bounded. `found`/`error`/`errors`/`failed`/`status` — a failed/error/timed-out/aborted status always yields a free diagnostic, even alongside contradictory `found:true, partial:true`; a non-empty `error`/`errors` warning survives only with explicit `found:true, partial:true` and no hard failure.

Fields the source may also carry (`caption`, `hashtags`, `videoViewCount`, `ownerId`, `paidPartnership`) are never read and never appear in output — `ownerId` is deliberately never surfaced.

**A note on Instagram Profile Scraper.** This Actor's contract is a **flat, per-post row**. `apify/instagram-profile-scraper`'s own default output is **profile-shaped**: one record per account, posts nested inside a `latestPosts`-style array — not automatically a supported post row here. Flatten its nested post list into individual rows before pointing `datasetId` at it, or use its post-array output mode if offered. `apify/instagram-scraper` (behind this README's real sample — see **Sources and rights**) returns the flat per-post shape natively, no preprocessing needed.

**Hard read bounds, always enforced regardless of `maxInputRows`:** at most 1000 source rows, 4 MiB total source JSON per run, 64 KiB per row (an oversized row is dropped and disclosed). This Actor reads only the fixed `https://api.apify.com` origin with your run's own token — never an arbitrary URL, never an upstream Actor start.

### Output examples

These four outputs reproduce actual September 23 canaries from accepted build `XWhJBNjPuSWXzGKYb` (`0.1.1`), values unchanged. Run IDs: `hAYCefOQW31GBJ0w8` (1), `xfXwstMfIqbfvwYGp` (2), `vlM19lF0IZO94jUph` (3), `J3FqX4kuPCgcNcfzH` (4).

#### 1. First useful benchmark — the default inline prefill, no source capture time claimed

Actor input (the schema's own six-row default prefill, verbatim; first record shown, the remaining five follow the identical shape):

```json
{
  "items": [
    {
      "id": "3991274049559765207",
      "type": "Image",
      "shortCode": "Ddj2pn1PqDX",
      "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
      "commentsCount": 625,
      "likesCount": 171442,
      "timestamp": "2026-09-21T18:56:33.000Z",
      "ownerUsername": "nasa"
    }
  ]
}
```

First Dataset output row (of six delivered from this run — 3 Image + 3 Sidecar, each cohort exactly at the ≥3 minimum):

```json
{
  "entityId": "id:3991274049559765207",
  "found": true,
  "status": "benchmarked",
  "action": "weak_performer_review",
  "confidence": 0.9,
  "shortCode": "Ddj2pn1PqDX",
  "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
  "ownerUsername": "nasa",
  "type": "Image",
  "timestamp": "2026-09-21T18:56:33.000Z",
  "likesCount": 171442,
  "likesState": "present",
  "commentsCount": 625,
  "commentsState": "present",
  "combinedEngagement": 172067,
  "groupKey": "nasa|Image",
  "benchmarkBasis": "combined",
  "cohortSize": 3,
  "comparableCohortSize": 3,
  "likesMedian": 401824,
  "commentsMedian": 1091,
  "combinedMedian": 403011,
  "likesPercentile": 16.7,
  "commentsPercentile": 16.7,
  "combinedPercentile": 16.7,
  "likesRelativeIndex": 0.427,
  "commentsRelativeIndex": 0.573,
  "combinedRelativeIndex": 0.427,
  "duplicateSourceRowCount": 1,
  "evidence": [
    {
      "field": "combinedEngagement",
      "value": 172067,
      "rule": "benchmark_basis_combined: compared against 3 comparable post(s) in cohort \"nasa|Image\" (median 403011, percentile 16.7)",
      "sourceRowIndex": 0
    }
  ],
  "businessPartial": false,
  "sourceRowIndexes": [0],
  "partial": false,
  "sourceCoverage": { "complete": true, "reason": null, "droppedOversized": 0 },
  "product": "instagram-campaign-performance-benchmark",
  "schemaVersion": "1.0",
  "sourceDatasetId": null,
  "sourceRunId": null,
  "suppliedSourceRunId": null,
  "sourceRunIdVerified": null,
  "processedAt": "2026-09-23T05:05:06.311Z"
}
```

The six-post prefill is a curated, real 2026-09-08–2026-09-21 export from `@nasa`, unchanged since capture (see **Sources and rights**). This post's own values (171,442 likes / 625 comments) sit below its 3-post Image cohort's median (401,824 / 1,091), landing at percentile 16.7 — hence `weak_performer_review`. This run delivered all 6 posts paid with no diagnostics; the broader public Dataset (`fuFnFcE7LnzPL0xLc`, 9 posts) yields a 6-post Image and 3-post Sidecar cohort with different medians — a larger real cohort genuinely changes a post's relative standing, expected, not a defect.

#### 2. Same batch with source-admitted partial rows — a disclosed warning, not a hard failure

Actor input (identical six posts to Example 1, with `found: true, partial: true` added to every row — a source's own honest admission a row is incomplete; first record shown):

```json
{
  "items": [
    {
      "id": "3991274049559765207",
      "type": "Image",
      "shortCode": "Ddj2pn1PqDX",
      "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
      "commentsCount": 625,
      "likesCount": 171442,
      "timestamp": "2026-09-21T18:56:33.000Z",
      "ownerUsername": "nasa",
      "found": true,
      "partial": true
    }
  ]
}
```

Resulting Dataset output row for the same post (`partial: true`, an extra disclosed evidence entry, every measured value otherwise identical to Example 1):

```json
{
  "entityId": "id:3991274049559765207",
  "found": true,
  "status": "benchmarked",
  "action": "weak_performer_review",
  "confidence": 0.9,
  "shortCode": "Ddj2pn1PqDX",
  "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
  "ownerUsername": "nasa",
  "type": "Image",
  "timestamp": "2026-09-21T18:56:33.000Z",
  "likesCount": 171442,
  "likesState": "present",
  "commentsCount": 625,
  "commentsState": "present",
  "combinedEngagement": 172067,
  "groupKey": "nasa|Image",
  "benchmarkBasis": "combined",
  "cohortSize": 3,
  "comparableCohortSize": 3,
  "likesMedian": 401824,
  "commentsMedian": 1091,
  "combinedMedian": 403011,
  "likesPercentile": 16.7,
  "commentsPercentile": 16.7,
  "combinedPercentile": 16.7,
  "likesRelativeIndex": 0.427,
  "commentsRelativeIndex": 0.573,
  "combinedRelativeIndex": 0.427,
  "duplicateSourceRowCount": 1,
  "evidence": [
    {
      "field": "sourceRow",
      "value": null,
      "rule": "source_admitted_partial: source row(s) reported partial:true; any failure warning is retained only with explicit found:true; this result preserves source incompleteness",
      "sourceRowIndex": 0
    },
    {
      "field": "combinedEngagement",
      "value": 172067,
      "rule": "benchmark_basis_combined: compared against 3 comparable post(s) in cohort \"nasa|Image\" (median 403011, percentile 16.7)",
      "sourceRowIndex": 0
    }
  ],
  "businessPartial": true,
  "sourceRowIndexes": [0],
  "partial": true,
  "sourceCoverage": { "complete": true, "reason": null, "droppedOversized": 0 },
  "product": "instagram-campaign-performance-benchmark",
  "schemaVersion": "1.0",
  "sourceDatasetId": null,
  "sourceRunId": null,
  "suppliedSourceRunId": null,
  "sourceRunIdVerified": null,
  "processedAt": "2026-09-23T05:05:23.520Z"
}
```

`found: true, partial: true` together is a **disclosed warning**, not a hard failure — the post still benchmarks normally, every measured value identical to Example 1. Only `partial`/`businessPartial` flip to `true` plus one extra `source_admitted_partial` evidence entry. This run delivered all 6 posts paid, all carrying `partial: true` — matching `businessPartialResults: 6`.

#### 3. Below-price run — free `budget_stopped` diagnostic, no partial charge

```json
[
  {
    "product": "instagram-campaign-performance-benchmark",
    "schemaVersion": "1.0",
    "status": "budget_stopped",
    "reason": "Run charge limit cannot cover any result; no source was read.",
    "found": false,
    "processedAt": "2026-09-23T05:05:35.104Z"
  }
]
```

This run was started with the platform run option `maxTotalChargeUsd: 0.005` — below every pricing tier's per-benchmark price (even Diamond's $0.0084). The Actor never reads the source batch, delivers zero paid results, and writes this one free diagnostic.

#### 4. Empty batch — free `no_results` diagnostic

Actor input:

```json
{ "items": [] }
```

Dataset output:

```json
[
  {
    "product": "instagram-campaign-performance-benchmark",
    "schemaVersion": "1.0",
    "status": "no_results",
    "found": false,
    "reason": "no_usable_rows_in_batch",
    "sourceCoverage": { "complete": true, "reason": null, "droppedOversized": 0 },
    "processedAt": "2026-09-23T05:05:46.228Z"
  }
]
```

An empty or entirely-unusable batch is a free diagnostic, never a silent zero-row success and never a charge.

### Field dictionary

| Field | Type | Meaning |
|---|---|---|
| `entityId` | string | `id:<id>` when a valid `id` occurs in the bridged alias cluster; otherwise `shortCode:<shortCode>`. |
| `found` | boolean | `true` on every billed benchmark; `false` on every free diagnostic. |
| `status` | string | `"benchmarked"` on a billed post; a diagnostic reason (`invalid_input`, `source_unavailable`, `invalid_row`, `missing_identity`, `missing_group_key`, `source_row_error`, `conflicting_duplicate_source`, `insufficient_benchmark_data`, `budget_stopped`, `no_results`, `max_results_reached`, `result_dropped_oversized`, `source_rows_dropped`, `partial_source`) on a free row. |
| `benchmarkBasis` | string | `combined` | `likes_only` | `comments_only`. Non-`combined` always implies `partial: true`. |
| `groupKey` | string | `<lowercased ownerUsername>|<type>` display cohort key; grouping internally uses a separate delimiter-collision-safe key. |
| `cohortSize` / `comparableCohortSize` | number | Total posts sharing this cohort (incl. conflicts) / non-conflicted posts with the billed metric known — always ≥ 3 for a billed result. |
| `likesMedian` / `commentsMedian` / `combinedMedian` | number/null | Cohort median per metric, over posts where it's known; `null` if fewer than 3 qualify. |
| `likesPercentile` / `commentsPercentile` / `combinedPercentile` | number/null | 0–100 tie-safe mid-rank percentile per metric independently; an all-tied cohort reads 50. `null` when not computable. |
| `likesRelativeIndex` / `commentsRelativeIndex` / `combinedRelativeIndex` | number/null | This post's value ÷ cohort median, rounded to 3 decimals. `null` when not computable. |
| `likesState` / `commentsState` | string | `dataset_missing` | `observed_absent` | `negative_hidden` | `invalid` | `present`. |
| `likesCount` / `commentsCount` / `combinedEngagement` | number/null | Measured value when `present`; `combinedEngagement` also `null` if the sum would overflow `Number.MAX_SAFE_INTEGER`. |
| `action` | string | `top_performer` (≥75) | `weak_performer_review` (≤25) | `typical_performer` — suffixed `_likes_only`/`_comments_only` when basis isn't `combined`. |
| `confidence` | number | `0.9` for `combined`, `0.55` single-metric, capped `0.75` with any conflicting-duplicate exclusion. A disclosed rule label, not a probability. |
| `shortCode` / `url` | string/null | Only ever a typed, bounded value; an oversized/malformed raw field is withheld as `null`, with a `url_invalid_or_oversized` evidence entry when `url` was rejected. |
| `ownerUsername` / `type` / `timestamp` | string/null | From a valid-group occurrence in the bridged cluster. `timestamp` is `null` when missing or calendar-invalid. |
| `duplicateSourceRowCount` | number | How many bridged source rows contributed to this post. |
| `evidence` | array | Up to 50 entries, each `{ field, value, rule, sourceRowIndex }` — always the billed basis's comparison, plus anything unusual (see **Evidence and boundaries**). |
| `partial` / `businessPartial` | boolean | `businessPartial` is this module's own signal; `partial` also folds in run-level source-read incompleteness — check `partial` if you only check one flag. |
| `sourceRowIndexes` | array | Original source-batch offsets (remapped past oversized-row drops) contributing to this post. |
| `sourceCoverage` | object | Run-level: `{ complete, reason, droppedOversized }`. |
| `sourceDatasetId`, `sourceRunId`, `suppliedSourceRunId`, `sourceRunIdVerified` | string/null, boolean/null | Where the batch came from; `sourceRunId` populated only when independently verified against the Dataset. |
| `processedAt` | string (ISO 8601) | When this Actor processed the row — never a claim about when the post was captured. |
| `reason` / `error` | string | Present on free diagnostic rows only. |

**A note on `observedAt`.** The Dataset's Overview view reserves an `observedAt` column, but this Actor never populates it, and the run-level `businessSummary.observedAt` is always `null`. The Instagram post contract this Actor reads carries no "when the scraper captured this row" field distinct from `timestamp` (the post's own reported posting date) — so rather than relabel processing time as a fabricated capture time, it is left honestly empty. Use each row's `timestamp` for the post's date, and `businessSummary.observedWindow`/`timestampCoverage` for the batch's range.

**`businessSummary`** (embedded in `OUTPUT`/`SUMMARY`): `totalSourceRows`, `resultsCount`, `diagnosticsCount`, `statusBreakdown` (`{ benchmarked: N }` when benchmarks exist, or `{}` when none exist), `observedWindow.earliest`/`.latest` (min/max valid `timestamp` across unique, non-conflicted accepted posts), `acceptedPostCount` (the true denominator, not raw source rows), `timestampCoverage` (fraction with a valid `timestamp`), and `observedAt` (always `null`).

### Evidence and boundaries

**Identity is bridged before anything else runs.** Occurrences connected through shared `id` or `shortCode` aliases are merged into a single entity via union-find *before* unique-post counting or cohort assignment. An id-only row and a shortCode-only row require a connecting occurrence; disconnected aliases cannot be inferred to be one post. Only bounded, typed `id`/`shortCode` values are ever join keys. This bridging, and the conflict check below, run over **every** identity-bearing, non-error row — including one lacking a usable `ownerUsername`/`type` — *before* any row is set aside for lacking a group key, so a contradictory alias can never slip through unopposed.

**Genuinely disagreeing duplicates are excluded, never billed on a guess.** When two or more bridged rows disagree on a materially **observed** field (`ownerUsername`, `type`, `likesCount`, `commentsCount`, `timestamp` — comparing only fields **both** sides actually reported), that post is a **conflicting duplicate**: excluded from its cohort and reported as a free `conflicting_duplicate_source` diagnostic — never counted toward that cohort's ≥3 quorum. Every occurrence is compared against every other, not just source order. Remaining non-conflicted cohort members carry a `cohort_partial_exclusions` evidence entry disclosing how many posts were excluded.

**A conflict-free complementary cluster is billed from whichever row actually supplied each field.** One occurrence may report no engagement metrics while another reports likes, comments, and a timestamp — incompleteness, not a contradiction. Each field is resolved independently from whichever occurrence actually reported it; a field stays unknown only when no occurrence ever reported it, and results are identical regardless of row order. When a metric's supplying row differs from the row supplying `ownerUsername`/`type`/`url`, a `metric_aggregated_across_cluster` evidence entry names it at that field's real `sourceRowIndex`; a billed `combinedEngagement` summed from two rows names both component values and indexes.

**Grouping is exact and collision-safe.** Cohorts key on `ownerUsername.toLowerCase()` + the literal `type` string, so `NASA`/`nasa` land in one cohort, but a Reel from `@brandx` is never compared against an Image from `@brandx`, or against `@brandy`. Internally, cohort lookups use a separate, delimiter-collision-safe tuple key, never the delimited display string, so a `|` inside a raw field can never merge two distinct cohorts.

**Counts are never fabricated.** A negative `likesCount`/`commentsCount` is hidden as unknown, never zero. A non-integer or count beyond `Number.MAX_SAFE_INTEGER` is `invalid`. `combinedEngagement` requires both counts individually `present` **and** their sum itself `Number.isSafeInteger` — an overflowing sum withholds `combinedEngagement` (disclosed `combined_engagement_overflow` evidence) rather than rounding, falling back to a single-metric basis.

**Timestamps are validated against the real calendar, never a loose prefix match.** Leap years and real day/hour/minute/second/timezone-offset ranges are checked explicitly, so an impossible date like `2026-02-30` can never silently roll forward into a valid-looking date. A malformed or missing `timestamp` marks that post `partial: true` and is excluded from `observedWindow`/`timestampCoverage`.

**Aux fields never amplify a hostile input straight into output.** `url` is surfaced only when genuinely bounded (≤2000 char) http(s); otherwise withheld as `null` with a disclosed `url_invalid_or_oversized` evidence entry and forced `partial: true`. `shortCode` is only ever the already-bounded (≤190 char), typed identity value used for alias bridging.

**Bounded, disclosed caps, applied only to display, never to the underlying facts:** `evidence` caps at 50 entries per post; `sourceRowIndexes` has no separate cap. The combined diagnostic-plus-notice list writes at most 200 entries per run (`diagnosticsTruncated` flags this); later result-size/cap notices add free rows beyond it — independently verified: a 1000-row batch of 994 synthetic failures plus 6 real posts, run with `maxInputRows: 1000` and `maxResults: 1`, correctly delivered 1 paid post and 201 free rows total (994 diagnostics capped at 200, plus one `max_results_reached` notice), the surviving post's `sourceRowIndex` correctly remapped to its true original offset (`994`), not a post-drop dense index. **This fixture also exposed a real, retained limitation:** the same run with the schema's default `maxInputRows: 100` correctly read only its first 100 rows (all synthetic failures there), delivering 0 paid results and 101 free rows — it never reached a real post. That is not a probe that "passed"; it is honest evidence of what the default does on a batch shaped this way. Raise it when real posts may be preceded by many unusable rows.

**No proof of reach, ROI, or audience.** A benchmark means this post's own likes/comments sat at a given percentile against at least 3 comparable posts from the same account and format — nothing more. Not a follower-adjusted engagement rate (no follower count is read), not evidence of a successful paid campaign, not a bot/fraud signal, not an audience-demographic inference. Instagram's own counters can be publicly hidden by the poster; a `negative_hidden`/`invalid` state reflects that honestly rather than guessing.

**Delivery is not transactional.** Dataset storage precedes event charging. A lost acknowledgment can leave an unconfirmed row; the run stops without retry and can fail after some deliveries succeeded. Inspect the Dataset and summary before retrying — a new run can bill again, with no cross-run deduplication.

#### Reading the run summary

| Field | Meaning |
|---|---|
| `schemaVersion`, `product`, `outcome`, `processedAt` | Contract version, product identifier, outcome, processing time (not a post date). |
| `requested` / `usefulResults` / `delivered` | Source rows encountered / useful results after oversized-result filtering / useful Dataset writes with a confirmed complete delivery+charge check. |
| `paid` / `free` | Confirmed named `result-found` events / acknowledged diagnostic writes without one. |
| `failed` | Oversized useful result rows dropped before delivery, not a count of fatal exceptions. |
| `fatalFailure`, `errorCode` | Whether the run failed and its diagnostic code. Input-policy diagnostics can succeed with a non-null `errorCode`, so read both. |
| `deliveryUncertain` | A write/charge acknowledgment could not be confirmed; actual rows may exceed confirmed counters. |
| `replaySafety`, `replayBlocked` | Reminder a new run bills again; `replayBlocked` means this run/storage already had a claim or named events, so automatic replay was refused. |
| `budgetStopped`, `resultsCapped` | Delivery stopped by the effective charge allowance or `maxResults`. |
| `sourcePartial`, `sourcePartialReason`, `sourceDroppedOversized` | Source-read coverage limits and rows discarded for size. |
| `businessPartialResults` | Useful transform results carrying `partial: true`, before delivery filtering. |
| `oversizedDiagnosticsDropped`, `diagnosticsTruncated` | Diagnostics omitted for size or the 200-entry combined limit; later notices are outside it. |
| `partialOverall` | At least one source/output/diagnostic/business-coverage limit was recorded — does not replace `fatalFailure`. |
| `budgetMode`, `maxTotalChargeUsd` | Verified finite/unlimited limit mode; `null` when no finite verified limit is available. |
| `businessSummary` | The full module summary described in **Field dictionary** above. |

### Decision routing

- **`top_performer`** (percentile ≥ 75) — this post genuinely out-performed the account's own recent comparable posts, the strongest signal this batch can offer.
- **`weak_performer_review`** (percentile ≤ 25) — worth a manual look before drawing conclusions; reflects this account's own history, not an absolute quality judgment.
- **`typical_performer`** — between the two, including every post in an all-tied cohort (correctly percentile 50, not a false weak signal).
- **`benchmarkBasis` other than `combined`** (and `partial: true`) — the combined-engagement cohort didn't qualify, so a single metric was used instead. Real and disclosed, but narrower — check `likesState`/`commentsState` for which count is missing.
- **`confidence: 0.75` or lower** — a single-metric basis, or a conflicting-duplicate exclusion in this cohort. Weight accordingly before treating it the same as a `0.9` `combined` result.
- **Free `conflicting_duplicate_source`** — a source-data-quality signal worth investigating upstream, not a benchmark verdict.
- **Free `insufficient_benchmark_data`** — this account+format has fewer than 3 comparable posts on every basis; expand your export's date range or post count.
- **Free `budget_stopped`/`max_results_reached`** — a run-level cap was hit; re-run with a higher `maxTotalChargeUsd` or `maxResults`.

### Commercial playbooks

Filter a fresh campaign export by `action` to triage quickly: review `weak_performer_review` posts for format/timing/caption patterns, and treat `top_performer` posts as candidates for content reuse or paid amplification — citing `evidence` and the cohort median, not just the label.

Compare repeated batches using the same `entityId`/`groupKey`; a post's percentile can shift as the account publishes more posts into its cohort over time — expected, not noise. Replaying an unchanged saved batch supplies no fresh observation and bills again (see **Operating guide**). This Actor does not estimate campaign spend, reach, or ROI; pair its output with your own paid-media reporting for that half of the picture.

### Integration recipes

![Instagram campaign performance benchmark — workflow diagram](https://raw.githubusercontent.com/TimmyZinin/apify-actor-assets/a2f86b716f96fa3d68ca68b66945b34b6efdb65e/value-add-20260923/instagram-campaign-performance-benchmark/readme-workflow.webp)

This Actor's ID is **`HpnuTSqBZvFAe70CI`**. A natural upstream source is [Instagram Scraper](https://apify.com/apify/instagram-scraper) (`shu8hvrXbJbY3Eb9W`) or [Instagram Profile Scraper](https://apify.com/apify/instagram-profile-scraper) (`dSCLg0C3YEZ83HzYX`, subject to the flattening note in **Input contract**); any Actor producing the row shape in **Input contract** works identically. These recipes describe how to configure each mechanism — not a claim any trigger is currently installed on your account; a saved public example is available in the Tasks tab.

**1. Console-native chaining (no code).** On your Instagram-scraper Actor's run page, open **Integrations**, add an "Actor/task run" action targeting this Actor, and let Apify's Integrations UI populate the payload with `{{resource.defaultDatasetId}}`. Map that value explicitly into this Actor's `datasetId` field — not the generic `payload` pass-through alone — to request `READ` access under `LIMITED_PERMISSIONS`, conditional on resource-picker or integration authorization. Documented at `docs.apify.com/integrations/actors`.

**2. Direct webhook (`POST /v2/webhooks`), full recipe.** Configure a webhook on your upstream Instagram-scraper Actor for `ACTOR.RUN.SUCCEEDED`, scoped via `condition.actorId`, targeting this Actor's run-creation endpoint:

```json
{
  "isApifyIntegration": true,
  "shouldInterpolateStrings": true,
  "eventTypes": ["ACTOR.RUN.SUCCEEDED"],
  "condition": { "actorId": "shu8hvrXbJbY3Eb9W" },
  "requestUrl": "https://api.apify.com/v2/acts/HpnuTSqBZvFAe70CI/runs?maxTotalChargeUsd=0.50",
  "doNotRetry": true,
  "headersTemplate": "{\"Authorization\": \"Bearer <APIFY_TOKEN>\"}",
  "payloadTemplate": "{\"datasetId\": \"{{resource.defaultDatasetId}}\", \"payload\": {\"resource\": {\"defaultDatasetId\": \"{{resource.defaultDatasetId}}\", \"id\": \"{{resource.id}}\"}}, \"maxResults\": 25}"
}
```

Submit to `POST https://api.apify.com/v2/webhooks` with your own `Authorization: Bearer <APIFY_TOKEN>` header — the placeholder is filled in by whichever secrets-management step provisions the webhook, never hardcoded into the template or a URL query string. `doNotRetry: true` avoids a duplicate-charge risk from an automatic retry. A resource-picker selection or integration can request scoped `READ` access; the raw `datasetId` string and `payload.resource` alone do not grant it. A positive `maxTotalChargeUsd` on the request URL caps this chained run's spend.

**3. Generic automation tools (n8n, Zapier, Make, or a spreadsheet export).** Call `run-sync-get-dataset-items` on this Actor's ID with a JSON body containing `datasetId` and your chosen `maxResults`/`maxInputRows` — a plain authenticated HTTPS POST. Or export any finished run's Dataset via `GET /v2/datasets/{datasetId}/items?format=csv` and map `entityId`, `groupKey`, `benchmarkBasis`, `combinedPercentile`, `action`, and `partial` into a spreadsheet.

Being publicly searchable as an integration target (once public) does not imply a recommended-placement partnership with any specific upstream Actor — no outreach to a third party was performed to produce this README.

### Operating guide

1. **Confirm your source batch shape first.** Spot-check a few rows against **Input contract** — each needs an `id` or `shortCode`, an `ownerUsername`, and a `type`.
2. **Start with a small `maxResults` on a new source.** Set it low (e.g. 5) to confirm the output matches expectations before a full batch.
3. **Set `maxTotalChargeUsd` deliberately.** Use the platform run option, not an Actor input field. A value below one tier's per-benchmark price guarantees zero paid results and a free `budget_stopped` diagnostic (Example 3).
4. **Read `OUTPUT`/`SUMMARY`, not just the Dataset row count.** It reports `requested`/`delivered`/`paid`/`free`/`failed`, whether `budgetStopped`/`resultsCapped` ended the run early, `diagnosticsTruncated`, and `sourcePartial` completeness — e.g. when `maxInputRows` truncated a larger batch before reaching your real posts (raise it if `sourcePartialReason: "max_input_rows_reached"` appears with fewer benchmarks than expected — see the mixed-boundary fixture in **Evidence and boundaries**).
5. **If a run finalizes `FAILED`, inspect before retrying.** Check the Dataset and `OUTPUT` for what was actually delivered/charged before re-running — a blind retry can duplicate already-successful paid benchmarks.
6. **Re-running is always new billing.** No dedup key across runs — reserve re-runs for a genuinely new or updated export.
7. **Use `comparableCohortSize` alongside the percentile.** A percentile against 3 posts is a real, honest read, but thinner than one against 20 — both bill identically, so weigh the cohort size yourself.

### FAQ

**Does this Actor scrape Instagram itself?** No. It only reads an existing post export you or an upstream Actor already collected — never fetches a page from Instagram, never starts another Actor.

**Can I use a source other than Instagram Scraper?** Yes — any source producing rows with the fields in **Input contract** works identically. See the Instagram Profile Scraper flattening note if your source returns a nested, profile-shaped record.

**Does a benchmark prove a post reached more people or performed better in an ad sense?** No. It means this post's own likes/comments sat at a given percentile against at least 3 comparable posts from the same account and format — nothing about reach, impressions, follower-adjusted engagement rate, or paid-campaign ROI.

**Why do some posts get `likes_only` or `comments_only` instead of `combined`?** Their combined-engagement cohort didn't have 3 qualifying posts, or this post's own likes or comments were unknown — the Actor never fabricates a combined number.

**What happens to a post whose duplicate source rows disagree?** A free `conflicting_duplicate_source` diagnostic, excluded entirely from its cohort's statistics — never billed on an arbitrary first-row guess.

**Is a cohort of exactly 3 posts as reliable as one of 20?** Both bill the same way (≥ 3 is the minimum, not a target), but `comparableCohortSize` tells you exactly how many posts the median/percentile were computed from.

**Does re-running the same batch avoid double-billing?** No. Every run is independent with no cross-run deduplication.

**What does a `FAILED` run mean for what was actually delivered?** A pricing, budget, ledger, source, algorithm, delivery, free-write or summary-persistence failure stopped the run. Some rows may already have been delivered or charged. Inspect the Dataset, available `OUTPUT` record and run logs before retrying.

**Is the public example Dataset (`fuFnFcE7LnzPL0xLc`) something I should point production traffic at?** No — a small, curated real example for trying the Actor without your own source.

**Why do I see fewer than 200 free diagnostic rows even though my batch had many more unmatched rows?** The combined-list cap is 200; later result-size/cap notices are additional (see **Evidence and boundaries**).

### Sources and rights

This Actor reads only Datasets and runs your own Apify account token already has permission to read; it never uses another user's credentials and never starts an upstream Actor on your behalf. The public prefill contains six real `@nasa` posts (three `Image`, three `Sidecar`, post dates 2026-09-08 to 2026-09-21). The broader public example Dataset (`fuFnFcE7LnzPL0xLc`) contains nine posts (six `Image`, three `Sidecar`, post dates 2026-09-08 to 2026-09-22). Both are curated, non-sensitive source snapshots originally captured by an upstream `apify/instagram-scraper` run (`sourceActorId shu8hvrXbJbY3Eb9W`, `sourceRunId ihXlFVzJhgdIQrjRJ`, `sourceDatasetId yh6mJRFTATd9ABSJR`), reused with its original values and timestamps unchanged — a saved example, not a live re-scrape, containing only allowlisted public post fields (no commenter identities, no media). Every output value shown in this README is copied verbatim from real runs of this Actor's accepted build; none are illustrative or invented. This README makes no claim about a post's current, live counter values — Instagram's own counters can change, or be hidden by the poster, after capture.

#### Related tools

Related tools for adjacent workflows in social platforms and Instagram data collection. The first three are this project's own Actors for adjacent Instagram/social workflows; the last two are the official Apify Actors this Actor reads its source data from (see **Input contract**, **Integration recipes**).

| Actor | What it does |
|---|---|
| [Instagram Public Posts Scraper](https://apify.com/zinin/instagram-public-posts-scraper) | Scrape current public Instagram posts and reels, captions, media links, and source URLs from logged-out pages — a source this Actor can benchmark directly. |
| [Social Preview Checker](https://apify.com/zinin/social-preview-checker) | Audit observed Open Graph and Twitter Card metadata for up to 100 authorized public pages. |
| [TikTok Public Videos & Profiles Scraper](https://apify.com/zinin/tiktok-public-videos-profiles-scraper) | Scrape public TikTok video cards, play counts, and current creator profile metrics from official embed endpoints. |
| [Instagram Scraper](https://apify.com/apify/instagram-scraper) | The official Apify Actor that produced this README's real captured sample — the flat per-post row shape this Actor reads natively. |
| [Instagram Profile Scraper](https://apify.com/apify/instagram-profile-scraper) | The official Apify Actor for profile-level Instagram data — its nested post list needs flattening before use here (see **Input contract**). |

# Actor input Schema

## `items` (type: `array`):

Small real public example: https://api.apify.com/v2/datasets/fuFnFcE7LnzPL0xLc/items?clean=true . This saved snapshot is not a new scrape.

## `datasetId` (type: `string`):

Read an existing source dataset with your run permissions. Overrides inline items. The resource picker can request scoped READ permission. Integration mapping must use an authorized resource; a plain Dataset ID or webhook payload alone does not grant access. Public example: fuFnFcE7LnzPL0xLc.

## `runId` (type: `string`):

Optional Actor run ID to read instead of Source Dataset. Its default Dataset is resolved with your run's own permissions — no elevated access is used, and no upstream Actor is started.

## `maxInputRows` (type: `integer`):

Maximum source records examined before grouping. At most 1000 rows, 4 MiB total and 64 KiB per row. Capped or incomplete source coverage is reported.

## `maxResults` (type: `integer`):

Maximum useful post benchmark results delivered, independently of the platform Max total charge setting. Free diagnostics are reported separately.

## `payload` (type: `object`):

Optional ACTOR.RUN.SUCCEEDED event payload with resource.defaultDatasetId and resource.id. Dataset resourcePicker is recommended for private datasets; a payload alone does not grant access.

## Actor input object example

```json
{
  "items": [
    {
      "id": "3991274049559765207",
      "type": "Image",
      "shortCode": "Ddj2pn1PqDX",
      "caption": "Good night, everyone😴\n \n@astro_jessica snapped this photo of the United States at night on Sept. 8, 2026, with city lights looking toward New York City (at center).\n \n#NASA #SpaceStation #Earth",
      "hashtags": [
        "NASA",
        "SpaceStation",
        "Earth"
      ],
      "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
      "commentsCount": 625,
      "likesCount": 171442,
      "timestamp": "2026-09-21T18:56:33.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3987552875446548478",
      "type": "Sidecar",
      "shortCode": "DdWojaYFDf-",
      "caption": "The boosters for Artemis III are almost stacked!\n \nThese boosters will contribute over 75% of the Space Launch System’s total rocket thrust at launch, providing the power needed to propel the Artemis III crew on their mission in low Earth orbit.\n \n#NASA #ArtemisIII #WIPWednesday",
      "hashtags": [
        "NASA",
        "ArtemisIII",
        "WIPWednesday"
      ],
      "url": "https://www.instagram.com/p/DdWojaYFDf-/",
      "commentsCount": 651,
      "likesCount": 184365,
      "timestamp": "2026-09-16T15:42:47.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3988961919403244082",
      "type": "Image",
      "shortCode": "Ddbo7s0lzoy",
      "caption": "No matter where you are, we all see the same Moon. 🌕\n\nSept. 19 is International Observe the Moon Night, an annual celebration dedicated to our closest celestial neighbor.\n\n#Moon #Moongazing #ObserveTheMoon",
      "hashtags": [
        "Moon",
        "Moongazing",
        "ObserveTheMoon"
      ],
      "url": "https://www.instagram.com/p/Ddbo7s0lzoy/",
      "commentsCount": 1187,
      "likesCount": 401824,
      "timestamp": "2026-09-18T14:22:23.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3988274761411540133",
      "type": "Sidecar",
      "shortCode": "DdZMsPElzSl",
      "caption": "The universe, but fashion⁣\n\nFamous for its broad central bulge and dark outer dust ring, the Sombrero Galaxy sits nearly edge-on to Earth. Studying it may help us better understand how a galaxy's outer cloud of stars grows alongside its inner disk.\n\n#NASA #Galaxy #Space",
      "hashtags": [
        "NASA",
        "Galaxy",
        "Space"
      ],
      "url": "https://www.instagram.com/p/DdZMsPElzSl/",
      "commentsCount": 1064,
      "likesCount": 462220,
      "timestamp": "2026-09-17T15:37:16.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3986255392669277466",
      "type": "Image",
      "shortCode": "DdSBijYCZ0a",
      "caption": "2 Fast 2 Furious 🏎️\n\n@NASAChandraXray captured two galaxies merging at a furious rate (in a cosmic sense). Not only do they look cool, they're also scientifically important: They can teach us how powerful galaxy collisions shaped the early universe.\n\n#NASA #Telescope #Galaxies #Family",
      "hashtags": [
        "NASA",
        "Telescope",
        "Galaxies",
        "Family"
      ],
      "url": "https://www.instagram.com/p/DdSBijYCZ0a/",
      "commentsCount": 1091,
      "likesCount": 448527,
      "timestamp": "2026-09-14T20:45:06.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3983374110243288826",
      "type": "Sidecar",
      "shortCode": "DdHyaYAifb6",
      "caption": "Cementing their names in history.\n\nThe Artemis III crew is leaving their mark — literally. The astronauts recently signed their names on the hardware that will be inside their Orion spacecraft during their low Earth orbit mission, launching in 2027.\n\nImage descriptions:\n\n1. The Artemis III primary and back-up crew members pose for a photograph insi",
      "hashtags": [],
      "url": "https://www.instagram.com/p/DdHyaYAifb6/",
      "commentsCount": 626,
      "likesCount": 110136,
      "timestamp": "2026-09-10T21:20:24.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    }
  ],
  "maxInputRows": 100,
  "maxResults": 10
}
```

# Actor output Schema

## `results` (type: `string`):

API URL for the default dataset items produced by this run.

## `summary` (type: `string`):

API URL for the OUTPUT record in the default key-value store.

# 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 = {
    "items": [
        {
            "id": "3991274049559765207",
            "type": "Image",
            "shortCode": "Ddj2pn1PqDX",
            "caption": "Good night, everyone😴\n \n@astro_jessica snapped this photo of the United States at night on Sept. 8, 2026, with city lights looking toward New York City (at center).\n \n#NASA #SpaceStation #Earth",
            "hashtags": [
                "NASA",
                "SpaceStation",
                "Earth"
            ],
            "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
            "commentsCount": 625,
            "likesCount": 171442,
            "timestamp": "2026-09-21T18:56:33.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "id": "3987552875446548478",
            "type": "Sidecar",
            "shortCode": "DdWojaYFDf-",
            "caption": "The boosters for Artemis III are almost stacked!\n \nThese boosters will contribute over 75% of the Space Launch System’s total rocket thrust at launch, providing the power needed to propel the Artemis III crew on their mission in low Earth orbit.\n \n#NASA #ArtemisIII #WIPWednesday",
            "hashtags": [
                "NASA",
                "ArtemisIII",
                "WIPWednesday"
            ],
            "url": "https://www.instagram.com/p/DdWojaYFDf-/",
            "commentsCount": 651,
            "likesCount": 184365,
            "timestamp": "2026-09-16T15:42:47.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "id": "3988961919403244082",
            "type": "Image",
            "shortCode": "Ddbo7s0lzoy",
            "caption": "No matter where you are, we all see the same Moon. 🌕\n\nSept. 19 is International Observe the Moon Night, an annual celebration dedicated to our closest celestial neighbor.\n\n#Moon #Moongazing #ObserveTheMoon",
            "hashtags": [
                "Moon",
                "Moongazing",
                "ObserveTheMoon"
            ],
            "url": "https://www.instagram.com/p/Ddbo7s0lzoy/",
            "commentsCount": 1187,
            "likesCount": 401824,
            "timestamp": "2026-09-18T14:22:23.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "id": "3988274761411540133",
            "type": "Sidecar",
            "shortCode": "DdZMsPElzSl",
            "caption": "The universe, but fashion⁣\n\nFamous for its broad central bulge and dark outer dust ring, the Sombrero Galaxy sits nearly edge-on to Earth. Studying it may help us better understand how a galaxy's outer cloud of stars grows alongside its inner disk.\n\n#NASA #Galaxy #Space",
            "hashtags": [
                "NASA",
                "Galaxy",
                "Space"
            ],
            "url": "https://www.instagram.com/p/DdZMsPElzSl/",
            "commentsCount": 1064,
            "likesCount": 462220,
            "timestamp": "2026-09-17T15:37:16.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "id": "3986255392669277466",
            "type": "Image",
            "shortCode": "DdSBijYCZ0a",
            "caption": "2 Fast 2 Furious 🏎️\n\n@NASAChandraXray captured two galaxies merging at a furious rate (in a cosmic sense). Not only do they look cool, they're also scientifically important: They can teach us how powerful galaxy collisions shaped the early universe.\n\n#NASA #Telescope #Galaxies #Family",
            "hashtags": [
                "NASA",
                "Telescope",
                "Galaxies",
                "Family"
            ],
            "url": "https://www.instagram.com/p/DdSBijYCZ0a/",
            "commentsCount": 1091,
            "likesCount": 448527,
            "timestamp": "2026-09-14T20:45:06.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        },
        {
            "id": "3983374110243288826",
            "type": "Sidecar",
            "shortCode": "DdHyaYAifb6",
            "caption": "Cementing their names in history.\n\nThe Artemis III crew is leaving their mark — literally. The astronauts recently signed their names on the hardware that will be inside their Orion spacecraft during their low Earth orbit mission, launching in 2027.\n\nImage descriptions:\n\n1. The Artemis III primary and back-up crew members pose for a photograph insi",
            "hashtags": [],
            "url": "https://www.instagram.com/p/DdHyaYAifb6/",
            "commentsCount": 626,
            "likesCount": 110136,
            "timestamp": "2026-09-10T21:20:24.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": null,
            "paidPartnership": false,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": true,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
            }
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/instagram-campaign-performance-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 = { "items": [
        {
            "id": "3991274049559765207",
            "type": "Image",
            "shortCode": "Ddj2pn1PqDX",
            "caption": """Good night, everyone😴
 
@astro_jessica snapped this photo of the United States at night on Sept. 8, 2026, with city lights looking toward New York City (at center).
 
#NASA #SpaceStation #Earth""",
            "hashtags": [
                "NASA",
                "SpaceStation",
                "Earth",
            ],
            "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
            "commentsCount": 625,
            "likesCount": 171442,
            "timestamp": "2026-09-21T18:56:33.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "id": "3987552875446548478",
            "type": "Sidecar",
            "shortCode": "DdWojaYFDf-",
            "caption": """The boosters for Artemis III are almost stacked!
 
These boosters will contribute over 75% of the Space Launch System’s total rocket thrust at launch, providing the power needed to propel the Artemis III crew on their mission in low Earth orbit.
 
#NASA #ArtemisIII #WIPWednesday""",
            "hashtags": [
                "NASA",
                "ArtemisIII",
                "WIPWednesday",
            ],
            "url": "https://www.instagram.com/p/DdWojaYFDf-/",
            "commentsCount": 651,
            "likesCount": 184365,
            "timestamp": "2026-09-16T15:42:47.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "id": "3988961919403244082",
            "type": "Image",
            "shortCode": "Ddbo7s0lzoy",
            "caption": """No matter where you are, we all see the same Moon. 🌕

Sept. 19 is International Observe the Moon Night, an annual celebration dedicated to our closest celestial neighbor.

#Moon #Moongazing #ObserveTheMoon""",
            "hashtags": [
                "Moon",
                "Moongazing",
                "ObserveTheMoon",
            ],
            "url": "https://www.instagram.com/p/Ddbo7s0lzoy/",
            "commentsCount": 1187,
            "likesCount": 401824,
            "timestamp": "2026-09-18T14:22:23.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "id": "3988274761411540133",
            "type": "Sidecar",
            "shortCode": "DdZMsPElzSl",
            "caption": """The universe, but fashion⁣

Famous for its broad central bulge and dark outer dust ring, the Sombrero Galaxy sits nearly edge-on to Earth. Studying it may help us better understand how a galaxy's outer cloud of stars grows alongside its inner disk.

#NASA #Galaxy #Space""",
            "hashtags": [
                "NASA",
                "Galaxy",
                "Space",
            ],
            "url": "https://www.instagram.com/p/DdZMsPElzSl/",
            "commentsCount": 1064,
            "likesCount": 462220,
            "timestamp": "2026-09-17T15:37:16.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "id": "3986255392669277466",
            "type": "Image",
            "shortCode": "DdSBijYCZ0a",
            "caption": """2 Fast 2 Furious 🏎️

@NASAChandraXray captured two galaxies merging at a furious rate (in a cosmic sense). Not only do they look cool, they're also scientifically important: They can teach us how powerful galaxy collisions shaped the early universe.

#NASA #Telescope #Galaxies #Family""",
            "hashtags": [
                "NASA",
                "Telescope",
                "Galaxies",
                "Family",
            ],
            "url": "https://www.instagram.com/p/DdSBijYCZ0a/",
            "commentsCount": 1091,
            "likesCount": 448527,
            "timestamp": "2026-09-14T20:45:06.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
        {
            "id": "3983374110243288826",
            "type": "Sidecar",
            "shortCode": "DdHyaYAifb6",
            "caption": """Cementing their names in history.

The Artemis III crew is leaving their mark — literally. The astronauts recently signed their names on the hardware that will be inside their Orion spacecraft during their low Earth orbit mission, launching in 2027.

Image descriptions:

1. The Artemis III primary and back-up crew members pose for a photograph insi""",
            "hashtags": [],
            "url": "https://www.instagram.com/p/DdHyaYAifb6/",
            "commentsCount": 626,
            "likesCount": 110136,
            "timestamp": "2026-09-10T21:20:24.000Z",
            "ownerUsername": "nasa",
            "ownerId": "528817151",
            "videoViewCount": None,
            "paidPartnership": False,
            "_exampleProvenance": {
                "sourceActorId": "shu8hvrXbJbY3Eb9W",
                "sourceRunId": "ihXlFVzJhgdIQrjRJ",
                "sourceDatasetId": "yh6mJRFTATd9ABSJR",
                "curatedPublicSnapshot": True,
                "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities.",
            },
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("zinin/instagram-campaign-performance-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 '{
  "items": [
    {
      "id": "3991274049559765207",
      "type": "Image",
      "shortCode": "Ddj2pn1PqDX",
      "caption": "Good night, everyone😴\\n \\n@astro_jessica snapped this photo of the United States at night on Sept. 8, 2026, with city lights looking toward New York City (at center).\\n \\n#NASA #SpaceStation #Earth",
      "hashtags": [
        "NASA",
        "SpaceStation",
        "Earth"
      ],
      "url": "https://www.instagram.com/p/Ddj2pn1PqDX/",
      "commentsCount": 625,
      "likesCount": 171442,
      "timestamp": "2026-09-21T18:56:33.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3987552875446548478",
      "type": "Sidecar",
      "shortCode": "DdWojaYFDf-",
      "caption": "The boosters for Artemis III are almost stacked!\\n \\nThese boosters will contribute over 75% of the Space Launch System’s total rocket thrust at launch, providing the power needed to propel the Artemis III crew on their mission in low Earth orbit.\\n \\n#NASA #ArtemisIII #WIPWednesday",
      "hashtags": [
        "NASA",
        "ArtemisIII",
        "WIPWednesday"
      ],
      "url": "https://www.instagram.com/p/DdWojaYFDf-/",
      "commentsCount": 651,
      "likesCount": 184365,
      "timestamp": "2026-09-16T15:42:47.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3988961919403244082",
      "type": "Image",
      "shortCode": "Ddbo7s0lzoy",
      "caption": "No matter where you are, we all see the same Moon. 🌕\\n\\nSept. 19 is International Observe the Moon Night, an annual celebration dedicated to our closest celestial neighbor.\\n\\n#Moon #Moongazing #ObserveTheMoon",
      "hashtags": [
        "Moon",
        "Moongazing",
        "ObserveTheMoon"
      ],
      "url": "https://www.instagram.com/p/Ddbo7s0lzoy/",
      "commentsCount": 1187,
      "likesCount": 401824,
      "timestamp": "2026-09-18T14:22:23.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3988274761411540133",
      "type": "Sidecar",
      "shortCode": "DdZMsPElzSl",
      "caption": "The universe, but fashion⁣\\n\\nFamous for its broad central bulge and dark outer dust ring, the Sombrero Galaxy sits nearly edge-on to Earth. Studying it may help us better understand how a galaxy'\''s outer cloud of stars grows alongside its inner disk.\\n\\n#NASA #Galaxy #Space",
      "hashtags": [
        "NASA",
        "Galaxy",
        "Space"
      ],
      "url": "https://www.instagram.com/p/DdZMsPElzSl/",
      "commentsCount": 1064,
      "likesCount": 462220,
      "timestamp": "2026-09-17T15:37:16.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3986255392669277466",
      "type": "Image",
      "shortCode": "DdSBijYCZ0a",
      "caption": "2 Fast 2 Furious 🏎️\\n\\n@NASAChandraXray captured two galaxies merging at a furious rate (in a cosmic sense). Not only do they look cool, they'\''re also scientifically important: They can teach us how powerful galaxy collisions shaped the early universe.\\n\\n#NASA #Telescope #Galaxies #Family",
      "hashtags": [
        "NASA",
        "Telescope",
        "Galaxies",
        "Family"
      ],
      "url": "https://www.instagram.com/p/DdSBijYCZ0a/",
      "commentsCount": 1091,
      "likesCount": 448527,
      "timestamp": "2026-09-14T20:45:06.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    },
    {
      "id": "3983374110243288826",
      "type": "Sidecar",
      "shortCode": "DdHyaYAifb6",
      "caption": "Cementing their names in history.\\n\\nThe Artemis III crew is leaving their mark — literally. The astronauts recently signed their names on the hardware that will be inside their Orion spacecraft during their low Earth orbit mission, launching in 2027.\\n\\nImage descriptions:\\n\\n1. The Artemis III primary and back-up crew members pose for a photograph insi",
      "hashtags": [],
      "url": "https://www.instagram.com/p/DdHyaYAifb6/",
      "commentsCount": 626,
      "likesCount": 110136,
      "timestamp": "2026-09-10T21:20:24.000Z",
      "ownerUsername": "nasa",
      "ownerId": "528817151",
      "videoViewCount": null,
      "paidPartnership": false,
      "_exampleProvenance": {
        "sourceActorId": "shu8hvrXbJbY3Eb9W",
        "sourceRunId": "ihXlFVzJhgdIQrjRJ",
        "sourceDatasetId": "yh6mJRFTATd9ABSJR",
        "curatedPublicSnapshot": true,
        "redaction": "Allowlisted public business/product fields only; review excerpts and social captions truncated; no reviewer identities."
      }
    }
  ]
}' |
apify call zinin/instagram-campaign-performance-benchmark --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zinin/instagram-campaign-performance-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/HpnuTSqBZvFAe70CI/builds/WtEKJ35s0lsBcBtK2/openapi.json
