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

Scrape posts and profile details from any Instagram profile: captions, hashtags, likes, comments, video plays, image and video URLs, tagged users and more. No login or cookies needed. Export to JSON, CSV or Excel, or use via API. Pay only for results.

- **URL**: https://apify.com/arisma_tech/instagram-profile-posts-scraper.md
- **Developed by:** [Arishma](https://apify.com/arisma_tech) (community)
- **Stats:** 6 total users, 3 monthly users, 79.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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

### What does Instagram Profile & Posts Scraper do?

**Instagram Profile & Posts Scraper** extracts posts and profile details from any public Instagram profile, with **no Instagram login and no cookies needed**. Give it one or many usernames or profile URLs and get back clean, structured data for every post: caption, hashtags, mentions, likes, comments, video plays, image and video URLs, carousel items, tagged users, collaborators, location and publication date.

Use it to:

- **Monitor competitors and brands**: track what they post, how often, and how their content performs.
- **Measure influencer engagement** before a partnership: likes, comments and video plays per post.
- **Research content and hashtags**: find out what formats (reels, carousels, images) work in your niche.
- **Feed dashboards, CRMs and AI pipelines** with fresh Instagram data on a schedule.

### What data can I extract from Instagram?

| Post data | Profile data |
| --- | --- |
| Post URL, shortcode and ID | Username, full name and user ID |
| Caption, hashtags and mentions | Biography and bio links |
| Publication date and time | Followers and following counts |
| Likes and comments count, latest comments | Verified and private status |
| Video play and view counts, duration | Profile picture URL (standard and HD) |
| Image URL, video URL and carousel items | Number of posts and story highlights |
| Content type (image, video/reel, carousel) | Business account flag and category |
| Pinned, paid-partnership and comments-disabled flags | External URL and Facebook ID |
| Tagged users, collaborators and location | |
| Reel audio: music or original sound, audio URL | |
| Image alt text | |

### How do I scrape Instagram posts?

1. Click **Try for free**.
2. Enter one or more **profile URLs or usernames**, for example `https://www.instagram.com/nasa/` or `nasa`.
3. Keep the default Apify residential proxy, or under **Proxy configuration** choose **Own proxies** and enter your proxy URL.
4. Set **Max posts per profile**, and optionally a date in **Only posts newer than** (such as `7 days` or `2025-01-31`).
5. Click **Start** and download your data as JSON, CSV, Excel or HTML, or get it through the API.

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

You pay **$1.50 per 1,000 posts**; platform usage is included. With the default Apify residential proxy, proxy traffic is billed at cost: **$0.008 per MB**, in 100 KB steps (a typical profile uses well under 1 MB). Use your own proxy and there is no traffic charge. In profile-only mode you pay **$1.60 per 1,000 profiles**. Profiles that can't be scraped (missing, blocked, or private when you ask for posts) are not charged.

For example, 100 posts from each of 10 profiles costs 1,000 × $0.0015 = **$1.50**.

To control costs, set **Max posts per profile** and **Only posts newer than**, or set a maximum cost per run in the run options. The scraper stops as soon as that limit is reached.

### Input

The input is the same as Apify's **Instagram Scraper** (posts) and **Instagram Profile Scraper** (profile details), so existing integrations work by changing only the Actor ID.

| Field | Description |
| --- | --- |
| `directUrls` | Profile URLs or usernames (`nasa`, `@nasa`, share links like `nasa?igsh=...`). |
| `usernames` | Same, in Instagram Profile Scraper's format. With `includeAboutSection` and no `directUrls`, returns profile details only. |
| `resultsType` | `posts` (default) or `details` (one item per profile with its 12 latest posts). |
| `onlyPostsNewerThan` | Only posts published after this date. Absolute (`2025-01-31`) or relative (`7 days`, `2 weeks`, `3 months`). |
| `resultsLimit` | Maximum number of posts per profile (default 50, or 1,000 when `onlyPostsNewerThan` is set). |
| `skipPinnedPosts` | Ignore posts pinned to the top of the profile. |
| `addParentData` | Add the owner's profile details to every post under `metaData`. |
| `searchType` | Only `user` is supported. |
| `includeAboutSection` | Accepted for compatibility; the about section needs a login and is not scraped. |
| `outputFormat` | `auto` (default), `default` or `apify`. See [Switching from Apify's Instagram scrapers](#switching-from-apifys-instagram-scrapers). |
| `proxy` | Apify residential proxy by default ($0.008 per MB of traffic). To use your own (no traffic charge): `{ "useApifyProxy": false, "proxyUrls": ["http://user:password@host:port"] }`. |

Posts:

```json
{
    "directUrls": ["https://www.instagram.com/nasa/"],
    "resultsType": "posts",
    "searchType": "user",
    "onlyPostsNewerThan": "14 days",
    "addParentData": true,
    "skipPinnedPosts": false,
    "proxy": { "useApifyProxy": false, "proxyUrls": ["http://user:password@proxy.example.com:8000"] }
}
```

Profile details:

```json
{
    "usernames": ["nasa"],
    "includeAboutSection": false,
    "proxy": { "useApifyProxy": false, "proxyUrls": ["http://user:password@proxy.example.com:8000"] }
}
```

### Output

Each post is one item in the dataset. Example (shortened):

```json
{
    "id": "3983374110243288826",
    "shortCode": "DdHyaYAifb6",
    "postUrl": "https://www.instagram.com/p/DdHyaYAifb6/",
    "contentType": "carousel",
    "productType": "carousel_container",
    "text": "Cementing their names in history. The Artemis III crew is leaving their mark...",
    "hashtags": [],
    "mentions": ["NASAKennedy", "EuropeanSpaceAgency"],
    "createdTime": "2026-09-10T21:20:24.000Z",
    "likesCount": 119152,
    "commentsCount": 880,
    "videoPlayCount": null,
    "videoDuration": null,
    "imageUrl": "https://instagram.fbkk5-1.fna.fbcdn.net/v/t51.82787-15/805027638_...jpg",
    "videoUrl": null,
    "carouselItems": [
        { "id": "3983374043612570267", "contentType": "image", "imageUrl": "https://...jpg", "videoUrl": null }
    ],
    "width": 1440,
    "height": 1800,
    "isPinned": true,
    "isPaidPartnership": false,
    "location": null,
    "taggedUsers": [
        { "id": "549403870", "username": "nasakennedy", "fullName": "NASA's Kennedy Space Center", "isVerified": true }
    ],
    "coauthors": [
        { "id": "549403870", "username": "nasakennedy", "fullName": "NASA's Kennedy Space Center", "isVerified": true }
    ],
    "ownerId": "528817151",
    "ownerUsername": "nasa",
    "ownerFullName": "NASA",
    "inputUsername": "nasa"
}
```

`ownerUsername` is the account that published the post. For collaboration posts this can be a different account than the profile you scraped, so use `inputUsername` to group posts by the profile you asked for.

With **Add profile details to each post** turned on, or in profile-only mode, the profile looks like this:

```json
{
    "userId": "528817151",
    "username": "nasa",
    "url": "https://www.instagram.com/nasa/",
    "fullName": "NASA",
    "biography": "Making the seemingly impossible, possible. ✨",
    "externalUrls": [{ "title": "NASA.gov Homepage", "url": "https://www.nasa.gov" }],
    "followersCount": 104282125,
    "followsCount": 89,
    "isVerified": true,
    "isPrivate": false,
    "profilePicUrl": "https://scontent.cdninstagram.com/v/t51.2885-19/...jpg",
    "profilePicUrlHD": "https://scontent.cdninstagram.com/v/t51.2885-19/...jpg",
    "highlightsCount": 5,
    "postsCount": 4512,
    "isBusinessAccount": true,
    "businessCategoryName": "Government organization",
    "externalUrl": "https://www.nasa.gov",
    "fbid": "17841400008460056"
}
```

A summary of each run (which profiles succeeded, failed or were skipped, and why, plus the Apify Proxy traffic used) is saved as `RUN_SUMMARY` in the run's key-value store.

A run whose profiles are missing, private, restricted or mistyped still ends as succeeded, with the reasons in its status message and `RUN_SUMMARY`; it only fails when the scraper itself could not get through to Instagram. When Instagram stops answering partway through a profile's posts, the posts already scraped are kept and the profile counts as done.

### Switching from Apify's Instagram scrapers

This Actor can replace **apify/instagram-scraper** (posts of a profile) and **apify/instagram-profile-scraper** without changes to your code: send the same input and you get the same output fields (`url`, `timestamp`, `caption`, `displayUrl`, `childPosts`, `type`, `metaData`, `latestPosts`, `postsCount`, ...).

- **Posts**: the input of apify/instagram-scraper works as is: `directUrls`, `resultsType: "posts"`, `searchType: "user"`, `onlyPostsNewerThan`, `skipPinnedPosts`, `addParentData` (adds `metaData` to each post) and `proxy` (Apify residential by default, or your own `proxyUrls`).
- **Profiles**: the input of apify/instagram-profile-scraper (`usernames`, `includeAboutSection`, `proxy`) returns one profile item per username, including `latestPosts`. `resultsType: "details"` or `onlyProfileInfo: true` does the same.
- **Errors**: a profile that can't be scraped is written as `{ inputUrl, url, username, error, errorDescription }` (`error` is `not_found`, `private`, `restricted`, `invalid_input` or `failed`), and is not charged.

The compatible format is chosen automatically when the input uses those Actors' fields; set `outputFormat` to `apify` or `default` to choose it yourself. Only profile scraping is supported: hashtag, place and comment searches, and the "about this account" add-on (`includeAboutSection`), are ignored with a warning.

### Integrations and API

Run the scraper from your own code with the [Apify API](https://docs.apify.com/api/v2), or the [JavaScript](https://docs.apify.com/api/client/js) and [Python](https://docs.apify.com/api/client/python) clients. Schedule it to run daily or weekly, and connect the results to Google Sheets, Slack, Zapier, Make, Airbyte, webhooks and [other integrations](https://apify.com/integrations).

### FAQ

#### Do I need an Instagram account or cookies?

No. The scraper only reads public data that Instagram shows to visitors who are not logged in, so your accounts are never at risk.

#### Can I use my own proxy?

Yes. The scraper uses Apify residential proxy by default, billed at $0.008 per MB of traffic. To use your own and skip that charge, select **Own proxies** and enter your proxy URLs. If a request fails 3 times on your own proxy (blocked, rate-limited, out of traffic), the scraper retries it up to 3 times on Apify residential proxy so the profile is still scraped; that traffic is charged at the same $0.008 per MB. Residential or mobile proxies from any provider work (Oxylabs, Bright Data, GoProxies, ...); Instagram blocks datacenter IPs quickly.

#### Can it scrape private profiles?

No. Private profiles are skipped, and they appear in the run summary as `Profile is private`. You can still get their basic profile details with **Scrape profile details only**.

#### Why do some results have `likesCount: null`?

The account has hidden like counts on that post.

#### Why are pinned posts older than my date filter?

Pinned posts always appear at the top of a profile. The date filter skips old pinned posts automatically. Turn on **Skip pinned posts** to ignore all pinned posts.

#### Is it legal to scrape Instagram?

This scraper collects only publicly available data. However, results may contain personal data, which is protected by regulations such as the GDPR in the European Union. Do not scrape personal data unless you have a legitimate reason to. If you are unsure, consult a lawyer. You can also read the Apify blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

#### Something does not work. What should I do?

Open an issue in the **Issues** tab. Include the run link and the profiles you tried, and we will look into it quickly.

# Actor input Schema

## `directUrls` (type: `array`):

Profiles to scrape. Accepts profile URLs (<code>https://www.instagram.com/nasa/</code>), usernames (<code>nasa</code>, <code>@nasa</code>) and share links (<code>nasa?igsh=...</code>).

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

Same as above, in the input format of Apify's Instagram Profile Scraper. Sent together with <code>includeAboutSection</code> and without <code>directUrls</code>, it returns profile details only.

## `resultsType` (type: `string`):

<code>posts</code>: the posts of each profile. <code>details</code>: one item per profile with its details and 12 latest posts. Empty means posts, unless the input looks like an Instagram Profile Scraper input.

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

Only scrape posts published after this date. Absolute (<code>2025-01-31</code>) or relative (<code>7 days</code>, <code>2 weeks</code>, <code>3 months</code>). Old pinned posts are skipped.

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

Maximum number of posts per profile. Default 50, or 1,000 when <b>Only posts newer than</b> is set. You pay per post, so keep this as low as you need.

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

Ignore posts pinned to the top of the profile (they are often old).

## `addParentData` (type: `boolean`):

Attach the owner's profile details (followers, posts count, bio, links, ...) to every post under <code>metaData</code>.

## `searchType` (type: `string`):

Only <code>user</code> (profiles) is supported. Accepted for compatibility with Apify's Instagram Scraper.

## `includeAboutSection` (type: `boolean`):

Accepted for compatibility with Apify's Instagram Profile Scraper. The about section (join date, country) needs a login, so it is not scraped.

## `outputFormat` (type: `string`):

<code>auto</code> uses the Apify Instagram Scraper format whenever the input uses its fields (<code>directUrls</code>, <code>resultsType</code>, <code>addParentData</code>, ...). <code>default</code> uses this Actor's own field names.

## `proxy` (type: `object`):

Apify residential proxy by default; its traffic is charged at cost, $0.008 per MB (billed per 100 KB). To avoid that charge, select <b>Own proxies</b> and enter your proxy URLs, e.g. <code>http://user:password@proxy.example.com:8000</code>. Instagram blocks datacenter IPs quickly, so use residential or mobile proxies.

## Actor input object example

```json
{
  "directUrls": [
    "https://www.instagram.com/nasa/"
  ],
  "skipPinnedPosts": false,
  "outputFormat": "auto",
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Scraped posts with captions, likes, comments, video plays, media URLs and more.

## `profiles` (type: `string`):

Profile details, when the Actor runs in profile-only mode.

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

Which profiles succeeded, failed or were skipped, and why.

# 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 = {
    "directUrls": [
        "https://www.instagram.com/nasa/"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("arisma_tech/instagram-profile-posts-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 = {
    "directUrls": ["https://www.instagram.com/nasa/"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("arisma_tech/instagram-profile-posts-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 '{
  "directUrls": [
    "https://www.instagram.com/nasa/"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call arisma_tech/instagram-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

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