# Instagram Profile Posts & Reels Scraper (`lance_api/instagram-profile-posts-reels-scraper`) Actor

Collect posts and Reels from one or more Instagram profiles, with up to 1,000 items per profile. Use postedAfter to fetch only newly published content and stop paginating early, so scheduled runs pay the lower filter rate for old items instead of the full result rate.

- **URL**: https://apify.com/lance_api/instagram-profile-posts-reels-scraper.md
- **Developed by:** [LanceAPI](https://apify.com/lance_api) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 content results

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 Posts & Reels Scraper

**Fetch posts and Reels from Instagram profiles. Use `postedAfter` to retrieve only newly published content, so your Dataset and your result fees stay focused on what is new.**

This Actor collects public posts and Reels from one or more Instagram profiles and writes one clean, structured row per item. Paste usernames, profile URLs or numeric user IDs, choose what you want, and — when you only care about what is new — set a cutoff date so pagination stops as soon as the feed moves past it. It is built for content collection and new-content monitoring, not for profile analytics.

- **Posts and Reels in one pass** — photos, carousels, feed videos and Reels come back from the profile feed, or ask for posts only / Reels only.
- **`postedAfter` incremental monitoring** — only content published strictly after your cutoff is returned, and pagination stops early once the feed is older than that moment, so a scheduled run does not re-collect and re-pay full result fees for content you already have.
- **Zero new posts is a normal, successful result** — not an error, and not a reason to retry the same profile against every data source.
- **Up to 1,000 items per profile, 200 profiles per run** — with input normalization and de-duplication built in.
- **Pay per delivered item, plus a small per-item fee when the date filter runs** — result fees follow the unique posts and Reels actually written to your Dataset, never the pages or requests behind them; when `postedAfter` is set, the items it examines and removes are charged at a lower filter rate.

### ✨ Key features

#### 1. One profile, many content rows

Every unique post or Reel is delivered as its own Dataset row, linked back to the profile it came from through `sourceUsername`, `sourceProfileUrl` and `sourceProfileId`. Photos, carousels, feed videos and Reels are all first-class rows, with `type` telling them apart (`photo`, `carousel`, `video`, `reel`).

Because each item is its own row, filtering, joining against your own tables, and exporting stay simple — you never have to unpack a nested list to get at a single post.

#### 2. `postedAfter`: real incremental scraping, not a local filter

Set `postedAfter` to a calendar date, an ISO-8601 moment, or a relative value such as `7 days`, and only content published **strictly after** it is returned. The filter is applied inside the pagination pipeline, page by page:

- each page is normalized and filtered as it arrives;
- once the feed has moved past your cutoff, pagination stops instead of continuing to pull older pages you would throw away;
- pinned posts are excluded from the stop decision, so a pinned old item at the top of a feed can never hide newer content;
- an item with no usable timestamp is not delivered and not guessed — it cannot be proven to be newer than your cutoff.

For scheduled monitoring this is the difference between "collect what is new" and "download the whole feed again": old items are examined, removed and charged at the lower filter rate, while only genuinely new items reach your Dataset at the full result rate. A run that finds nothing new still succeeds — no content rows, no result fees, just the filter fee for the items it checked.

#### 3. Content-type control that matches how you will use the data

- **All content** returns the profile's mixed feed: photos, carousels, feed videos and Reels in one pass.
- **Posts only** returns the same feed with explicit Reels removed.
- **Reels only** uses the dedicated Reels feed rather than filtering the first page of a mixed one, so Reel-only runs are not limited by what happens to sit on top of the general feed.

#### 4. Batch-friendly with de-duplication at two levels

Process up to **200 profiles in one run**. Inputs are normalized before any work starts, so `nasa`, `@nasa`, `https://www.instagram.com/nasa/` and a numeric user ID for the same account are recognized as the same profile and processed once — no repeated work, no duplicate rows, no duplicate charges. At the result level, the same media ID is delivered only once even across pagination and recovery.

If one profile in a batch fails, the rest of the batch continues. Failures are reported per profile in the run summary, so one bad input does not waste a 200-profile run.

#### 5. Limits that control both Dataset size and cost

`resultsLimit` caps how many unique items are delivered **per profile** (1–1000, default 100). It is the main lever over both your Dataset size and your result fees: set it to what you actually need rather than leaving it high. How far back a profile can be read also depends on what the data source returns — this Actor does not claim to deliver an account's entire history.

#### 6. Stable identifiers and source links

Every row carries the Instagram media `id` and `shortcode` plus the canonical `url`, so you can de-duplicate against previous runs, join to your own tables, and trace any row back to the profile and input value that produced it. `scrapedAt` records when the row was collected.

### 🚀 Quick start

1. Open the Actor's **Input** tab.
2. Add one or more public Instagram profiles — usernames, `@usernames`, profile URLs, or numeric user IDs.
3. Keep the defaults for a first run: `contentType: all`, `resultsLimit: 100`.
4. Click **Start**. When the run finishes, open **Output → Content**.

For monitoring, set **Only content published after** to the last moment you already have (for example `2026-10-11T18:30:00Z`). The run then returns only newer items and stops paginating once the feed is past that moment.

Minimal input:

```json
{
  "profiles": ["nasa", "@natgeo", "https://www.instagram.com/lego/"],
  "contentType": "all",
  "resultsLimit": 100
}
```

Incremental input — only what is new since yesterday evening:

```json
{
  "profiles": ["nasa"],
  "contentType": "all",
  "resultsLimit": 100,
  "postedAfter": "2026-10-11T18:30:00Z"
}
```

### Short output example

Each unique post or Reel is written as its own Dataset row. The example below is an **illustrative example** showing structure and field names — values are redacted, not from a live run.

```json
{
  "sourceUsername": "nasa",
  "sourceProfileUrl": "https://www.instagram.com/nasa/",
  "sourceProfileId": "528817151",
  "type": "reel",
  "url": "https://www.instagram.com/reel/XXXXXXXXXXX/",
  "timestamp": "2026-10-12T15:04:00.000Z",
  "caption": "Example caption text #hashtag",
  "likesCount": 123456,
  "commentsCount": 2345,
  "viewsCount": 987654,
  "videoUrl": "https://…example-video-url…",
  "thumbnailUrl": "https://…example-thumbnail-url…",
  "id": "3000000000000000000",
  "shortcode": "XXXXXXXXXXX",
  "contentType": "all",
  "input": "nasa",
  "scrapedAt": "2026-10-13T06:00:00.000Z"
}
```

### Input

| Field | Type | Required | Default | Limits / notes |
|---|---|---|---|---|
| `profiles` | array of strings | Yes | prefill: `["instagram"]` | 1–200 values. Accepts usernames (`nasa`), `@usernames`, profile URLs (`https://www.instagram.com/nasa/`) and numeric Instagram user IDs. Normalized and de-duplicated before processing: the same profile is processed once, whatever form it arrived in. |
| `contentType` | string | No | `all` | `all` (mixed feed: photos, carousels, feed videos, Reels), `posts` (same feed with explicit Reels removed), `reels` (dedicated Reels feed). |
| `resultsLimit` | integer | No | `100` | 1–1000 unique items **per profile**. The main control over Dataset size and result fees. |
| `postedAfter` | string | No | empty | Cutoff for incremental runs. In the form, **Absolute** provides a `YYYY-MM-DD` calendar picker and **Relative** accepts a number of days, weeks, months, or years (e.g. `1 days`, `2 months`, `3 years`). JSON also accepts ISO-8601 date-times such as `2026-10-11T18:30:00Z` or `2026-10-11T08:00:00+08:00`. Dates start at midnight UTC; relative values are resolved once at run start in UTC. Only items published **strictly after** that cutoff are returned. Invalid values fail with `INVALID_POSTED_AFTER` before processing. |

How the fields interact:

- `postedAfter` and `resultsLimit` work together: the cutoff decides *which* items qualify, the limit decides *how many* are delivered. When both are set, the run stops at whichever comes first.
- `postedAfter` with zero new items is a successful run: the profile is reported as checked, and no content rows are written.
- `contentType: reels` measures Reels directly from the Reels feed; it is not "the first page of the general feed, filtered".

### Output

One row per unique post or Reel. The Dataset Views change only the column order and presentation, never the underlying rows:

- **All Content** — the balanced overview: source, type, link, timestamp, caption, likes, comments, views, video and thumbnail.
- **Posts** — photo and carousel oriented columns.
- **Reels** — Reel oriented columns: views, duration, video URL, music.
- **Downloads** — media URLs and identifiers for downloading or archiving.

#### Field reference

Core fields:

| Field | Type | Meaning |
|---|---|---|
| `sourceUsername` | string | null | Username the item was collected from. Null when the profile was supplied as a numeric ID and nothing proved the username. |
| `sourceProfileUrl` | string | null | Profile URL the item was collected from. |
| `sourceProfileId` | string | null | Numeric Instagram user ID of the source profile, when known. Stable across username changes. |
| `type` | string | `reel`, `photo`, `carousel`, `video`, or `unknown` when the payload did not establish one. Never folded into another bucket. |
| `url` | string | null | Canonical Instagram URL of the item. |
| `timestamp` | string | null | Publication time, ISO-8601 UTC. Null when the payload carried no usable timestamp. |
| `caption` | string | null | Caption text, when present. |
| `id` | string | null | Instagram media ID — stable identifier for de-duplication and joins. |
| `shortcode` | string | null | Instagram shortcode; the slug used in the content URL. |

Engagement and media fields:

| Field | Type | Meaning |
|---|---|---|
| `likesCount` | integer | null | Like count, when reported. |
| `commentsCount` | integer | null | Comment count, when reported. |
| `viewsCount` | integer | null | Play/view count for video content, when reported. Null for content that reports none. |
| `playsCount` | integer | null | Play count, when separately reported. |
| `sharesCount` | integer | null | Share count, when reported. |
| `videoUrl` | string | null | Direct video URL, when the payload returned one. **Provider media URLs can expire** — download promptly if you need the file. |
| `thumbnailUrl` | string | null | Thumbnail or first-frame image. |
| `imageUrl` | string | null | Display image for photos and carousels. |
| `duration` | number | null | Video duration in seconds, when reported. |

Context fields:

| Field | Type | Meaning |
|---|---|---|
| `hashtags` | string\[] | Hashtags parsed from the caption. |
| `mentions` | string\[] | Usernames mentioned in the caption. |
| `music` | object | null | Attached audio (`title`, `artist`) when the payload carried it. |
| `location` | object | null | Tagged location (`id`, `name`, `city`, `address`) when the payload carried one. |
| `contentType` | string | The `contentType` setting this run used. |
| `input` | string | The exact profile value you supplied that produced this row. |
| `scrapedAt` | string | When the row was collected, ISO-8601 UTC. |

Missing values are delivered as `null`, never as zero or placeholder text: a null `likesCount` means the source did not report one, which is different from a real count of zero.

### Status and errors

Every run writes a `RUN_SUMMARY` record to the key-value store with per-run totals: profiles requested / processed / succeeded / failed, how many items the date filter removed, how many content rows were delivered (split into posts and Reels), how many pages and upstream calls were used, how many times the date filter stopped pagination early, and which inputs were rejected.

Run-level input errors fail the whole run before any profile is processed:

| Code | Meaning |
|---|---|
| `INVALID_REQUEST` | The input could not be read. |
| `BATCH_LIMIT_EXCEEDED` | More than 200 profiles in one run. |
| `INVALID_POSTED_AFTER` | `postedAfter` could not be parsed as an absolute date, an ISO-8601 instant, or a relative UTC duration. |

Per-profile outcomes are reported in the summary; a failed profile does not stop the rest of the batch:

| Code | Meaning | Retry? |
|---|---|---|
| `PROFILE_NOT_FOUND` | The profile could not be found. | Check the username; no retry needed. |
| `CONTENT_UNAVAILABLE` | Public content is not available right now (for example a private or restricted account). | Retry later may help. |
| `UPSTREAM_RATE_LIMITED` / `UPSTREAM_QUOTA_EXHAUSTED` / `UPSTREAM_TIMEOUT` | A temporary data-source issue. | Retry later. |
| `MALFORMED_RESPONSE` / `UPSTREAM_ERROR` | A temporary data-source issue prevented this profile from being resolved. | Retry later. |
| `SERVICE_CONFIGURATION_ERROR` | No data source was available because of a routing configuration issue. Nothing was requested upstream and nothing was charged. | Do not retry: the Actor's routing configuration has to be fixed first. |
| `INVALID_PROFILE` | The value is not a usable Instagram profile. | Fix the input. |
| `FREE_USAGE_LIMIT_EXCEEDED` | The free usage allowance has been reached. | See Pricing. |
| `INTERNAL_ERROR` | The profile could not be processed right now. | Retry later. |

Important, non-error outcomes:

- **Zero new items with `postedAfter` set** — a successful check. The profile is counted as checked, no rows are written, and no result fee applies.
- **Reaching the natural end of a feed** — a successful result, even when fewer items than `resultsLimit` are available.
- **Items older than your cutoff** — filtered out by design; the summary reports how many were seen and how many were filtered.

### 💰 Pricing

This Actor uses **pay-per-event** pricing, so what you pay follows what the run actually delivered.

#### Result pricing (per 1,000 delivered posts or Reels)

| Plan | content-result |
|---|---|
| Free | $1.10 |
| Bronze | $1.00 |
| Silver | $0.80 |
| Gold | $0.60 |

That is **$0.0011 per delivered item** on the Free plan, down to **$0.0006** on Gold. See the Actor's **Pricing** tab for the rates that apply to your account.

#### Date-filter processing fee

When you set `postedAfter`, every item the filter examines and removes is charged at **$0.60 per 1,000 filtered items** ($0.0006 per item) — **the same on every plan**. Content older than your cutoff counts, and so does content with no usable timestamp: both were fetched and judged on your behalf. A run where everything returned is new pays no filter fee at all.

#### Actor start fee

**$0.001 per run**, whatever the batch size.

How the billing works:

- **One result fee per unique post or Reel actually delivered.** The unit is the row written to your Dataset — never a page, a request, or an attempt. `resultsLimit` is the main lever over this fee: lower it and you collect — and pay for — less.
- **One filter fee per item the date filter removed.** Charged only when `postedAfter` is set, because that is the only mode in which items are filtered by date. A monitoring run that examined 100 old items and found 3 new ones pays 3 result fees plus 100 filter fees — roughly half of what delivering all 103 items would have cost.
- **One start fee per run**, independent of how many profiles the run handles.

What you are never charged for:

- **Invalid input rejected before processing.** A value that is not a usable profile produces no fee.
- **Duplicates.** A profile listed twice — or listed once as a username and once as its numeric ID — is checked once and charged once.
- **Retries and recoveries.** A temporary failure that is retried, or a profile resolved through a second attempt, does not create another fee for the same profile or the same item.
- **Items removed by content type.** A Reel skipped in Posts-only mode is not date-filtered, so it never creates a filter fee.
- **Items beyond your limit.** Anything past `resultsLimit` is never fetched, filtered or charged.
- **Pagination.** How many pages a profile needed is never billed directly.

Cost example (Free-plan rates): a daily monitoring run over 5 profiles starts at $0.001. On a day where the run examined 300 items, removed 288 older ones and delivered 12 new posts, the total is 12 × $0.0011 + 288 × $0.0006 + $0.001 ≈ **$0.19**. On a quiet day where the same run examines 60 items and delivers nothing, it is 60 × $0.0006 + $0.001 ≈ **$0.04**. A plain archive run with no `postedAfter` — 100 items from one profile — is 100 × $0.0011 + $0.001 ≈ **$0.11** with no filter fee.

#### Free-plan users

Free-plan users are subject to the current free usage allowance configured for this Actor. Paid users are not subject to that allowance. When a run reaches the allowance, the remaining profiles continue to be processed and the ones that were not served are reported explicitly in `RUN_SUMMARY`.

### API usage

Run the Actor programmatically and retrieve the default Dataset when it finishes. Replace the sample profiles with your own.

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('lance_api/instagram-profile-posts-reels-scraper').call({
  profiles: ['nasa', '@natgeo'],
  contentType: 'all',
  resultsLimit: 100,
  postedAfter: '2026-10-11T18:30:00Z',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient(token=os.environ['APIFY_TOKEN'])

run = client.actor('lance_api/instagram-profile-posts-reels-scraper').call(run_input={
    'profiles': ['nasa', '@natgeo'],
    'contentType': 'all',
    'resultsLimit': 100,
    'postedAfter': '2026-10-11T18:30:00Z',
})

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item)
```

#### cURL

```bash
curl -X POST \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "profiles": ["nasa", "@natgeo"],
    "contentType": "all",
    "resultsLimit": 100,
    "postedAfter": "2026-10-11T18:30:00Z"
  }' \
  "https://api.apify.com/v2/acts/lance_api~instagram-profile-posts-reels-scraper/runs?waitForFinish=120"
```

Fetch the default Dataset of the finished run:

```bash
curl "https://api.apify.com/v2/datasets/{datasetId}/items?format=json"
```

### Use cases

- **New-content monitoring.** Schedule the Actor daily with `postedAfter` set to your last checkpoint and receive only what was published since — without re-collecting and re-paying for the same posts on every run.
- **Competitor content tracking.** Collect the recent posts and Reels of competitor profiles into your own store and compare posting volume, formats and captions over time.
- **Creator content review at scale.** Pull the recent output of a shortlist of creators and review formats, cadence and captions in a spreadsheet before outreach.
- **Reels research.** Run with `contentType: reels` to study a profile's Reel output specifically — views, duration and music — rather than a mixed feed.
- **Content archiving.** Use `resultsLimit` and the Downloads view to capture posts, images and video URLs for an internal archive, downloading media before the URLs expire.
- **Feeding analytics pipelines.** Every row carries stable IDs, timestamps and engagement counts, so the Dataset drops straight into a database, dashboard or BI tool.
- **UGC and mention sourcing.** Use captions, hashtags, mentions and location fields to find brand-relevant public content for outreach or research.

### How it works

1. You submit profiles in any supported form.
2. The Actor validates, normalizes and de-duplicates them, so the same profile is processed once.
3. For each profile it collects the requested content type, normalizing every item into a stable row shape.
4. When `postedAfter` is set, items are filtered page by page and pagination stops once the feed has moved past your cutoff.
5. Unique items are written to the Dataset, and the run summary reports totals, checks, filtered counts and failures.

### Related Actors

| If you need to… | Recommended Actor |
|---|---|
| Evaluate a creator's followers, engagement rate and posting cadence | **Instagram Creator & Engagement Scraper** |
| Look up profile metadata, bio and public contact details | **Instagram Profile Scraper API** |
| Collect comments and replies from posts and Reels | **Instagram Comments Scraper API** |
| Find who liked a post or Reel | **Instagram Likers Scraper API** |
| Download Reels and videos as files | **Instagram Reels Downloader – Fast Batch API** |
| Collect content by hashtag | **Instagram Hashtag Scraper API** |

Explore more Instagram data Actors from `lance_api` on Apify.

### FAQ

**Which profile formats are accepted?**
Usernames (`nasa`), `@usernames` (`@nasa`), profile URLs (`https://www.instagram.com/nasa/`) and numeric Instagram user IDs. All forms of the same profile are recognized and processed once.

**Do I need a login or cookie?**
No. This Actor works with publicly available data only. Never send tokens, cookies or sessions to support.

**Is `postedAfter` inclusive or exclusive?**
Exclusive. Only items published strictly **after** the moment are returned. An item published at exactly `2026-10-11T18:30:00Z` is excluded when the cutoff is that same moment.

**What date formats does `postedAfter` accept?**
Use **Absolute** to select a date with the calendar (`YYYY-MM-DD`, interpreted as midnight UTC), or **Relative** to choose days, weeks, months, or years before run start, for example `1 days`, `2 months`, or `3 years`. JSON can also supply ISO-8601 date-times with a timezone (`2026-10-11T18:30:00Z`, `2026-10-11T08:00:00+08:00`). All time values are taken in UTC timezone. The relative cutoff is resolved once per run, so scheduled runs automatically move the window forward. Days/weeks use elapsed UTC days; months/years use calendar subtraction, keeping the UTC time of day and clamping to the last valid day when needed (March 31 minus one month becomes February 28 or 29). `0 days` means the run start time. Invalid values fail with `INVALID_POSTED_AFTER` before any profile is processed.

**What happens when there are no new posts?**
The run succeeds. The profile is reported as checked, no content rows are written, and no result fees apply — the only charge is the filter fee for the items the cutoff examined and removed. The profile is **not** retried against other data sources: an empty result is an answer, not a failure.

**Can I get an account's entire post history?**
No guarantee. The Actor delivers up to `resultsLimit` unique items per profile, and how far back the feed can actually be read depends on what the data source returns. Do not market or plan against "complete history".

**How are pinned posts handled with `postedAfter`?**
A pinned item is never allowed to trigger the early stop, so a pinned old post at the top of a feed cannot hide newer content below it.

**What happens to items with no timestamp when `postedAfter` is set?**
They are not delivered. An item without a usable timestamp cannot be proven to be newer than your cutoff, so it is excluded rather than guessed, and the count is reported in the run summary.

**Are duplicate profiles charged twice?**
No. Repeated references to the same profile — in any supported form — are normalized to one profile, processed once, and charged once.

**Are duplicate results possible?**
The same media ID is delivered once per run, even across pagination and recovery. Two different posts with identical captions remain separate rows.

**If one profile fails, does the whole run fail?**
No. Each profile is processed independently; failures are reported per profile in `RUN_SUMMARY` and the rest of the batch continues.

**Why are some counts null?**
The source did not report them. Null means "not reported", which is different from zero — this keeps your analysis honest.

**How long do media URLs stay valid?**
Video and image URLs come from the source and can expire. Download media promptly if you need the files; the metadata rows remain valid.

**How do I control cost?**
Lower `resultsLimit` to what you need, use `postedAfter` for scheduled runs so old items are charged at the lower filter rate instead of the full result rate, and remember that duplicates, type-filtered items, over-limit items and failed profiles never create a result fee.

### Limitations

- Public data only. Private, restricted or deleted profiles and content cannot be collected.
- Content availability, counts and media URLs depend on what the source returns at run time and can change without notice.
- History depth is not guaranteed: the Actor delivers up to `resultsLimit` unique items per profile, and the readable depth of a feed depends on the source.
- Counts such as likes, comments, views and shares are reported only when the source reports them; missing values are `null`.
- Direct media URLs can expire; download promptly when you need the files.
- The Actor does not log in, does not bypass access controls, and does not guarantee a fixed number of results per profile.

### Public data and responsible use

This Actor collects only publicly available data. You are responsible for complying with applicable laws, Instagram's terms of service, and the privacy and copyright expectations that apply to your use case — including how you store, share and republish collected content, and for avoiding spam or automated abuse of the platform.

### Support

Open an issue on the Actor page or email <lanceapi2026@hotmail.com>.

For a bug report, include:

- Apify Run ID
- a non-sensitive Instagram profile you used
- the input fields you set
- the relevant status or error code from `RUN_SUMMARY`, if available
- what you expected and what actually happened

Do **not** send:

- Apify Token or `APIFY_TOKEN`
- Cookie
- Session ID
- Password
- API Key
- Proxy credentials
- Authorization header

# Actor input Schema

## `profiles` (type: `array`):

Enter usernames (nasa), @usernames (@nasa), Instagram profile URLs (https://www.instagram.com/nasa/), or numeric Instagram user IDs (25025320). Add up to 200 profiles in one batch. Your batch is normalized and de-duplicated automatically, so the same profile is only processed once.

## `contentType` (type: `string`):

Choose what to collect. "All content" returns the profile's mixed feed, so photos, carousels, feed videos and Reels all come back in one pass. "Posts only" returns the same feed with explicit Reels removed. "Reels only" uses the dedicated Reels feed instead of filtering a mixed one.

## `resultsLimit` (type: `integer`):

Maximum number of unique items to deliver for each profile (1-1000). This is the main control over both Dataset size and result fees: set it to what you actually need rather than leaving it high. How far back a profile can be read also depends on what the data source returns.

## `postedAfter` (type: `string`):

Optional cutoff. Use Absolute to select a date (YYYY-MM-DD, midnight UTC), or Relative for e.g. 1 days, 2 weeks, 2 months, 3 years before run start. All time values are taken in UTC timezone. Only content published strictly after the cutoff is returned. JSON also accepts ISO-8601 date-times such as 2026-10-11T18:30:00Z or 2026-10-11T08:00:00+08:00. Leave empty for no date filter.

## Actor input object example

```json
{
  "profiles": [
    "instagram"
  ],
  "contentType": "all",
  "resultsLimit": 100,
  "postedAfter": "2026-10-11T00:00:00Z"
}
```

# Actor output Schema

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

One row per unique Post or Reel delivered. A profile with no matching content produces no row; the run summary reports it.

## `datasetConsole` (type: `string`):

No description

## `runSummary` (type: `string`):

Per-run totals in plain language: profiles requested, processed, succeeded and failed, how many items the date filter removed, how many content rows were delivered, how many pages and upstream calls the run used, how many times the date filter stopped pagination early, and which inputs were rejected.

# 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 = {
    "profiles": [
        "instagram"
    ],
    "postedAfter": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("lance_api/instagram-profile-posts-reels-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 = {
    "profiles": ["instagram"],
    "postedAfter": "",
}

# Run the Actor and wait for it to finish
run = client.actor("lance_api/instagram-profile-posts-reels-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 '{
  "profiles": [
    "instagram"
  ],
  "postedAfter": ""
}' |
apify call lance_api/instagram-profile-posts-reels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lance_api/instagram-profile-posts-reels-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/o0CBojxXAyynkUJFk/builds/qweuqUqsNrb1JR334/openapi.json
