# Instagram Scraper (`dami_studio/instagram-scraper`) Actor

Instagram scraper API for profiles, posts and reels. A username gives the profile row plus the posts on its grid; a post or reel link gives that one item. Rows have the caption, likes, comments, views, media links, tagged users and timestamp. $0.45 per 1,000 rows.

- **URL**: https://apify.com/dami_studio/instagram-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Social media
- **Features:** Limited permissions
- **Stats:** 119 total users, 30 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.44 / 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.
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 scraper for a username or a post link, flat rows back**: the account's profile row
plus the posts and reels on its public grid, or the one post or reel you linked, with caption,
likes, comments, views, media links and tagged people. One row per thing, ready for a sheet.

The part worth knowing up front: a run reads the public grid. On most
accounts that is the whole grid. On a few it is smaller than what you see while logged in. On the
free Apify plan a profile stops at 12 posts; a paid plan gets the rest, up to about 720.

| | |
|---|---|
| **Input** | Usernames, profile, post and reel links, accounts whose tagged posts or live stories you want, place links |
| **Output** | One row per profile, post, reel or place: caption, likes, comments, views, media links, post type, length, sound, place, owner, tagged users, timestamp |
| **Ceiling** | 5,000 rows per run, and 12 posts a profile on the free plan |
| **Account needed** | None |
| **Price** | $0.45 per 1,000 rows on the free plan, down to $0.435 on Business. The free plan's $5 a month covers about 11,000 |

### 🔍 What Instagram Scraper does

Public accounts are supported, including brands and creators with a business category set. On some
business accounts `postsCount` and `isBusinessAccount` come back `null`; the rest of the row is
filled in.

A username returns that account's profile row, then its grid in the grid's own order: pinned tiles
first, then newest first. Every media row carries `isPinned`, and `skipPinnedPosts` drops the pinned
ones if you want plain publication order. Reels an account keeps off its grid are a separate set,
and `includeReelsTabOnly` adds them on top of the grid.

A post or reel link returns that one item, whether or not it is still on the grid: one row, billed
once. That holds for links with the account name in front (`instagram.com/nasa/p/...`) and for the
`instagram.com/share/` links the app's Share button copies. You can mix usernames and links in one run.

Hashtags and mentions are parsed out of the caption for you. Tagged users, collaborators and
sponsors come back as their own arrays with ids, names and links.

### 📋 What data you get from each Instagram profile and post

| What you get | Field |
|---|---|
| What the row is: a profile, a photo, a video or a carousel | `type` |
| Profile: handle, display name, numeric id, link | `username`, `fullName`, `id`, `url` |
| Profile: bio, bio link and picture | `biography`, `externalUrl`, `profilePicUrl` |
| Profile: follower, following and post counts | `followersCount`, `followsCount`, `postsCount` |
| Profile: verified, business and private flags | `verified`, `isBusinessAccount`, `private` |
| Post: link and shortcode | `url`, `shortCode` |
| Post: caption, and the hashtags and handles in it | `caption`, `hashtags`, `mentions` |
| Post: likes, comments and video views | `likesCount`, `commentsCount`, `videoViewCount`, `videoPlayCount` |
| Post: cover image, video file and every carousel frame | `displayUrl`, `videoUrl`, `images`, `dimensions`, `isVideo` |
| Post: who posted it and when | `ownerUsername`, `ownerId`, `timestamp` |
| Post: tagged people, co-authors and sponsors | `taggedUsers`, `coauthorProfiles`, `coauthorUsernames`, `sponsorProfiles` |
| Post: paid partnership, hidden likes, comments off, pinned | `isPaidPartnership`, `isSponsored`, `likesAndViewCountsDisabled`, `isCommentsDisabled`, `isPinned` |
| Post: Instagram's alt text for the image | `accessibilityCaption` |
| Post: numeric id, type (reel, photo, video, carousel) and length | `postId`, `postType`, `videoDuration` |
| Post: the poster's name, badge, privacy, picture and counts | `ownerFullName`, `ownerIsVerified`, `ownerIsPrivate`, `ownerProfilePicUrl`, `ownerFollowersCount`, `ownerFollowsCount`, `ownerPostsCount` |
| Post: the place it is tagged at | `locationName`, `locationId`, `locationLat`, `locationLng` |
| Post: its sound | `musicTitle`, `musicArtist`, `audioId`, `isOriginalAudio` |
| Post: every carousel slide with its own image and video link | `carouselSlides` |
| Profile: category, highlights, new-account flag, every bio link | `businessCategory`, `highlightCount`, `joinedRecently`, `bioLinks` |
| Profile: Facebook page, Threads, live story, adults-only flag | `facebookPageUrl`, `threadsUrl`, `hasPublicStory`, `isAgeRestricted` |
| Profile: business address and related accounts | `businessAddress`, `relatedProfiles` |
| Tagged posts: the account tagged and how | `mentionedUsername`, `mentionTypes`, `timestampIsApproximate` |
| Place: name, category, address, coordinates, post count, phone, opening status | `locationId`, `locationName`, `category`, `address`, `city`, `zip`, `latitude`, `longitude`, `postCount`, `phone`, `openingStatus`, `priceRange` |
| Story (paid plan): one row per story up now | `storyId`, `ownerUsername`, `ownerFullName`, `mediaType`, `timestamp`, `expiresAt`, `displayUrl`, `videoUrl`, `videoDuration`, `url` |
| Comment under a post link (paid plan) | `id`, `text`, `ownerUsername`, `ownerId`, `likesCount`, `repliesCount`, `timestamp`, `isReply`, `parentCommentId`, `postShortCode`, `postUrl` |
| Every row: the input it came from | `inputUrl` |
| Optional add-ons, from 9 November 2026 | `facebookPlayCount`, `facebookLikesCount`, `instagramPlayCount`, `facebookCountsFound`, `audioUrl`, `topComments` |

### ▶️ How to scrape Instagram posts

1. Open [Instagram Scraper](https://apify.com/dami_studio/instagram-scraper) and click
   **Try for free**.
2. Type a handle into **Profile usernames**, or paste links into **Start URLs (profiles or posts)**.
3. Set **Max results**. Start at 50 while you look at the output shape.
4. Click **Start**.
5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.

Start it with both lists empty and you get one labelled sample row, which is not charged.

### 💰 How much does it cost to scrape Instagram posts?

**$0.45 per 1,000 rows.** That is the free plan's price; paid plans pay a little less: $0.445 on Starter, $0.44 on Scale and $0.435 on Business. On the free plan, the $5 Apify
gives you each month covers about 11,000 rows.

Profile, post, place, story and comment rows cost the same. You pay for rows that carry data, so the sample row,
diagnostic rows, posts your date or type filter leaves out and duplicates inside a run are not charged.
`resultsLimit` is the ceiling on both the rows and the spend.

The three add-ons start on 9 November 2026 and need a paid Apify plan. Before then a free row says so.

| Add-on, from 9 November 2026 | Starter | Scale | Business |
|---|---|---|---|
| Facebook counts, per 1,000 posts checked | $4.94 | $4.89 | $4.83 |
| Audio link, per 1,000 posts checked | $4.94 | $4.89 | $4.83 |
| Comments, per 1,000 comments | $0.396 | $0.391 | $0.387 |

### 📥 What you give it

```json
{
  "usernames": ["nasa"],
  "onlyPostsNewerThan": "2 weeks",
  "resultsLimit": 50
}
```

| Field | Default | What it is |
|---|---|---|
| `usernames` | none | Handles with or without `@`. Each returns its profile row plus its grid. |
| `startUrls` | none | Paste links instead. A profile link reads that grid; a `/p/`, `/reel/` or `/tv/` link reads that one item, with or without the account name in front, and so does a `/share/` link from the app. A stories, hashtag or place page gets a free row naming the field that reads it. |
| `mentionsOf` | none | Accounts whose Tagged tab you want: public posts by other people that tag or mention them. |
| `places` | none | Place links (`instagram.com/explore/locations/...`) or place ids. One place row each, then recent posts tagged there on a paid Apify plan. |
| `storiesOf` | none | Accounts whose stories are up now, one row per story, on a paid Apify plan. An account with none gets a free row. |
| `commentsAsRows` | none | Up to this many comments under each post link, one row each, on a paid Apify plan. |
| `resultsLimit` | `50` | Rows across the whole run, profiles and posts together. 1 to 5,000. This is also your spend cap. |
| `resultsPerProfile` | none | Posts per profile (and per tagged account). `0` returns the profile or place row only and reads no posts. |
| `postTypes` | `all` | `reels`, `photos` or `carousels` to keep only that kind. A post link you paste always comes back. |
| `onlyPostsNewerThan` | none | A day (`2026-05-01`) or a window (`7 days`, `2 weeks`, `1 month`); the form gives you a calendar. Days count in UTC, and pinned tiles have to meet the date too. A value that is not a date stops the run with a `BAD_INPUT` row before anything is read. |
| `skipPinnedPosts` | off | Drop the tiles pinned to the top of the grid, up to three of them. |
| `includeReelsTabOnly` | off | Also return reels the account keeps off its grid, such as trial reels. It adds them; it does not limit the run to reels. |
| `posterCountsOnLinks` | off | Fill the poster's follower, following and post counts on post links too, at one more profile read per poster. Profile runs fill them anyway. |
| `includeFacebookCounts` | off | Add-on from 9 November 2026: Instagram plays, Facebook plays and Facebook likes. Needs a paid Apify plan. |
| `includeAudioLink` | off | Add-on from 9 November 2026: the link to a reel's or video's sound. A link only, nothing is downloaded. Needs a paid Apify plan. |
| `commentsPerPost` | none | Add-on from 9 November 2026: up to 15 of each post's comments on the post row. Needs a paid Apify plan. |
| `sessionCookies` | none | Optional. Your own Instagram cookie, used from the first request so the run sees what your account sees. Treat the value like a password. |
| `proxyConfiguration` | none | Leave it alone unless you have your own servers to use. |
| `notionConnector`, `notionParentId` | none | Optional. Write each row into a Notion database as well as the dataset. |

### 📤 What you get back

A real post row from a run on 30 September 2026, with the image links cut short:

```json
{
  "ok": true,
  "type": "image",
  "shortCode": "Dd4OWyWjFsh",
  "url": "https://www.instagram.com/p/Dd4OWyWjFsh/",
  "caption": "I spy with my X-ray eyes 👀\n\nUsing @NASAChandraXray, astronomers discovered a new class of \"hypersoft\" objects that give off very low-energy, difficult to detect X-rays. These objects exist in multiple galaxies, including this one, the Pinwheel Galaxy.\n\n#NASA #Space #Galaxy",
  "hashtags": ["NASA", "Space", "Galaxy"],
  "mentions": ["NASAChandraXray"],
  "likesCount": 240993,
  "commentsCount": 664,
  "videoPlayCount": null,
  "videoViewCount": null,
  "displayUrl": "https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/...",
  "videoUrl": null,
  "images": ["https://scontent-iad6-1.cdninstagram.com/v/t51.82787-15/..."],
  "isVideo": false,
  "dimensions": {"height": 1441, "width": 1439},
  "ownerUsername": "nasa",
  "ownerId": "528817151",
  "timestamp": "2026-09-29T16:48:08.000Z",
  "accessibilityCaption": null,
  "taggedUsers": [],
  "sponsorProfiles": [],
  "coauthorProfiles": [],
  "coauthorUsernames": [],
  "isPaidPartnership": false,
  "isSponsored": false,
  "likesAndViewCountsDisabled": false,
  "isCommentsDisabled": false,
  "isPinned": false
}
```

| Field | How to read it |
|---|---|
| `shortCode` | Unique per post. Use it as your dedupe key across runs. |
| `ownerUsername` | On a collaboration post this can be the other account, with the one you asked for in `coauthorUsernames`. |
| `videoViewCount`, `videoPlayCount` | `null` on photos. On a reel the two usually hold the same number. |
| `isSponsored` | The same flag as `isPaidPartnership`, kept under both names. |
| `displayUrl`, `videoUrl`, `images` | Signed and time limited. Download anything you want to keep. |
| `postsCount`, `isBusinessAccount` | On the profile row, `null` on some business accounts. The rest of the profile row is still there. |
| `postId` | Text, not a number, so it is never rounded. |
| `locationLat`, `locationLng` | The tagged place's page, not where the photo was taken. |
| `timestamp` on tagged posts | Worked out from the post id, so it can be a few minutes off; `timestampIsApproximate` says so. |
| `businessCategory`, `highlightCount`, `joinedRecently` | `null` on some business accounts. |

### 🧾 Reading the output

Three kinds of row can land in your dataset.

| Row | How to spot it | Billed |
|---|---|---|
| A profile, post or reel | `ok: true` and a `type` | yes |
| The sample row | `_sample: true`, `charged: false` | no |
| A diagnostic | `ok: false` and an `errorCode` | no |

Filter on `ok == true` and you have your data. Diagnostic rows carry one of these codes:

| Code | What it means |
|---|---|
| `NOT_FOUND` | Instagram showed the item or account as gone, private or suspended. |
| `NOT_SERVED` | This request was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here. |
| `RATE_LIMITED`, `SERVER_ERROR`, `NETWORK` | Instagram was busy or unreachable for that item. Try again in a few minutes. |
| `PARTIAL` | A profile's posts stopped coming part way, or a free-plan run reached its 12 posts a profile. `postsDelivered` says how many arrived, and only those were charged. A new run starts from the top. |
| `BAD_INPUT` | An option had a value it cannot use, so nothing was read. Or a `/share/` link was cut short, or a link needs another field. |
| `OPTION_STARTS_SOON`, `OPTION_OFF` | An add-on, stories, comment rows or posts at a place did not run: it needs a paid Apify plan, or it was an add-on asked for before they started on 9 November 2026. The rest of the run went ahead. |
| `NO_RESULTS` | The run finished with nothing to return for your input. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The results delivered before that are complete and charged. Give the run more time, or ask for fewer results, to get the rest. |
| `COST_LIMIT` | The maximum cost per run you set does not cover one result, so nothing was read. Raise it and run again. |
| `UNEXPECTED_ERROR` | The run stopped early on an unexpected error. The results before this row are kept. |

None of these rows is billed. The run carries on after each one except `TIME_LIMIT` and `COST_LIMIT`, which end it, and even then it still ends as succeeded, with an amber status message.

One quirk of the Overview table: it shows post columns, so a profile row reads as an almost empty
line there. Open the row itself or download the JSON and it is all present.

### 💡 What people use it for

- Pulling a competitor's recent posts every Monday and diffing the like and comment counts.
- Checking one post or reel at a time from links a team drops into a channel.
- Measuring posting cadence: `timestamp` across a grid tells you how often an account actually posts.

From a grid to what the comments say, in three steps:

1. Run this on a username with `onlyPostsNewerThan` set to `30 days`.
2. Sort the rows on `commentsCount` and copy the `url` of the posts at the top.
3. Paste those links into
   [Instagram Comments Scraper](https://apify.com/dami_studio/instagram-comments-scraper) and read
   what people actually said.

### 🚧 What it does not do

- **No hashtag feeds or keyword search, and only the top comments under a link.** Separate actors do those, linked below.
- **No website on place rows**, and the phone is empty when the place lists none.
- **A private account returns the profile shell only.** Bio, counts and `private: true` come
  through. There is nothing public behind it to read.
- **Recent posts, not the full archive.** About 720 posts per profile at most, so on a very large
  account use `onlyPostsNewerThan` to make the walk purposeful.
- **A signed-out run can see a smaller grid.** If a profile shows more in your browser than the run
  returned, that is the difference.
- **Media links expire.** They are signed, short-lived links. Fetch anything you want to keep.
- **Counts are a snapshot at read time**, not at publish time.
- It is not an official Instagram tool. Dami's Studio is independent and is not affiliated with or endorsed by Instagram or Meta, or by any other company named on this page.

### 🧭 Which Instagram scraper do you need?

| If you want | Use |
|---|---|
| A profile plus the posts on its grid | This one |
| One row per account, with engagement | [Instagram Profile Scraper](https://apify.com/dami_studio/instagram-profile-scraper) |
| Posts and reels from links you already have | [Instagram Post Scraper](https://apify.com/dami_studio/instagram-post-scraper) |
| The reels on a profile's reels tab, with play counts and MP4 links | [Instagram Reel Scraper](https://apify.com/dami_studio/instagram-reel-scraper) |
| Posts under a hashtag | [Instagram Hashtag Scraper](https://apify.com/dami_studio/instagram-hashtag-scraper) |
| Comments under a post or reel | [Instagram Comments Scraper](https://apify.com/dami_studio/instagram-comments-scraper) |
| Stories a profile has up right now | [Instagram Stories Scraper](https://apify.com/dami_studio/instagram-stories-scraper) |
| Followers or following lists of a profile | [Instagram Followers & Following Scraper](https://apify.com/dami_studio/instagram-followers-following-scraper) |

### ❓ Questions people ask

#### Do I need an Instagram account to scrape posts?

No. Profiles with their first 12 posts, post links, tagged posts and places are read the way a
signed-out visitor sees them. Later posts, stories, comment rows and posts at a place need a paid
Apify plan. The cookie field is optional.

#### Is resultsLimit per username or per run?

Per run, and the profile row counts towards it. Ask for 100 across three handles and you get 100
rows in total, not 300.

#### Why did I get fewer posts than I asked for?

The account has fewer, your date filter dropped them, the free plan stopped at 12, or the walk hit
its 720-post ceiling. If the posts stopped for any other reason, a free `PARTIAL` row says so.

#### Why do the numbers differ from what I see in the app?

Counts keep moving, and the row holds them as they were when it was read. If posts are missing,
open the profile in a private browser window: what a logged-out visitor sees there is what this
actor can read.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/instagram-scraper/api/python) has code for Python, JavaScript and the CLI.
MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/instagram-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-instagram-SKILL.md). All three
bill your Apify account at the same price.

#### Is scraping Instagram legal?

This reads public profiles, posts and place pages only, never private accounts or messages. Results can
still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it.
Apify's write-up on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is
a good starting point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Include the username or link you used and the run ID, and
the log is enough for us to see what happened.

# Actor input Schema

## `usernames` (type: `array`):

Instagram usernames, with or without @. Each one returns a profile row plus the media on that account's public profile grid, in the grid's own order: pinned tiles first, then newest first.

## `startUrls` (type: `array`):

Paste Instagram URLs directly. A profile URL returns that account's public grid; a post or reel URL returns that one item, whether or not it is on the grid. That includes links with the account name in front (instagram.com/name/p/...) and the instagram.com/share/ links the app's Share button copies.

## `onlyPostsNewerThan` (type: `string`):

Keep posts and reels published on or after this date. Pick a day in the calendar, or switch to a relative window such as 7 days or 2 weeks, which suits a scheduled run. Days are counted in UTC. Pinned tiles have to meet the date too. Leave it empty for no date limit.

## `skipPinnedPosts` (type: `boolean`):

Drop the posts an account pinned to the top of its grid, up to three of them. Off by default; every media row carries isPinned either way. Reels pinned to the reels tab are a separate set and are not counted here, they come back at their own date.

## `includeReelsTabOnly` (type: `boolean`):

Off by default, so a profile run returns what the profile grid shows. Turn it on to also get media that only the reels tab lists, such as trial reels and reels an account keeps off its grid.

## `postTypes` (type: `string`):

Keep only reels, only photos or only carousels. Posts of another kind are left out and not charged. Applies to posts read from profiles, tagged posts, places, hashtags and search words; a post link you paste always comes back. Leave it on All for every kind.

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

Maximum rows across the run, including the profile row. The limit is applied after the grid is filtered and ordered, so pinned tiles use result slots unless Skip pinned posts is on.

## `resultsPerProfile` (type: `integer`):

Optional. The most posts to return for each profile, and for each tagged account, place, hashtag or search word. 0 returns only the profile row (or the place row) and reads no posts. Max results above still caps the whole run. Leave it empty for no cap per profile.

## `mentionsOf` (type: `array`):

Account names or profile links. Returns public posts by other people that tag or mention each account, the posts its Tagged tab shows. Each post is one result. Their publish time is worked out from the post id, so it can be a few minutes off (timestampIsApproximate says so).

## `places` (type: `array`):

Instagram place links (instagram.com/explore/locations/...) or place ids. Each returns one place row: name, category, address, coordinates, post count, the opening status and the phone the place lists, where Instagram's page shows them. With a paid Apify plan the run then adds recent posts tagged at the place, when the page lists any. Each row and each post is one result.

## `storiesOf` (type: `array`):

Account names. Returns the stories each account has up right now, one result per story. The run first checks the account's own page, and an account with no story up gets a free row instead. Needs a paid Apify plan.

## `commentsAsRows` (type: `integer`):

Optional. For each post or reel link you paste, also return up to this many of its comments, each as its own row and its own result, in Instagram's own order. Posts with no comments are skipped. Needs a paid Apify plan. Leave it empty or at 0 for none.

## `posterCountsOnLinks` (type: `boolean`):

Profile runs always fill ownerFollowersCount, ownerFollowsCount and ownerPostsCount from the profile row. Turn this on to fill them on post links too: the run reads each poster's profile once more, which makes a link run slower. No extra charge.

## `includeFacebookCounts` (type: `boolean`):

Optional add-on, off by default. Adds Instagram plays, Facebook plays and Facebook likes for posts also shared to Facebook. It starts on 9 November 2026, at $4.94 per 1,000 posts checked on Starter and a little less on Scale and Business; before that day the run says so in a free row and adds nothing. Needs a paid Apify plan.

## `includeAudioLink` (type: `boolean`):

Optional add-on, off by default. Adds audioUrl, the link Instagram serves for a reel's or video's sound. It is a link only; the run never downloads or keeps the file. It starts on 9 November 2026, at $4.94 per 1,000 posts checked on Starter and a little less on Scale and Business; before that day the run says so in a free row and adds nothing. Needs a paid Apify plan.

## `commentsPerPost` (type: `integer`):

Optional add-on. Adds up to this many of each post's comments, in Instagram's own order, as topComments on the post row. Posts with only a few comments are skipped. It starts on 9 November 2026, at $0.396 per 1,000 comments on Starter and a little less on Scale and Business; before that day the run says so in a free row and adds nothing. Needs a paid Apify plan. Leave it empty for none.

## `notionConnector` (type: `string`):

Optional. Deliver the results to your connected Notion via Apify MCP connectors, no extra code.

## `notionParentId` (type: `string`):

Optional Notion database/data-source id to create the pages in.

## `sessionCookies` (type: `array`):

Optional: your own session, used only for your run. You are responsible for using it within the site's terms. Runs work without it.

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

Optional. Leave this alone unless you need the run to go out through a particular network. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "usernames": [
    "nasa",
    "natgeo"
  ],
  "startUrls": [
    "https://www.instagram.com/natgeo/",
    "https://www.instagram.com/p/C8/"
  ],
  "onlyPostsNewerThan": "2024-01-01",
  "resultsLimit": 50,
  "mentionsOf": [
    "nasa"
  ],
  "places": [
    "https://www.instagram.com/explore/locations/212988663/"
  ],
  "storiesOf": [
    "nasa"
  ]
}
```

# Actor output Schema

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

Profile rows and media rows are stored in the default dataset. A profile returns the media on its public grid, deduplicated by shortcode, filtered by date, and ordered the way the grid reads: pinned tiles first in the account's own order, then newest first. Media that only the reels tab lists is left out unless includeReelsTabOnly is on. Rows include isPinned, videoPlayCount, videoViewCount, tagged-user, collaborator and paid-sponsor profiles, plus hidden-like and comments-disabled flags. Empty and failed runs return an uncharged diagnostic row.

# 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 = {
    "usernames": [
        "nasa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = { "usernames": ["nasa"] }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "usernames": [
    "nasa"
  ]
}' |
apify call dami_studio/instagram-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/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/YunzhVBUetNi0cC3o/builds/TLLbVA7BIamPwWER5/openapi.json
