# Instagram Reels Scraper: Likes, Views, Comments & Followers (`tictechid/vanzi-instagram-scraper`) Actor

Scrape recent reels from public Instagram profiles to JSON: likes, views, comments, post date and URL per reel, plus follower, following and post counts. Add a date cutoff, or use enrich mode for photo and carousel posts with captions. No login; falls back to residential proxy when blocked.

- **URL**: https://apify.com/tictechid/vanzi-instagram-scraper.md
- **Developed by:** [TicTech](https://apify.com/tictechid) (community)
- **Categories:** Social media, Videos, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

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

## Instagram Reels Scraper: Likes, Views, Comments & Followers

Scrape recent reels from public Instagram profile URLs into JSON: like, view/play and comment counts, shortcode and URL per reel, plus one profile row with follower, following and post counts. Bulk profile lists, no login. Blocked profiles are retried automatically on a fallback route.

**What you put in:** public profile URLs (e.g. `https://www.instagram.com/ksi/`). Direct `/p/` and `/reel/` URLs also work. **No hashtag, place, or keyword search input** — this Actor is for known profiles and posts.

> **Note:** Only **public** profiles and posts. If a URL returns nothing (removed/renamed account, private account, login wall) you get one **uncharged status row** (`media_type: "error"`) with the reason, and the run still completes.

### Why Use This Tool?

- **Automate Instagram reporting:** Replace manual screenshots with structured data.
- **Bulk creator lists:** Run dozens of profile URLs in a single Apify job.
- **Profile + content together:** Each profile URL scrapes **profile metadata once** (followers, following, post count) even when there are **no new reels/posts** in your date window.
- **Stack-friendly output:** Snake_case JSON for Sheets, warehouses, n8n/Make, or internal APIs.
- **Lean by design:** HTTP + TLS impersonation — no heavy browser farm; Apify Proxy handles anti-block.

### Why Choose This Actor?

- **Reels-focused:** recent reels per profile with like, view/play and comment counts
- **Always-on profile row:** `media_type: "profile"` so account metrics stay updated
- **Date filter (`until`):** Keep only content newer than a date for monthly monitoring
- **Soft-fail per URL:** One blocked profile does not kill the bulk run, and you see why in a status row
- **Apify-native:** Console, schedules, webhooks, API, Make, n8n, Zapier
- **PPE pricing:** Predictable start + per-result billing

### Features

- Scrape **Instagram profile URLs** and **direct post/reel URLs**
- **Bulk `start_urls`** in one run (deduped within a run, including after platform restarts)
- **Profile metadata scraped once per profile** (followers, following, posts count, handle, display name)
- Reel fields: shortcode, URL, likes, views/plays, comments, `posted_at` (from the media ID), author, handle, product type; caption when it appears in the profile grid. `posted_at` is filled for every reel; **`enrich_details: true` adds the exact `taken_at` time, all captions, and photo/carousel posts with their counts**
- Optional **`until`** date filter (ISO / `YYYY-MM-DD`)
- Apify Proxy by default with an **automatic fallback**: a blocked profile is retried on a fallback route, and after 2 blocks in a row the rest of the run uses that route; custom `proxyUrls` OK
- **`enrich_details` off by default** — skips per-post page fetches; reels already carry likes/views/comments
- Dataset export: JSON, CSV, Excel

### Use Cases

- **Brand & competitor monitoring** on Instagram
- **Influencer outreach** — follower counts + recent reel performance
- **Agency dashboards** — scheduled Apify runs into Sheets / Looker
- **Content archives** for captions, URLs, and engagement history
- **E‑commerce / DTC** social proof and creator tracking

### Input Example

```json
{
  "start_urls": [
    "https://www.instagram.com/ksi/",
    "https://www.instagram.com/reel/DdKDOY9iWFc/"
  ],
  "max_items": 100,
  "until": "2026-09-01",
  "enrich_details": false,
  "useResidential": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

| Field | What it does |
| --- | --- |
| `start_urls` | Profile and/or `/p/` · `/reel/` URLs (required) |
| `max_items` | Cap on dataset items (default 20; `0` = safe ceiling 5000). Free-tier tip: keep **≤ 100** |
| `until` | Optional — keep reels/posts **newer than** this date (works without `enrich_details`; dates come from the media ID) |
| `enrich_details` | Optional — fetch each post/reel page for exact date, caption, and grid photo/carousel posts with counts (default **false**) |
| `emit_status_rows` | Default **true** — one uncharged `media_type: "error"` row per URL that returns nothing, with the reason |
| `useResidential` | Default **false** — not needed for blocks: if a profile is blocked, it is retried on a fallback (residential) route, and after 2 blocks in a row the rest of the run uses that route. Set true to use it from the start for every profile |
| `proxyConfiguration` | Default Apify Proxy with the automatic fallback. Custom `proxyUrls` OK (no automatic fallback) |

### Output Examples

**Profile metadata** (one row per profile URL):

```json
{
  "id": "1234567890",
  "media_type": "profile",
  "platform": "instagram",
  "handle": "ksi",
  "author": "KSI",
  "url": "https://www.instagram.com/ksi/",
  "follower_count": 9500000,
  "following_count": 400,
  "posts_count": 1200
}
```

**Reel / post metadata:**

```json
{
  "url": "https://www.instagram.com/reel/DdKDOY9iWFc/",
  "caption": null,
  "posted_at": "2026-09-18T11:02:41Z",
  "posted_at_source": "media_id",
  "like_count": 29372,
  "view_count": 1325401,
  "play_count": 1325401,
  "comment_count": 144,
  "author": "ksi",
  "handle": "ksi",
  "media_type": "reel",
  "platform": "instagram"
}
```

**Status row** (not charged) for a URL with no data:

```json
{
  "media_type": "error",
  "input_url": "https://www.instagram.com/some.removed.account/",
  "handle": "some.removed.account",
  "error": "not_found",
  "error_message": "Profile/post not available (removed, renamed, deactivated or never existed).",
  "charged": false
}
```

#### Output field notes

| Field | Meaning |
| --- | --- |
| `media_type` | `profile` for the account row, `reel` for reels, `image` / `carousel` / `video` for grid posts (with `enrich_details`), `error` for uncharged status rows |
| `product_type` | Instagram's own product label for the post when exposed (e.g. `clips` for reels) |
| `view_count` / `play_count` | Video/reel views or plays as exposed by Instagram; `null` for photos or when not shown |
| `posted_at` | Filled for every reel. `posted_at_source` is `media_id` (upload time from the Instagram media ID, usually within minutes) or `taken_at` (exact, with `enrich_details`) |
| `caption` | Filled when the reel also appears in the profile grid; `enrich_details` fills the rest |
| `share_count` | Always `null`: Instagram does not show share counts to logged-out visitors |
| `follower_count` | Exact count from Instagram's page data. New or inactive accounts can really have 0 |

### How to Run on Apify

1. Open **Instagram Scraper** on Apify and click **Try for free** / **Start**.
2. Paste public Instagram profile or post/reel URLs into **start_urls**.
3. Set **max_items** (≤ 100 on free tier). Optionally set **until**.
4. Keep **Apify Proxy** on. If a profile is blocked, the Actor retries it on a fallback route, and after 2 blocks in a row the rest of the run uses that route. Rotate/backoff is automatic on HTTP 429.
5. Run and download the **Dataset** — profile row first, then reels, per profile. Check the run's status message for URLs with no data.
6. Wire to schedules, webhooks, or Make / n8n / Zapier for recurring brand scrapes.

#### Run from your stack (API sketch)

```bash
curl -X POST "https://api.apify.com/v2/acts/tictechid~vanzi-instagram-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"start_urls":["https://www.instagram.com/ksi/"],"max_items":50,"proxyConfiguration":{"useApifyProxy":true}}'
```

Use the Actor id with a **`~`** in API paths: `tictechid~vanzi-instagram-scraper`.

### Pricing

Pay-per-event (PPE):

- **`actor-start`** — once per run
- **`result`** — once per dataset item with data (including profile rows). Status rows (`media_type: "error"`) and rows without any data are not charged. A run restarted by the platform is not charged a second start fee or for rows it already delivered

Current list price: **$0.40 per 1,000 results** plus **$0.0005 per run start**. Check **Pricing** on the Actor page for the live price.

### Usage Limits

- **Free tier:** Run as often as you like within your monthly Apify free platform credit — there is no Actor-side run-count cap. Tip: free tier max items per run ≤ 100.
- **Paid plans:** Larger runs and higher volume, limited only by your Apify plan's credit and concurrency.

> Need more credit or concurrency? See [Apify Pricing](https://apify.com/pricing?fpr=maxknj).

### FAQ

**Do I need an Instagram login?** No — public HTML only.

**Do I need a residential proxy?** No setting needed. If Instagram blocks a profile, the Actor retries it on a **fallback (residential) route**. After 2 blocks in a row, the rest of the run uses that route directly. If there is still nothing, you get a status row with the reason and the run finishes SUCCEEDED. Set `useResidential` to use the fallback route from the start. Custom `proxyUrls` are also supported.

**Why was my run expensive?** Per-post page fetches only happen with `enrich_details: true`, and `until` no longer needs them. Keep `enrich_details` off for routine monitoring.

**What if there are no new reels this month?** You still get the **profile metadata** row so follower/post counts update.

**Empty dataset or missing profiles?** Look at the status rows (`media_type: "error"`) or `FAILED_TARGETS` in the run's key-value store. `not_found` means Instagram shows its "page isn't available" page for that handle (removed, renamed or deactivated: check the handle). `blocked` means a login wall or rate limit, so retry later. One bad URL won't fail the whole bulk run.

**Why do some profiles show 0 followers?** That is the number Instagram itself shows for that account (new or inactive accounts), not a parse error.

**Support:** Open an Issue on the Actor page or email **contact@tictech.id**.

***

For more details, contact the maintainer or email us at contact@tictech.id

# Actor input Schema

## `start_urls` (type: `array`):

Public Instagram profile URLs (main use). Direct /p/ and /reel/ URLs also work.

## `max_items` (type: `integer`):

Maximum number of posts/reels to output. Use 0 for a safe ceiling of 5000. For free-tier testing, keep this small.

## `until` (type: `string`):

Optional. Only keep reels/posts newer than this date (ISO-8601 or YYYY-MM-DD). Dates come from the media ID, so this works without enrich_details.

## `enrich_details` (type: `boolean`):

When true, also fetch each post/reel page: exact taken_at date, missing captions, and grid photo/carousel posts with their like/comment counts. Default false (reels with like/view/comment counts only; cheaper and faster).

## `emit_status_rows` (type: `boolean`):

When true (default), each URL that returns nothing (not found, private, login wall) gets one row with media_type "error" and the reason. Status rows are not charged.

## `useResidential` (type: `boolean`):

Default false: each profile that returns nothing is retried once automatically. Enable to skip the first attempt for every profile.

## `proxyConfiguration` (type: `object`):

Default: Apify Proxy (automatic retry for profiles that return nothing). Custom proxyUrls are supported (no automatic retry then).

## Actor input object example

```json
{
  "start_urls": [
    "https://www.instagram.com/ksi/"
  ],
  "max_items": 20,
  "enrich_details": false,
  "emit_status_rows": true,
  "useResidential": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Scraped post/reel metadata rows.

# 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 = {
    "start_urls": [
        "https://www.instagram.com/ksi/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tictechid/vanzi-instagram-scraper").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 = { "start_urls": ["https://www.instagram.com/ksi/"] }

# Run the Actor and wait for it to finish
run = client.actor("tictechid/vanzi-instagram-scraper").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 '{
  "start_urls": [
    "https://www.instagram.com/ksi/"
  ]
}' |
apify call tictechid/vanzi-instagram-scraper --silent --output-dataset

```

## MCP server setup

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

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/fFNo5tOKmpzv7RY41/builds/oYu5oJAj9Q0wVr9Uo/openapi.json
