# Instagram Scraper: Profile, Posts & Follower Data, No Login (`scrapers_lat/instagram-scraper`) Actor

Instagram scraper, no login or API key. Extract public profiles and posts by username or URL: followers, following, bio, email, verified badge, category, captions, hashtags, mentions, likes, comments, views, reel music, media URLs. Filter posts by type, likes, date or keyword. JSON, CSV, Excel.

- **URL**: https://apify.com/scrapers_lat/instagram-scraper.md
- **Developed by:** [Scrapers Lat](https://apify.com/scrapers_lat) (community)
- **Categories:** Social media, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 65 total users, 8 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $6.15 / 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 Profile & Posts Scraper](https://scrapers.lat/banners/instagram-scraper.png)](https://console.apify.com/actors/QE0yktj74B94JgcFw/input)

## Instagram Scraper: Profile, Posts & Follower Data, No Login

A fast Instagram scraper that pulls public profile data, posts, and follower counts by username or profile URL.

### Sample output

| Field | Example value |
|---|---|
| `type` | post |
| `username` | 9gag |
| `fullName` | 9GAG: Go Fun The World |
| `url` | `https://www.instagram.com/p/Db7k8Qaka8Z/` |
| `ownerId` | 259220806 |
| `followersCount` | 52112356 |
| `mediaType` | GraphSidecar |
| `width` | 750 |

You can test it on a free Apify plan with up to 10 results per run.

A fast **Instagram scraper** that pulls public **profile data**, **posts**, and **follower counts** by username or profile URL, with **no login and no API key**. Get a clean structured feed for influencer research, social media analytics, engagement metrics, and lead generation. Export to JSON, CSV, or Excel.

Here is one real result, with every field a post record returns:

```json
{
  "imageUrl": "https://scontent-bos5-1.cdninstagram.com/v/t51.82787-15/773402982_19214295055020807_3804665531988145921_n.jpg",
  "type": "post",
  "username": "9gag",
  "fullName": "9GAG: Go Fun The World",
  "url": "https://www.instagram.com/p/DcAg2kDEa5m/",
  "id": "3963312159132331622",
  "shortcode": "DcAg2kDEa5m",
  "ownerId": "259220806",
  "followersCount": 52112356,
  "isVerified": true,
  "mediaType": "GraphImage",
  "isVideo": false,
  "caption": "cause I don't wanna annoy my friends - #chatgpt #relationship #memes #9gag",
  "accessibilityCaption": null,
  "likesCount": 21519,
  "commentsCount": 134,
  "commentsDisabled": false,
  "videoViewCount": null,
  "isPinned": false,
  "locationName": null,
  "width": 1080,
  "height": 1350,
  "videoUrl": null,
  "childImageUrls": [],
  "taggedUsers": [],
  "coauthors": [],
  "takenAt": "2026-08-14T05:01:38.000Z",
  "productType": null,
  "isReel": null,
  "isCarousel": false,
  "childCount": null,
  "hasAudio": null,
  "thumbnailUrl": "https://scontent-bos5-1.cdninstagram.com/v/t51.82787-15/773402982_19214295055020807_3804665531988145921_n.jpg",
  "hashtags": ["chatgpt", "relationship", "memes", "9gag"],
  "mentions": [],
  "locationId": null,
  "locationSlug": null,
  "musicArtist": null,
  "musicTitle": null,
  "musicUsesOriginalAudio": null,
  "musicAudioId": null,
  "likeAndViewCountsDisabled": false,
  "children": [],
  "observedAt": "2026-08-14T08:32:22.186Z",
  "error": null,
  "aiSentiment": "neutral",
  "aiSentimentScore": 0,
  "aiTopics": ["chatgpt", "relationship", "memes", "9gag"],
  "aiCategory": "comedy"
}
```

The most complete no-login Instagram scraper available. It returns every field the public profile and post endpoints expose, plus parsed hashtags and mentions, per-slide carousel detail, related-profile discovery, and optional AI caption enrichment, and gives you six post filters to target exactly the posts you need.

**[Input](https://apify.com/scrapers_lat/instagram-scraper/input-schema) | [Output](https://apify.com/scrapers_lat/instagram-scraper/output-schema) | [Pricing](https://apify.com/scrapers_lat/instagram-scraper/pricing) | ▶️ [Examples](https://apify.com/scrapers_lat/instagram-scraper/examples)**

![Apify](https://img.shields.io/badge/Platform-Apify-1CE1CE?logo=apify\&logoColor=white)
![Coverage](https://img.shields.io/badge/Coverage-Public%20accounts-blue)
![Output](https://img.shields.io/badge/Output-JSON%20%7C%20CSV%20%7C%20Excel-orange)
![Billing](https://img.shields.io/badge/Billing-Pay%20per%20result-brightgreen)

### Table of contents

- [What it does](#what-it-does)
- [How this compares](#how-this-compares)
- [Quickstart](#quickstart)
- [Input reference](#input-reference)
- [Output reference](#output-reference)
- [Example output record](#example-output-record)
- [Run via API and CLI](#run-via-api-and-cli)
- [Fetch results](#fetch-results)
- [Billing and limits](#billing-and-limits)
- [FAQ and troubleshooting](#faq-and-troubleshooting)

### What it does

The actor takes one or more public Instagram usernames, reads the public web profile for each, and writes one normalized record per result to the run's dataset. In Profile mode it returns one profile record per username. In Posts mode it returns one record per recent public post, each carrying its parent profile context (username, full name, follower count, verified flag).

It reads only the public data any logged-out visitor can see, so it never logs in and needs no cookies. Hashtags and mentions are parsed out of every caption and bio into clean arrays, carousels return per-slide detail, and the suggested accounts Instagram surfaces next to a profile are attached as `relatedProfiles`. Two optional paid AI add-ons classify each post caption's sentiment and topic/category.

Only public accounts are supported. Private accounts expose no public posts, so the actor returns an error record for them.

### How this compares

Built to be a strict superset of the common Instagram profile and post scrapers on the input and output it can deliver without a login. It accepts the same inputs (usernames, profile URLs, results type, results limit, date filters), returns the same core outputs, and adds parsed hashtags/mentions, per-slide carousel detail, related-profile discovery, paid-partnership flags, and optional AI caption enrichment.

| Capability | This actor | Typical profile scraper | Typical posts scraper |
|---|---|---|---|
| Username input | Yes | Yes | Yes |
| Profile URL input | Yes | Yes | Yes |
| Profile fields (followers, following, bio, category, contact) | Yes | Yes | Partial |
| Business email / phone / address (when public) | Yes | Partial | No |
| Recent posts with captions and engagement | Yes | No | Yes |
| Video view counts and reel music attribution | Yes | No | Partial |
| Parsed hashtags and @mentions (post and bio) | Yes | No | Partial |
| Per-slide carousel detail | Yes | No | Partial |
| Paid-partnership / sponsor flags | Yes | No | Partial |
| Related / suggested profile discovery | Yes | No | No |
| Post filters (media type, min likes, date range, keyword) | Yes | No | Partial |
| AI caption sentiment and topics (optional paid add-on) | Yes | No | No |
| No login, no API key | Yes | Varies | Varies |

Honest scope: the public no-login source does not expose comments threads, stories, highlights, tagged-feed, or hashtag/place search (those require a logged-in session), so this actor does not offer them. It focuses on everything a logged-out visitor can see, returned as clean structured data.

### Quickstart

Open the actor, paste this into the input, and press Run. It returns up to 10 recent public posts from `nasa` with their captions, engagement counts and media URLs.

```json
{
  "usernames": ["nasa"],
  "resultsType": "posts",
  "postsLimit": 10,
  "maxRecords": 10
}
```

`usernames` is the only required field. Set `resultsType` to `profile` for one profile record per username instead of posts. Every filter is optional; leaving them empty returns every recent post the profile exposes.

### Input reference

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `usernames` | string\[] | yes | `["nasa"]` | Public Instagram usernames or profile URLs to scrape. Accepts plain handles (`nasa`), `@handles`, or full profile URLs (`https://www.instagram.com/nasa/`). Only public accounts are supported. |
| `directUrls` | string\[] | no | (empty) | Optional Instagram profile URLs, merged with `usernames`. Post/reel URLs (`/p/`, `/reel/`) carry no handle and are skipped. |
| `resultsType` | enum | no | `posts` | `profile` returns one profile record per username. `posts` returns one record per recent public post with profile context. |
| `postsLimit` | integer | no | `12` | Max recent posts per profile in Posts mode. The public no-login endpoint exposes roughly the 12 most recent posts, so higher values are capped to what the profile returns. Range 1 to 12. |
| `maxRecords` | integer | no | `10` | Maximum records to collect across all usernames. |
| `includeRelatedProfiles` | boolean | no | `false` | Also emit the suggested/related accounts as their own records (`type: related_profile`). They are always attached to each profile record in `relatedProfiles` regardless of this setting. |
| `mediaType` | enum | no | `any` | Keep only posts of this media type in Posts mode. One of `any`, `image`, `video`, `sidecar` (carousel), `reel`. |
| `minLikes` | integer | no | (none) | Keep only posts with at least this many likes. |
| `captionContains` | string | no | (empty) | Keep only posts whose caption contains this text (case-insensitive). Useful for a campaign keyword or hashtag. |
| `onlyPostsNewerThan` | string | no | (empty) | Keep only posts published on or after this ISO date or timestamp, for example `2026-01-31`. |
| `onlyPostsOlderThan` | string | no | (empty) | Keep only posts published on or before this ISO date or timestamp, for example `2026-06-30`. |
| `withAiSentiment` | boolean | no | `false` | Paid AI add-on. Classifies each post caption's sentiment (positive/neutral/negative with a score). Posts mode only. Billed per enriched record. |
| `withAiTopics` | boolean | no | `false` | Paid AI add-on. Tags each post caption with a content category and topic tags. Posts mode only. Billed per enriched record. |

Filters combine with logical AND and are applied before a post is charged.

### Output reference

One dataset item per result. Types: `string`, `integer`, `boolean`, `string[]`, `object`, or `null` when the source value is absent.

Fields present on both profile and post records:

| Field | Type | Description |
|---|---|---|
| `type` | string | Record type: `profile`, `post`, or `related_profile`. |
| `username` | string | Account handle without the `@`. |
| `fullName` | string | Display name of the account. |
| `url` | string | Public URL of the profile or post. |
| `id` | string | Instagram numeric id of the profile or post. |
| `imageUrl` | string | Primary image URL (profile picture, or post display image). |
| `isVerified` | boolean | Whether the account carries a verified badge. |
| `followersCount` | integer | Follower count of the account. |
| `observedAt` | string | ISO 8601 timestamp of when the record was collected. |
| `error` | string | `null` on success. On a failed username, a single record with a populated `error` field is written instead. |

Profile record fields (`type: profile`):

| Field | Type | Description |
|---|---|---|
| `biography` | string | Profile bio text. |
| `followingCount` | integer | Number of accounts the profile follows. |
| `postsCount` | integer | Total public posts on the profile. |
| `highlightReelCount` | integer | Number of story highlight reels. |
| `isPrivate` | boolean | Whether the account is private. |
| `isBusinessAccount` | boolean | Whether Instagram flags the account as a business. |
| `isProfessionalAccount` | boolean | Whether it is a professional (business or creator) account. |
| `category` | string | Public category label of the account. |
| `categoryEnum` | string | Machine category code when present. |
| `businessCategoryName` | string | Business category name when present. |
| `overallCategoryName` | string | Overall category name when present. |
| `businessContactMethod` | string | Public contact method shown (for example `CALL`, `EMAIL`), or `null`. |
| `businessAddress` | string | Single-line public business address, or `null`. |
| `businessEmail` | string | Public business email when Instagram exposes it (usually `null` logged-out). |
| `businessPhoneNumber` | string | Public business phone when exposed (usually `null` logged-out). |
| `externalUrl` | string | Website link in the bio. |
| `bioLinks` | string\[] | All link URLs listed on the profile. |
| `fbid` | string | Linked Facebook id when present. |
| `connectedFbPage` | string | Linked Facebook page when present. |
| `fbProfileBiolink` | string | Facebook profile biolink when present. |
| `profilePicUrl` | string | Profile picture URL. |
| `profilePicUrlHd` | string | High-resolution profile picture URL. |
| `hasThreads` | boolean | Whether the account has onboarded to Threads. |
| `hasChannel` | boolean | Whether the account runs a broadcast channel. |
| `hasClips` / `hasGuides` / `hasArEffects` | boolean | Feature-presence flags. |
| `shouldShowPublicContacts` | boolean | Whether Instagram shows public contacts for the account. |
| `isJoinedRecently` | boolean | Whether the account joined recently. |
| `isVerifiedByMv4b` | boolean | Meta Verified for Business flag. |
| `hideLikeAndViewCounts` | boolean | Whether like/view counts are hidden. |
| `isEmbedsDisabled` | boolean | Whether embeds are disabled. |
| `isSupervisionEnabled` | boolean | Whether parental supervision is enabled. |
| `pronouns` | string\[] | Pronouns listed on the profile. |
| `bioHashtags` | string\[] | Hashtags parsed from the bio. |
| `bioMentions` | string\[] | @mentions parsed from the bio. |
| `relatedProfiles` | object\[] | Suggested/related accounts (username, fullName, id, isVerified, isPrivate, profilePicUrl). |

Post record fields (`type: post`):

| Field | Type | Description |
|---|---|---|
| `shortcode` | string | Post shortcode used in its URL. |
| `ownerId` | string | Numeric id of the posting account. |
| `mediaType` | string | Source typename: `GraphImage`, `GraphVideo`, or `GraphSidecar`. |
| `isVideo` | boolean | Whether the primary media is video. |
| `caption` | string | Full post caption text. |
| `accessibilityCaption` | string | Auto-generated accessibility caption when present. |
| `likesCount` | integer | Like count. Null when Instagram hides counts from logged-out visitors (common since November 2026). |
| `commentsCount` | integer | Comment count. |
| `commentsDisabled` | boolean | Whether comments are turned off. |
| `videoViewCount` | integer | Video view count when the post is a video. |
| `isPinned` | boolean | Whether the post is pinned to the profile. |
| `locationName` / `locationId` / `locationSlug` | string | Tagged location detail when present. |
| `width` / `height` | integer | Media dimensions in pixels. |
| `videoUrl` | string | Direct video URL when the post is a video. |
| `thumbnailUrl` | string | Thumbnail image URL. |
| `childImageUrls` | string\[] | Image URLs of each carousel slide. |
| `taggedUsers` | string\[] | Usernames tagged in the media. |
| `coauthors` | string\[] | Verified co-authors of the post. |
| `takenAt` | string | ISO 8601 publish timestamp. |
| `productType` | string | Source product type (for example `clips` for reels). |
| `isPaidPartnership` | boolean | Whether the post is a disclosed paid partnership / branded content. |
| `sponsorUsers` | string\[] | Sponsor account handles tagged on a paid-partnership post, when present. |
| `isReel` | boolean | Whether the post is a reel. |
| `isCarousel` | boolean | Whether the post is a multi-slide carousel. |
| `childCount` | integer | Number of carousel slides. |
| `hasAudio` | boolean | Whether a video post has audio. |
| `hashtags` | string\[] | Hashtags parsed from the caption. |
| `mentions` | string\[] | @mentions parsed from the caption. |
| `musicArtist` / `musicTitle` / `musicAudioId` | string | Reel audio attribution when present. |
| `musicUsesOriginalAudio` | boolean | Whether the reel uses original audio. |
| `children` | object\[] | Per-slide detail for carousels (id, shortcode, isVideo, imageUrl, videoUrl, width, height, taggedUsers). |
| `aiSentiment` | string | AI caption sentiment (`positive`/`neutral`/`negative`), only with `withAiSentiment`. |
| `aiSentimentScore` | integer | AI sentiment score, only with `withAiSentiment`. |
| `aiTopics` | string\[] | AI caption topic tags, only with `withAiTopics`. |
| `aiCategory` | string | AI content category, only with `withAiTopics`. |

### Example output record

Real carousel post record from a live run (input `{"usernames":["9gag"],"resultsType":"posts"}`), showing multi-slide detail:

```json
{
  "type": "post",
  "username": "9gag",
  "fullName": "9GAG: Go Fun The World",
  "url": "https://www.instagram.com/p/Db7k8Qaka8Z/",
  "id": "3961922767671111449",
  "shortcode": "Db7k8Qaka8Z",
  "ownerId": "259220806",
  "followersCount": 52112356,
  "isVerified": true,
  "mediaType": "GraphSidecar",
  "isVideo": false,
  "caption": "How old do I look to you?! Obsession @obsessionthemovie @mcl_cinemas - #Obsession #memes #9gag",
  "likesCount": 18212,
  "commentsCount": 35,
  "isPinned": true,
  "width": 750,
  "height": 937,
  "childCount": 8,
  "isCarousel": true,
  "hashtags": ["Obsession", "memes", "9gag"],
  "mentions": ["obsessionthemovie", "mcl_cinemas"],
  "takenAt": "2026-08-12T09:00:00.000Z",
  "observedAt": "2026-08-14T08:32:22.186Z",
  "error": null
}
```

### Run via API and CLI

Start a run and read the dataset. Replace `<TOKEN>` with your Apify API token.

Run synchronously and get dataset items in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~instagram-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"usernames":["nasa","natgeo"],"resultsType":"posts","postsLimit":12,"minLikes":1000}'
```

Start a run asynchronously:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~instagram-scraper/runs?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"usernames":["starbucks"],"resultsType":"profile"}'
```

Apify CLI:

```bash
apify call scrapers_lat/instagram-scraper \
  --input '{"usernames":["nasa"],"resultsType":"posts"}'
```

### Fetch results

Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing `format`:

```bash
## JSON
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"

## CSV
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"

## Paginate large datasets
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&offset=1000&limit=1000"
```

`<DATASET_ID>` is returned as `defaultDatasetId` in the run object. `clean=true` drops empty and internal fields.

### Billing and limits

- **Pay per result.** Profile and related-profile records bill on the `result` event. Post records bill on the `details` event. See the [pricing tab](https://apify.com/scrapers_lat/instagram-scraper/pricing) for current per-record prices.
- **AI add-ons billed separately.** `withAiSentiment` and `withAiTopics` bill on the `ai_sentiment` and `ai_topics` events, and only when the AI returns usable output. They are off by default and require a paid Apify plan.
- **No charge on failure.** A username that cannot be fetched writes a single record with a populated `error` field and is not charged. Empty runs cost nothing.
- **Spend cap respected.** Set `maxTotalChargeUsd` on the run; once reached, the actor stops emitting and charging further billable records.
- **Free Apify plans** are capped at 10 records per run. Upgrade for higher `maxRecords`.
- **Source limit.** The public no-login endpoint exposes roughly the 12 most recent posts per profile, and Instagram rate-limits heavy request bursts. Requests that get rate-limited return an `error` record rather than partial data.

### FAQ and troubleshooting

**Why are likesCount and commentsCount sometimes null?**
Since November 2026 Instagram shows logged-out visitors the profile, follower counts and the latest 12 posts (caption, media, type, date) but hides like and comment counts. When the counts are hidden those fields are null; everything else is still returned.

**Can I scrape an Instagram profile without logging in?**
Yes. The actor uses only Instagram's public web profile data, so no account, password, or cookies are required. It works on public accounts only.

**Do I need an Instagram API key or access token?**
No. There is no API key, app registration, or access token to set up. You provide public usernames or profile URLs and run the actor.

**Can I scrape by hashtag or location?**
No. Instagram gates hashtag and place feeds behind a logged-in session, so they are not available to a no-login scraper. This actor works from public usernames and profile URLs. Use `captionContains` to filter the returned posts by a hashtag or keyword.

**How reliable is it? Do requests ever fail?**
Instagram rate-limits bursts of logged-out requests, so an individual username can occasionally come back throttled. When that happens the actor writes an `error` record for that username instead of partial data and does not charge it. Re-run throttled usernames later or spread runs out for the most consistent results.

**Can I detect sponsored or branded-content posts?**
Yes, when Instagram discloses them. Post records include `isPaidPartnership` and any `sponsorUsers` handles tagged on the post.

**How many posts can I get per profile?**
The public no-login source exposes roughly the 12 most recent posts per profile. `postsLimit` controls how many of those are returned, up to that ceiling.

**Can it scrape private accounts?**
No. Private accounts expose no public posts. The actor returns an `error` record for them and does not charge.

**A username returned an error about rate limiting. Why?**
Instagram throttles bursts of logged-out requests. When a request is throttled the actor writes an `error` record for that username instead of partial data, and does not charge it. Re-run that username later or spread runs out.

**Why are `businessEmail` and `businessPhoneNumber` null?**
The logged-out web profile endpoint rarely returns the raw email and phone strings even when a contact button is shown. The actor exposes `businessContactMethod` and the public `businessAddress` that the endpoint does return instead. Missing values are returned as `null`, never invented.

**What do the AI fields cost?**
`aiSentiment`/`aiSentimentScore` and `aiTopics`/`aiCategory` are optional paid add-ons, billed only when the AI returns usable output. Leave `withAiSentiment` and `withAiTopics` off to skip them entirely.

**Is this an official Instagram tool?**
No. This actor is independent and is not affiliated with, endorsed by, or sponsored by Instagram or Meta Platforms, Inc. It collects only data publicly visible on public profiles, without logging in. You are responsible for using the data, and the business contact fields in particular, in compliance with Instagram's terms, the GDPR, and other applicable privacy laws.

### Related scrapers

- [YouTube Scraper](https://apify.com/scrapers_lat/youtube-scraper): YouTube videos and channels by search, video URL, or channel URL.
- [X (Twitter) Profiles & Tweets Scraper](https://apify.com/scrapers_lat/x-twitter-scraper): Public X posts, authors, and engagement.
- [Reddit Posts & Comments Scraper](https://apify.com/scrapers_lat/reddit-scraper): Reddit posts and comments from subreddits and search.
- [TikTok Creative Center Top Ads Scraper](https://apify.com/scrapers_lat/tiktok-creative-center-scraper): Top-performing TikTok ads by country and period.
- [App Store Reviews Scraper](https://apify.com/scrapers_lat/app-store-reviews-scraper): Apple App Store reviews and ratings for any app.
- [Google Play App Details Scraper](https://apify.com/scrapers_lat/google-play-apps-scraper): App listings and details from the Google Play Store.

### More scrapers at scrapers.lat

Built and maintained by [scrapers.lat](https://scrapers.lat), where we publish scrapers for US and Latin American public platforms: company registries, government data, finance, e-commerce and more. Browse the catalog or request a custom scraper at [scrapers.lat](https://scrapers.lat).

***

> Independent tool, not affiliated with Instagram or Meta Platforms, Inc. Accesses only publicly visible data on public Instagram profiles, without logging in.

# Actor input Schema

## `maxRecords` (type: `integer`):

Maximum number of records to collect across all usernames. Optional.

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

Public Instagram usernames or profile URLs to scrape. Accepts plain handles (nasa), @handles (@nasa), or full profile URLs (https://www.instagram.com/nasa/). For each account the scraper fetches the public profile and, when Results Type is set to Posts, its most recent public posts. Only public accounts are supported; private accounts return an error record.

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

Optional. Full Instagram profile URLs to scrape (for example https://www.instagram.com/nasa/). Merged with Usernames. Post and reel URLs (/p/, /reel/) do not carry a handle and are skipped.

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

Profile returns one record per username with the public profile fields. Posts returns one record per recent public post (each post record also carries its parent profile context).

## `postsLimit` (type: `integer`):

Maximum number of recent posts to return per profile when Results Type is Posts. The public no-login endpoint exposes roughly the 12 most recent posts per profile, so values above that are capped to whatever the profile returns.

## `includeRelatedProfiles` (type: `boolean`):

Also emit the related / suggested accounts Instagram shows next to each profile as extra records (type: related_profile). Useful for competitor discovery and lead-gen. The related accounts are always attached to each profile record in the relatedProfiles field regardless of this setting.

## `mediaType` (type: `string`):

Only return posts of this media type when Results Type is Posts. Any returns every post.

## `minLikes` (type: `integer`):

Only return posts with at least this many likes. Optional. Leave empty for no minimum.

## `captionContains` (type: `string`):

Only return posts whose caption contains this text (case-insensitive). Optional. Useful for tracking a campaign keyword or hashtag.

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

Only return posts published on or after this date (ISO date such as 2026-01-31, or a full timestamp). Applies within the most recent posts the profile exposes. Optional.

## `onlyPostsOlderThan` (type: `string`):

Only return posts published on or before this date (ISO date such as 2026-06-30, or a full timestamp). Optional.

## `withAiSentiment` (type: `boolean`):

Optional paid AI add-on, off by default. Classifies the sentiment/tone of each post caption (positive/neutral/negative with a score). Applies to posts (resultsType=posts). Requires a paid Apify plan. Billed per enriched record.

## `withAiTopics` (type: `boolean`):

Optional paid AI add-on, off by default. Tags each post caption with a broad content category and specific topic tags. Applies to posts (resultsType=posts). Requires a paid Apify plan. Billed per enriched record.

## Actor input object example

```json
{
  "maxRecords": 10,
  "usernames": [
    "nasa"
  ],
  "resultsType": "posts",
  "postsLimit": 12,
  "includeRelatedProfiles": false,
  "mediaType": "any",
  "withAiSentiment": false,
  "withAiTopics": false
}
```

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

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

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

```

## MCP server setup

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