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

📸 Scrape public Instagram profiles, recent posts, reels, captions, engagement counts, media URLs, and profile metadata from handles or URLs.

- **URL**: https://apify.com/fetch\_cat/instagram-profile-posts-scraper.md
- **Developed by:** [Hanna Nosova](https://apify.com/fetch_cat) (community)
- **Categories:** Social media, Lead generation, Videos
- **Stats:** 13 total users, 10 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 item extracteds

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Instagram Profile & Posts Scraper

Scrape public Instagram profiles or paste direct public post/reel URLs to get complete, download-ready image and video media arrays, captions, engagement, audio metadata, and handled-error diagnostics.

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

Instagram Profile & Posts Scraper helps you collect public profile metadata and recent public media previews from Instagram profiles.
It is designed for teams that need structured exports instead of manual copy and paste.

You can enter handles like `nasa`, profile URLs, or direct URLs such as `https://www.instagram.com/p/SHORTCODE/` and `https://www.instagram.com/reel/SHORTCODE/`.
The actor returns profile rows, complete media rows, and unbilled diagnostic rows for restricted or unavailable inputs.

### Who is it for?

- 📣 Social media marketers monitoring public creator or brand accounts.
- 🧑‍💼 Brand teams checking public profile positioning and recent campaigns.
- 📊 Analysts comparing public engagement signals across accounts.
- 🛡️ Compliance teams archiving public posts for review workflows.
- 📰 Researchers tracking public media URLs, captions, and timestamps.

### Why use this scraper?

Manual Instagram monitoring is slow and inconsistent.
This actor gives you repeatable exports with stable field names.
You can schedule it, connect it to datasets, or call it from the Apify API.

### What data can you extract?

| Category | Example fields |
| --- | --- |
| Profile identity | handle, profile URL, full name |
| Profile metadata | bio, avatar URL, external URL |
| Public counts | followers, following, posts |
| Account flags | verified, private |
| Post identity | post URL, shortcode |
| Post content | caption, timestamp, media type |
| Engagement | likes, comments, views when visible |
| Media | every carousel asset, highest-resolution image URL, direct video URL, thumbnail |
| Video and audio | duration, play/view count, audio artist/title, original-audio flag |
| Diagnostics | per-input error code, message, and HTTP status for unavailable inputs |

### How much does it cost to scrape Instagram profiles and posts?

This Actor uses Apify pay-per-event pricing. Error/diagnostic rows are not charged.

| Event | What is charged | Price |
| --- | --- | ---: |
| `start` | One-time fee when a run starts. | $0.005 |

| Event | What is charged | Free / no discount | Starter / Bronze | Scale / Silver | Business / Gold | Custom / Platinum | Custom / Diamond |
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
| `item` | Each saved public profile or media row. | $0.062896 / 1,000 | $0.054692 / 1,000 | $0.042660 / 1,000 | $0.032815 / 1,000 | $0.021877 / 1,000 | $0.015314 / 1,000 |

Use low limits first, then increase `maxProfiles`, `maxPostsPerProfile`, or `maxDirectUrls` after checking output quality.

### Quick start

1. Open the actor on Apify.
2. Add Instagram handles such as `nasa` or `natgeo`.
3. Keep `maxPostsPerProfile` low for your first run.
4. Start the run.
5. Export the dataset as JSON, CSV, Excel, or via API.

### Input settings

Core JSON keys: `profileUrlsOrHandles`, `postUrls`, `maxProfiles`, `maxPostsPerProfile`, `maxDirectUrls`, `includePosts`, `includeReels`, `onlyPostsNewerThan`, `until`, `maxConcurrency`, `startUrls`, and `proxyConfiguration`.

#### Profile URLs or handles

Use this when you already know the usernames.
You can include or omit the `@` sign.

#### Instagram profile URLs

Use this when your source list contains full links.
The actor extracts the handle from each URL.

#### Maximum profiles

Controls how many unique profiles are processed.
Duplicate handles and URLs are deduplicated.

#### Include recent posts

When enabled, the actor saves recent public post or reel preview rows returned for the profile.

#### Include reels/videos

Disable this option if you only want image and carousel-style posts.

#### Direct post or reel URLs

Add public `/p/`, `/reel/`, or `/tv/` URLs in `postUrls`. Each successful row contains ordered `mediaAssets`, flattened `mediaUrls`, and convenient best-image/video fields. Carousel results include every asset Instagram exposes.

#### Date bounds

Use `onlyPostsNewerThan` with an ISO timestamp or a relative value such as `7 days`, and `until` with an ISO timestamp. Bounds are inclusive and apply to media rows; profile rows remain available for backward compatibility.

#### Maximum posts per profile and direct URLs

`maxPostsPerProfile`, `maxProfiles`, and `maxDirectUrls` are independent hard caps. Duplicate inputs are removed before processing.

#### Mixed legacy URLs and concurrency

`startUrls` remains a backward-compatible mixed list: profile URLs and public `/p/`, `/reel/`, or `/tv/` URLs are classified automatically. `maxConcurrency` is retained for old inputs; requests are intentionally processed sequentially to reduce rate-limit risk.

#### Proxy configuration

Apify Proxy is enabled by default for cloud reliability because Instagram can rate-limit shared datacenter traffic.
You can override the proxy configuration if your account requires a specific proxy setup.

### Example input

Profile mode remains backward compatible:

```json
{
  "profileUrlsOrHandles": ["nasa", "natgeo"],
  "maxProfiles": 2,
  "includePosts": true,
  "includeReels": true,
  "maxPostsPerProfile": 5,
  "onlyPostsNewerThan": "30 days",
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Direct download mode:

```json
{
  "postUrls": [
    "https://www.instagram.com/p/DalfZ3Jn8yi/",
    "https://www.instagram.com/reel/Dabg9j1xNHM/"
  ],
  "maxDirectUrls": 2
}
```

### Output example

```json
{
  "type": "profile",
  "profileUrl": "https://www.instagram.com/nasa/",
  "username": "nasa",
  "fullName": "NASA",
  "biography": "Public profile bio when visible",
  "followersCount": 90000000,
  "isVerified": true,
  "scrapedAt": "2026-07-03T00:00:00.000Z"
}
```

```json
{
  "input": "https://www.instagram.com/reel/SHORTCODE/",
  "profileUrl": "https://www.instagram.com/creator/",
  "username": "creator",
  "postUrl": "https://www.instagram.com/reel/SHORTCODE/",
  "shortCode": "SHORTCODE",
  "caption": "Caption text when visible",
  "timestamp": "2026-07-03T00:00:00.000Z",
  "likesCount": 12345,
  "commentsCount": 123,
  "type": "video",
  "videoDurationSeconds": 42.5,
  "videoPlayCount": 50000,
  "thumbnailUrl": "https://...jpg",
  "videoUrl": "https://...mp4",
  "mediaUrls": ["https://...mp4"],
  "mediaAssets": [{ "position": 1, "type": "video", "url": "https://...mp4" }],
  "audioArtist": "Creator",
  "audioTitle": "Original audio",
  "isOriginalAudio": true,
  "scrapedAt": "2026-07-03T00:00:00.000Z"
}
```

### Output fields

- `type` — `profile` for profile rows, `post`, `image`, `carousel`, `video`, or another visible Instagram source type for media rows.
- `profileUrl` — public Instagram profile URL.
- `username` — Instagram username.
- `fullName` — public display name when visible.
- `biography` — public bio text when visible.
- `profilePicUrl` — profile picture URL when visible.
- `externalUrl` — public external link when visible.
- `followersCount` — follower count when visible.
- `followingCount` — following count when visible.
- `postsCount` — public post count when visible.
- `isVerified` — verification flag when visible.
- `isPrivate` — private account flag when visible.
- `isBusinessAccount`, `isProfessionalAccount`, `categoryName`, `businessEmail`, `businessPhoneNumber` — public account metadata when Instagram exposes it.
- `postUrl` — public post URL for post rows.
- `shortCode` — Instagram shortcode.
- `caption` — caption text when visible.
- `timestamp` — post timestamp when visible.
- `likesCount` — like count when visible.
- `commentsCount` — comment count when visible.
- `videoViewCount` / `videoPlayCount` — public view/play count when visible.
- `videoDurationSeconds` — public video duration.
- `thumbnailUrl` — public thumbnail URL.
- `highestResolutionImageUrl` / `videoUrl` — convenient best image and video download URLs.
- `imageUrls`, `videoUrls`, `mediaUrls` — flattened public asset URLs.
- `mediaAssets` — every ordered carousel asset with type, dimensions, thumbnail, and duration when available.
- `audioArtist`, `audioTitle`, `isOriginalAudio` — public music/audio attribution.
- `isError`, `errorCode`, `errorMessage`, `statusCode` — per-input handled diagnostic. These rows are saved for debugging but are not charged as item events.
- `scrapedAt` — time the row was saved.

### Tips for better results

- Start with 1-2 handles before running a larger list.
- Use public profiles only.
- Avoid private or login-only accounts.
- Keep post limits modest for scheduled monitoring.
- Export CSV for spreadsheets and JSON for automation.

### Scheduling workflows

Run the actor daily or weekly to monitor public account changes.
Store each run in Apify datasets.
Connect the dataset to downstream reporting, alerting, or archival tools.

### Integrations

#### Google Sheets

Export dataset results to CSV or connect through the Apify API.
This is useful for campaign tracking sheets.

#### BI dashboards

Load JSON or CSV exports into dashboards for profile and engagement trend reports.

#### Compliance review

Archive public captions, URLs, and timestamps for later review.

#### CRM enrichment

Add public profile URLs, bios, and follower counts to creator or partner records.

### API usage

#### Node.js

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/instagram-profile-posts-scraper').call({
  profileUrlsOrHandles: ['nasa'],
  maxProfiles: 1,
  maxPostsPerProfile: 5
});
console.log(run.defaultDatasetId);
```

#### Python

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('fetch_cat/instagram-profile-posts-scraper').call(run_input={
    'profileUrlsOrHandles': ['nasa'],
    'maxProfiles': 1,
    'maxPostsPerProfile': 5,
})
print(run['defaultDatasetId'])
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/fetch_cat~instagram-profile-posts-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"profileUrlsOrHandles":["nasa"],"maxProfiles":1,"maxPostsPerProfile":5}'
```

### MCP usage

Use the Apify MCP server with tools scoped to this actor:

```text
https://mcp.apify.com/?tools=fetch_cat/instagram-profile-posts-scraper
```

Add it to Claude Code:

```bash
claude mcp add apify-instagram-profile-posts https://mcp.apify.com/?tools=fetch_cat/instagram-profile-posts-scraper
```

Claude Desktop JSON configuration:

```json
{
  "mcpServers": {
    "apify-instagram-profile-posts": {
      "url": "https://mcp.apify.com/?tools=fetch_cat/instagram-profile-posts-scraper"
    }
  }
}
```

Example prompts:

- "Run the Instagram Profile & Posts Scraper for nasa and summarize the latest captions."
- "Export recent public post URLs for these brand handles."
- "Compare public follower counts for this creator shortlist."

### Data quality notes

Instagram may hide some fields for some accounts, regions, or request contexts.
When a public field is not visible, the actor leaves it empty instead of guessing.
Counts can change frequently and should be treated as point-in-time values.

### Limitations

- Public profiles only.
- No private posts.
- No login-only stories or highlights.
- No direct messages.
- Recent post previews depend on what Instagram returns publicly.

### Troubleshooting

#### Why did a handle return no rows?

The handle may be invalid, private, blocked, renamed, unavailable in your region, or temporarily unavailable from Instagram.
Try the public profile URL in a browser and lower your run limits.

#### Why are some engagement counts missing?

Instagram does not expose every metric for every media item in every public response.
The actor saves metrics only when they are visible.

#### Why should I keep low limits first?

Low limits make it easier to verify output and avoid unnecessary proxy or compute usage.
Increase limits once your input list is clean.

### Legality

This actor is intended for public data collection.
Use it responsibly and respect Instagram terms, privacy rights, and applicable laws.
Do not use it to collect private, login-only, sensitive, or personal data in a way that violates rights or policies.

### Related scrapers

- [Instagram Stories & Highlights Scraper](https://apify.com/fetch_cat/instagram-stories-highlights-scraper) — collect public Instagram story and highlight metadata when available.
- [Threads Profile Posts Scraper](https://apify.com/fetch_cat/threads-profile-posts-scraper) — monitor public Threads profiles and posts.
- [X Profile Tweets Scraper](https://apify.com/fetch_cat/x-profile-tweets-scraper) — export public X profile timelines for cross-channel analysis.
- [TikTok Video Scraper](https://apify.com/fetch_cat/tiktok-video-scraper) — collect public TikTok video metadata for creator research.

### Support

If a run fails or output looks wrong, open a bug report from the Actor page. Include the Apify run ID or run URL, input JSON, expected output, actual output, and one reproducible public URL from Instagram.

### FAQ

#### Can I scrape private accounts?

No. This actor is public-only.

#### Do I need cookies?

No. V1 is designed without cookies or user login.

#### Can I schedule it?

Yes. Use Apify schedules for recurring monitoring.

#### Can I export to Excel?

Yes. Apify datasets support Excel, CSV, JSON, XML, and RSS exports.

#### Does it scrape comments?

No. It returns comment counts when visible, not full comment threads.

#### Does it download media files?

No. It returns media and thumbnail URLs when visible.

#### Can I use URLs instead of handles?

Yes. Add public Instagram profile URLs to `profileUrlsOrHandles`.

#### What happens with duplicate inputs?

Duplicate handles and URLs are deduplicated before scraping.

#### Is this an official Instagram API?

No. This is an Apify actor for public web data extraction.

#### How should I start?

Run one public handle with five posts, inspect the dataset, then scale up.

- 0.1 — Initial public-profile and recent-post scraper.

# Actor input Schema

## `profileUrlsOrHandles` (type: `array`):

Public Instagram usernames or profile URLs. You can include or omit the @ sign.

## `postUrls` (type: `array`):

Public Instagram /p/, /reel/, or /tv/ URLs. Each result includes every exposed carousel asset and highest-resolution image/video URLs.

## `maxPostsPerProfile` (type: `integer`):

Hard maximum recent post/reel records saved per profile.

## `maxDirectUrls` (type: `integer`):

Hard maximum number of unique direct post/reel URLs processed.

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

Inclusive lower date bound. Use an ISO date/time or a relative value such as 7 days, 2 weeks, or today. Profile rows are not filtered.

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

Inclusive upper date bound as an ISO date/time. Profile rows are not filtered.

## `includeReels` (type: `boolean`):

Include video or reel-like results discovered through profile mode. Direct reel URLs are always processed.

## `maxConcurrency` (type: `integer`):

Reserved concurrency limit for processing. Keep this low to reduce Instagram rate-limit risk.

## `maxProfiles` (type: `integer`):

Hard maximum number of unique profiles processed.

## `includePosts` (type: `boolean`):

Save recent public posts returned with each profile. Direct post/reel URLs are always processed.

## `handles` (type: `array`):

Backward-compatible alias for Profile URLs or handles.

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

Backward-compatible URL list. Profile, /p/, /reel/, and /tv/ URLs are classified automatically.

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

Optional Apify Proxy configuration. Enabled by default for cloud reliability because Instagram can rate-limit shared datacenter traffic.

## Actor input object example

```json
{
  "profileUrlsOrHandles": [
    "nasa"
  ],
  "postUrls": [
    "https://www.instagram.com/p/DalfZ3Jn8yi/"
  ],
  "maxPostsPerProfile": 12,
  "maxDirectUrls": 20,
  "includeReels": true,
  "maxConcurrency": 1,
  "maxProfiles": 2,
  "includePosts": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "profileUrlsOrHandles": [
        "nasa"
    ],
    "postUrls": [
        "https://www.instagram.com/p/DalfZ3Jn8yi/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetch_cat/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 = {
    "profileUrlsOrHandles": ["nasa"],
    "postUrls": ["https://www.instagram.com/p/DalfZ3Jn8yi/"],
}

# Run the Actor and wait for it to finish
run = client.actor("fetch_cat/instagram-profile-posts-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "profileUrlsOrHandles": [
    "nasa"
  ],
  "postUrls": [
    "https://www.instagram.com/p/DalfZ3Jn8yi/"
  ]
}' |
apify call fetch_cat/instagram-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fetch_cat/instagram-profile-posts-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/IDqOPM6P8vfYZ9sgl/builds/c1hZmzXg58VMWzcjt/openapi.json
