Instagram Profile Post Scraper avatar

Instagram Profile Post Scraper

Pricing

$19.99/month + usage

Go to Apify Store
Instagram Profile Post Scraper

Instagram Profile Post Scraper

The Instagram Profile Post Scraper collects posts from any public Instagram profile with speed and precision. It extracts captions, images, videos, timestamps, hashtags, and engagement metrics. Use it for research, analytics, content monitoring, or tracking competitor activity.

Pricing

$19.99/month + usage

Rating

0.0

(0)

Developer

Scraper Engine

Scraper Engine

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

0

Monthly active users

a day ago

Last modified

Share

Instagram Post Scraper — Captions, Likes, Comments and Media Data

Instagram Post Scraper extracts public posts — images, videos, carousels and reels — from any Instagram profile, returning captions, hashtags, mentions, like and comment counts, media links, and a sample of comments as structured JSON. Paste one or more usernames, profile URLs, or post shortcodes, set how many posts to pull, and every post streams into the dataset the moment it's collected — no login, cookies, or Instagram API credentials required. Start a run below to see it in action.

What is Instagram Profile Post Scraper?

Instagram Profile Post Scraper is an Apify Actor that reads the public posts on one or more Instagram profiles and returns each post — image, video, carousel, or reel — as a structured JSON record with captions, engagement counts, media links, and a comment sample. It works entirely from Instagram's public pages: no Instagram account, login, or session cookie is read from, or required in, the input schema. It's built for social media managers, competitor and influencer researchers, and developers or AI engineers who need clean, post-level data for dashboards, reports, or LLM pipelines.

What Instagram post data is publicly available to scrape?

Anyone who opens a public Instagram profile in a browser without logging in can already see its posts, captions, hashtags, media, and like/comment counts — Instagram Profile Post Scraper reads the same publicly rendered data.

Data CategoryPublicly AvailableRestricted behind login
Post captions & hashtags
Media (images, video, carousel slides)
Like & comment counts
A sample of commentsFull comment thread — login
Pinned-post status
Account username, verification & privacy flagFull bio, follower/following lists — login
Stories, Reels insights, saved/archived postsLogin (usually the account owner only)
Private-account postsLogin + accepted follow request

Instagram Profile Post Scraper only returns publicly visible data — what any visitor sees. Nothing behind a login wall.

What data can I extract with Instagram Post Scraper?

Each run returns one JSON record per post, covering identity and content fields, engagement and format metrics, and timestamps, comments, and nested media.

Field NameDescription
id, pk, shortcodePost identifiers; shortcode is the code used in Instagram's own post URLs
url, post_urlFull link back to the post on instagram.com
type, product_typeImage / Video / Carousel, plus Instagram's own product type (e.g. clips)
caption, accessibility_captionPost text and Instagram's auto-generated image description
hashtags, mentionsParsed from the caption
display_url, image_links, video_links, images, video_versions, dimensionsMedia URLs, size variants, and pixel dimensions
owner, user, account_username, account_verified, account_profile_pictureThe posting account's username, verification and privacy flags, and profile picture
likes_count / like_count, comments_count / comment_countEngagement counts
views_count / view_count, video_durationVideo/reel playback metrics
is_video, is_carousel, is_pinned, carousel_media_count, carousel_mediaFormat flags and carousel slide data
taken_at_timestamp, date, posted, crawled_at, scraped_atWhen the post went live and when this row was collected (real UTC)
comments, latest_commentsUp to 10 comments per post, each with text, author, and like count
usertags, coauthor_producers, clips_metadataTagged accounts, collaborators, and reel/clip audio metadata when present

Post identity & content fields

id, pk, shortcode, url, post_url, type, product_type, caption, accessibility_caption, hashtags, mentions, display_url, image_links, video_links, images, video_versions, dimensions, owner, user, account_username, account_profile_picture, from_url — everything that identifies the post, describes it, and locates its media.

Engagement & format metrics

likes_count / like_count, comments_count / comment_count, views_count / view_count, video_duration, is_video, is_carousel, is_pinned, carousel_media_count, carousel_media, account_verified — the counts, flags, and booleans used for ranking or filtering posts.

Timestamps, comments & nested media

taken_at_timestamp, date, posted, crawled_at, scraped_at, comments, latest_comments, usertags, coauthor_producers, clips_metadata — when the post happened, when it was scraped, its comment sample, and nested objects like tagged accounts and reel audio.

🤖 Add-on: Need additional Instagram data?

Need the creator's own bio, follower count, and verification badge alongside every post? Pair this Actor with Instagram Posts Scraper With Creator Profiles. Tracking a profile's Stories instead of its feed? Instagram Story Details Scraper covers that surface with the same JSON-first approach.

How does Instagram Post Scraper differ from the official Instagram API?

Meta's Instagram Graph API only returns content the authorizing account itself created — a permission "only allows access to data created by the app user who granted the permission," so it cannot be pointed at a competitor's or influencer's public profile without that profile's owner granting your app access (per Meta's Instagram Graph API documentation, checked 2026-07-30). Instagram Post Scraper instead reads any public profile's posts directly, no token or account ownership required.

FeatureInstagram Graph APIInstagram Post Scraper
Access to other public accounts' postsNot supported without that account's own access token✅ any public profile
Account type requiredBusiness or creator Instagram accountNone
App reviewAdvanced Access requires Meta App Review and business verification to read accounts you don't ownNot applicable
Setup timeApp creation, permission scopes, review, account conversionPaste a username and start the run
Rate limitingGoverned by Meta's content-impression-based platform limitsGoverned by requestDelay / maxRetries and your chosen Apify Proxy, set per run
Output shapeRaw Graph API JSON, versioned per API releaseFixed, unified JSON schema across every post

Use the Graph API when you manage the Instagram account yourself and need first-party analytics or publishing inside your own app. Use Instagram Post Scraper when you need post-level data from public profiles you don't own or control — competitors, influencers, or brand accounts — without going through Meta's app review process.

How to use Instagram Post Scraper

You run this Actor from the Apify platform — there's no separate signup or API key to obtain first.

  1. Open Instagram Profile Post Scraper on the Apify Store (or your Apify Console if you already have it saved).
  2. Add the required input — one or more entries in startUrls: full profile URLs, plain usernames, or post shortcodes.
  3. Set maxPosts (0 for unlimited), pinnedMode, and recent if you only want posts newer than a given date.
  4. Optionally open ⚙️ Advanced Settings to tune requestDelay / maxRetries, and 🛡️ Proxy Configuration — residential proxies are recommended.
  5. Click Start — posts stream into the default dataset as they're collected.
  6. Export the dataset as JSON, CSV, Excel, or XML from the Console, or pull it via the Apify API/SDK.

How to scale to bulk post extraction

startUrls accepts an unlimited number of entries in a single array, so queuing 50 profiles is one run, not fifty separate ones. Profiles are processed one after another within that run, with a requestDelay pause between each; there's no separate "bulk" toggle — the array itself is the bulk input, and posts from every profile land in the same dataset as they're collected.

What can you do with Instagram post data?

  • 📊 Social media managers benchmarking engagement use likes_count, comments_count, and view_count across a profile's posts to see which format or topic performs best.
  • 🕵️ Competitor & influencer researchers use caption, hashtags, and posted to track a rival's or creator's posting cadence and messaging over time.
  • 🛡️ Brand safety teams use mentions and usertags to spot unauthorized brand tags or collaborations surfacing in a creator's feed.
  • 🔬 Researchers and data scientists use caption and latest_comments[].text to build topic or sentiment models across an account's post history.
  • 🤖 AI engineers feed caption, hashtags, and comments into a RAG pipeline or LLM summarizer to power a social-listening or content-briefing agent. Because output is typed JSON reachable through the Apify API, any agent framework that can call an HTTP endpoint can drive this Actor and consume its results directly.

How does Instagram Post Scraper handle rate limits and blocking?

Every request is routed through Apify Proxy using the proxyConfiguration you set (residential proxies are recommended for Instagram); each attempt pulls a fresh rotating proxy URL and a randomized desktop User-Agent. Failed requests are retried automatically: the fallback pagination path retries each request up to maxRetries times and gives up on a profile after 3 consecutive failed pages, while ⚠️ the initial, faster profile-page fetch always retries a fixed 3 times regardless of maxRetries. requestDelay paces the wait between paginated requests and between profiles, and that delay is scaled up automatically on later pages to ease off large profiles. The Actor does not solve CAPTCHAs — if Instagram serves a challenge or login page instead of data, that request is treated as a failure and retried or skipped.

⬇️ Input

Instagram Profile Post Scraper takes the following parameters, defined in .actor/actor.json's input schema:

ParameterRequiredTypeDescriptionExample Value
startUrlsYesarrayList one or more Instagram profile URLs (e.g. https://www.instagram.com/username), plain usernames (e.g. username), or post shortcodes (e.g. ABC123DEF). The actor normalizes everything into usernames.["https://www.instagram.com/nasa/", "mkbhd"]
maxPostsNointeger (min 0, max 10000, default 10)How many posts to scrape per profile. Set to 0 for unlimited posts (use with care for very large profiles).25
pinnedModeNostring (enum: include, skip, only; default include)include: mix pinned + regular posts. skip: ignore pinned posts. only: return only pinned posts when available."include"
recentNostring (nullable)Filter posts by date. Use an absolute date (YYYY-MM-DD) or a relative value like "3 days", "2 weeks", or "1 month". Leave empty to scrape all available posts."2 weeks"
requestDelayNointeger (min 1, max 30, default 2)Base delay in seconds between paginated requests and between profiles. requestDelay=2 → the actor waits roughly 2–4s between page fetches (randomized, increasing on later pages).2
maxRetriesNointeger (min 1, max 10, default 3)How many times to retry a failed page/request before giving up on it.3
proxyConfigurationNoobjectConfigure which proxies to use for scraping. Residential proxies are strongly recommended (and usually required) for reliable Instagram scraping.{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}

Example input

{
"startUrls": [
"https://www.instagram.com/nasa/",
"mkbhd",
"DRnOEjME21V"
],
"maxPosts": 25,
"pinnedMode": "include",
"recent": "2 weeks",
"requestDelay": 2,
"maxRetries": 3,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

⬆️ Output

Every post is pushed to the run's default dataset as one typed, normalized JSON record, with the same field names and shapes on every row. Export it as JSON, CSV, Excel, or XML from the Apify Console, or read it programmatically via the Apify API/SDK. Each row written is charged under the row_result pay-per-event pricing shown on the Actor's pricing tab — the Actor does not push separate uncharged error or accounting rows, so every dataset row you see is a scraped post.

Example output

{
"id": "3776048697886076245_2535829435",
"pk": "3776048697886076245",
"shortcode": "DRnOEjME21V",
"url": "https://www.instagram.com/p/DRnOEjME21V/",
"post_url": "https://www.instagram.com/p/DRnOEjME21V/",
"type": "Video",
"product_type": "clips",
"is_video": true,
"is_carousel": false,
"is_pinned": false,
"has_audio": true,
"posted": "29 Nov 2025, 07:02:23 am",
"taken_at_timestamp": 1764360143,
"date": "2025-11-29T07:02:23Z",
"crawled_at": "2026-07-30T09:15:00Z",
"caption": "Behind the scenes from today's shoot — link in bio for the full video.",
"accessibility_caption": "Photo by Example Account on November 29, 2025.",
"hashtags": ["bts", "launch"],
"mentions": ["examplebrand"],
"usertags": null,
"likes_count": 996806,
"like_count": 996806,
"comments_count": 5024,
"comment_count": 5024,
"views_count": 4210332,
"view_count": 4210332,
"video_duration": 34.5,
"video_links": ["https://scontent.cdninstagram.com/video.mp4"],
"video_versions": [{"width": 1080, "height": 1920, "url": "https://scontent.cdninstagram.com/video.mp4", "type": 101}],
"display_url": "https://scontent.cdninstagram.com/thumb.jpg",
"thumbnail": "https://scontent.cdninstagram.com/thumb.jpg",
"image": "https://scontent.cdninstagram.com/thumb.jpg",
"image_links": ["https://scontent.cdninstagram.com/thumb.jpg"],
"images": [{"url": "https://scontent.cdninstagram.com/thumb.jpg", "width": 1080, "height": 1920}],
"dimensions": {"height": 1920, "width": 1080},
"carousel_media_count": null,
"carousel_media": null,
"coauthor_producers": [],
"owner": {
"id": "2535829435",
"pk": "2535829435",
"username": "example_account",
"profile_pic_url": "https://scontent.cdninstagram.com/profile.jpg",
"is_verified": true,
"is_private": false
},
"user": {
"pk": "2535829435",
"id": "2535829435",
"username": "example_account",
"full_name": "Example Account",
"profile_pic_url": "https://scontent.cdninstagram.com/profile.jpg",
"hd_profile_pic_url_info": {"url": ""},
"is_verified": true,
"is_private": false
},
"account_username": "example_account",
"account_verified": true,
"account_profile_picture": "https://scontent.cdninstagram.com/profile.jpg",
"from_url": "https://www.instagram.com/example_account/",
"clips_metadata": {"audio_type": "original_sounds", "music_info": null},
"scraped_at": "2026-07-30T09:15:01Z",
"comments": [
{
"id": "17912345678901234",
"text": "This is amazing!",
"created_at": 1764361000,
"created_at_utc": 1764361000,
"user": {"pk": "998877", "username": "a_follower", "full_name": "", "profile_pic_url": "", "is_verified": false, "is_private": false},
"comment_like_count": 12,
"has_liked_comment": false
}
],
"latest_comments": [
{
"id": "17912345678901234",
"text": "This is amazing!",
"created_at": 1764361000,
"created_at_utc": 1764361000,
"user": {"pk": "998877", "username": "a_follower", "full_name": "", "profile_pic_url": "", "is_verified": false, "is_private": false},
"comment_like_count": 12,
"has_liked_comment": false
}
]
}

Fields Instagram doesn't expose for a given post — for example carousel_media_count on a single-image post, or user.full_name when only the lightweight page path was used — return as null/[]/{} rather than a guessed value.

How does it work?

Instagram Post Scraper first requests each profile's public page over HTTP through Apify Proxy, using randomized browser-like headers, and reads the JSON Instagram embeds directly in that page's HTML for the profile's most recent posts. If that page doesn't expose any posts — for example because Instagram's markup changed for that profile — the Actor switches to Instagram's own private feed API: it first reads a CSRF token and app ID off the same public page, then pages through results the way a browser would while scrolling. No login, session, or saved cookie is ever used; every request looks like an anonymous visit to a public page. Whichever path succeeds, results are normalized into the same JSON schema before being written to the dataset, so field names and types stay stable even when Instagram changes its front end or private API shape.

Integrations

Instagram Post Scraper runs on the Apify platform, so it works with anything that can call the Apify API or trigger an Apify run.

Calling Instagram Post Scraper programmatically

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run = client.actor("instagram-profile-post-scraper").call(run_input={
"startUrls": ["https://www.instagram.com/nasa/"],
"maxPosts": 25,
"pinnedMode": "include",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["shortcode"], item["likes_count"])

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.

No-code tools (n8n, Make, LangChain)

In n8n, use the HTTP Request node (or the community Apify node) pointed at this Actor's run-and-get-dataset-items endpoint to pull posts straight into a workflow. In Make, the Apify app's "Run Actor and Get Dataset Items" module does the same without writing code. In LangChain or a similar agent framework, wrap the Apify API call in a custom Tool so an agent can request fresh Instagram post data on demand.

Scraping publicly available Instagram posts is generally lawful, since Instagram Post Scraper only reads what any logged-out visitor can already see — no login wall is bypassed. That said, captions, comments, and usernames are personal data, so storing or reusing them can bring GDPR or CCPA into play depending on where your users are and what you do with the data — you need a lawful basis for collecting and retaining it, and you still need to respect Instagram's own Terms of Use for your use case. Consult legal counsel if your use case involves bulk storage of personal data.

Frequently asked questions

What Instagram post fields does Instagram Post Scraper return?

The top fields are caption, likes_count, comments_count, display_url, and posted — see the data fields section above for every key returned on each row.

Does Instagram Post Scraper require an Instagram account or login?

No. It reads Instagram's own public profile and post pages; no username, password, session cookie, or Instagram API credential is accepted as input.

How many posts can I extract in one run?

Up to maxPosts per profile (0 removes the cap, 10000 is the schema's own maximum), across as many profiles as you list in startUrls in a single run. ⚠️ In practice, if Instagram's own profile page already returns posts on the first request, the Actor uses exactly what that page contains and does not paginate further even if maxPosts asks for more — it only switches to the paginated fallback (capped at 100 pages) when that first request returns zero posts.

What happens if a profile is private or doesn't exist?

Instagram Post Scraper logs an error for that profile — "No posts found for @username. Account may be private or unreachable." — and moves on to the next entry in startUrls. No rows are written, and nothing is charged, for a profile that returns zero posts.

Can I scrape multiple Instagram profiles at once?

Yes — list any number of profile URLs, usernames, or shortcodes in startUrls and they're processed one after another within the same run, each streaming its own posts into the shared dataset.

Does Instagram Post Scraper work with Claude, ChatGPT, and other AI agent tools?

Yes, as an HTTP endpoint. It isn't registered as an MCP server, but any agent framework that can call the Apify API — including custom tools built for Claude, ChatGPT, or LangChain — can start a run and read back the resulting JSON.

Does Instagram Post Scraper return data in a format LLMs can use directly?

Yes. Every post is typed, normalized JSON with the same field names and shapes across runs — no HTML to parse and no CSS selectors to maintain — so it can be passed straight to an LLM prompt, indexed into a vector store, or handed to an agent tool.

What happens when Instagram changes its layout or anti-bot system?

The Actor is maintained against Instagram's current page structure and private API shape, and the output schema is designed to stay the same regardless of front-end changes. No specific turnaround time is published for updates.

Can I use Instagram Post Scraper without managing proxies or browser infrastructure?

Yes — proxy rotation (via Apify Proxy / proxyConfiguration), retries, and header rotation are all handled by the Actor. You only choose the proxy group (residential is recommended); there's no separate browser or infrastructure to run yourself.

Which Instagram post fields work best for AI training data and RAG indexing?

For RAG, index caption and latest_comments[].text — the highest-information free text on each post. For training data or structured features, likes_count, comments_count, view_count, is_video, and is_carousel are the most consistently populated numeric/boolean fields across every row, and all fields return as typed primitives or nested objects, never embedded HTML.

What makes Instagram Post Scraper's output reliable without an Instagram login?

Every field is filled from what Instagram itself serves the request, including a real UTC scraped_at/crawled_at timestamp on each row. Fields Instagram doesn't expose for a given post on a given code path — for example a creator's verification badge when only the lightweight profile-page fetch was used — are left null/empty instead of guessed, so a null value always means "not exposed here," never a fabricated placeholder.

ScraperWhat it extracts
Instagram Posts Scraper With Creator ProfilesInstagram posts plus the creator's own profile fields (bio, followers, verification) in one run
Instagram Story Details ScraperPublic Instagram Stories per profile
TikTok User Profile Scraper With Engagement AnalyticsTikTok profile and engagement data
LinkedIn Company Profile ScraperLinkedIn company page data
Snapchat User Stories ScraperPublic Snapchat Stories per user

Your feedback

Found a bug or a field that's not populating? Let us know via the Issues tab on this Actor's Apify Store page, or through Apify's support chat in the Console — reports like this get folded directly into the next update.