Instagram Profile Post Scraper: Media Details & Tagged Posts
Pricing
from $4.99 / 1,000 results
Instagram Profile Post Scraper: Media Details & Tagged Posts
Instagram Profile Post Scraper extracts public profile posts, captions, media URLs, timestamps, engagement metrics, hashtags, mentions, and tagged posts. Build structured datasets for content research, influencer analysis, competitor monitoring, and social media insights.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
0
Bookmarked
10
Total users
2
Monthly active users
a day ago
Last modified
Categories
Share
Instagram Scraper — Extract Posts, Tagged Posts and Comments as JSON
Instagram scraper that pulls a public profile's posts — captions, hashtags, mentions, the full image/video size ladder, and flattened audio fields — plus the profile's real "Tagged" feed as its own labeled rows, plus each post's preview comments. Every response is typed, normalized JSON: no HTML, no selectors, no parsing step. Set profile targets, a post limit, and an optional content-type filter, and you can extract Instagram posts and tagged content for any number of public profiles in one run.
What is Instagram Profile Post Scraper: Media Details & Tagged Posts?
Instagram Profile Post Scraper: Media Details & Tagged Posts is an Apify Actor that fetches public Instagram profile posts, media metadata, and tagged-post activity without an Instagram login or API key. It returns posts, tagged posts, and per-post preview comments in one dataset. No Instagram account is required — the Actor requests public profile and post pages directly over Apify Proxy.
- Scrape posts: captions, hashtags, mentions, likes, comments, views, and every image/video size variant Instagram generated for that post
- Scrape tagged posts: the profile's real "Tagged" tab feed, written as labeled child rows linked back to the profile
- Scrape preview comments attached to each post
- Export as JSON or CSV from the Apify dataset
- No proxy management, no parsing — proxy rotation and retries are handled internally
What data does Instagram Profile Post Scraper: Media Details & Tagged Posts collect?
The Actor returns three kinds of rows in the same dataset: profile posts, tagged posts, and the comments nested inside each post.
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
| Posts | caption, likes, comments, timestamp, media variants | caption, likes_count, comments_count, hashtags, images, video_versions, imageVariantsCount |
| Tagged posts | shortcode, owner, mention flag, engagement | shortcode, ownerUsername, isMentionedInCaption, likesCount, commentsCount |
| Comments (preview) | commenter, text, like count | comments[].text, comments[].user.username, comments[].comment_like_count |
| Owner / profile info | username, verification, privacy | owner.username, owner.is_verified, owner.is_private, user.full_name |
Need more Instagram data?
If you also need follower counts, bios, or hashtag search results, pair this Actor with a dedicated Instagram profile-details or hashtag scraper from API-Empire — this Actor's scope is a target profile's own posts, its tagged-post feed, and post-level comments, not account-level statistics.
How does Instagram Profile Post Scraper: Media Details & Tagged Posts differ from the official Instagram API?
Meta's Instagram Platform API (Graph API) requires an Instagram professional account and is built for managing your own account's content, not for reading arbitrary public profiles; this Actor reads any public profile's posts directly, with no account linkage or app review.
| Feature | Instagram Graph API | This Actor |
|---|---|---|
| Account requirement | Instagram professional (Business/Creator) account | None — no Instagram login |
| Approval process | Standard Access by default; Advanced Access requires App Review and Business Verification to access accounts you don't own | None |
| Data scope | A permission only grants access to data created by the app user who granted it | Any public profile's posts and tagged-post feed |
| Third-party public profiles | Not accessible — only limited public data via specific features like hashtag search | Directly accessible |
| Tagged-post feed | Not exposed as a general-purpose endpoint | Returned as its own labeled dataset rows |
| Setup time | Account linkage, permission review, and (for Advanced Access) Business Verification | Provide profile URLs or usernames and run |
(Graph API details per Meta's Instagram Platform documentation.)
Use the Graph API when you manage the account yourself and need to publish or moderate its own content. Use this Actor when you need posts and tagged-post activity from profiles you don't own or manage.
Why do developers and teams scrape Instagram?
For AI engineers and agent builders
Post captions, hashtags, and tagged-post rows are typed JSON with stable field names, so they can be pushed straight into a vector store or RAG index without an HTML-parsing step. An agent tool can call this Actor with a list of usernames, read back caption, hashtags, and isMentionedInCaption for each row, and use that structured data to answer questions about a creator's content or brand mentions — no scraping logic inside the agent loop.
For marketers and brand teams
Turning on includeTaggedPosts surfaces every post another account tagged a brand or creator in, labeled type="taggedPost" with an isMentionedInCaption flag computed from the caption text. That combination — who tagged you, and whether they also named you — is a direct feed for brand-mention monitoring and creator-partnership tracking, without manually opening each profile's Tagged tab.
For researchers and analysts
postsPerProfile, publishedWithin, and contentTypeFilter together let a researcher pull a bounded, dated, single-content-type sample (e.g., only videos posted in the last 30 days) from a public profile for engagement or content-trend analysis. Only publicly visible posts and profile fields are returned — no private-account content, no login-gated data.
For developers building data products
Because every row carries owner, imageVariantsCount, videoVariantsCount, and flattened audioTitle/audioArtist fields, a scheduled run can feed a media pipeline (e.g., picking the right image rendition for a thumbnail) without a second lookup call. Pair with Apify's Schedule feature to refresh a dataset on a cadence and feed it into a downstream product.
How to scrape Instagram (step by step)
- Open the Actor on its Apify Store page and click Run, or call it via the Apify API /
apify-client - Provide
profileTargets— one or more Instagram profile URLs, plain usernames, or post links (none of the input fields are required; leaving it blank uses the field's own prefilled example) - Set
postsPerProfile,pinFilterMode,contentTypeFilter, and (optionally)includeTaggedPostswithmaxTaggedPoststo shape the result set - Start the run
- Download results as JSON or CSV from the run's Output tab, or pull them programmatically from the dataset
What to do when Instagram changes its structure
The Actor is maintained, and the output schema — field names and types — stays stable on your end even when the underlying scrape logic changes internally, so downstream integrations keep working without code changes.
⬇️ Input
The Actor accepts the parameters below, defined in .actor/actor.json. None are required — every field falls back to a documented default.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
profileTargets | No | array | Profile URLs, usernames, or post links/shortcodes. Normalized into usernames automatically. | ["https://www.instagram.com/cristiano/", "mrbeast"] |
startUrls | No | array | Legacy alias of profileTargets for older input JSON. | [] |
postsPerProfile | No | integer (min 0, max 10000) | Posts to scrape per profile. 0 = unlimited (use with care on large profiles). Default 10. | 50 |
maxPosts | No | integer (min 0, max 10000) | Legacy alias of postsPerProfile. | 50 |
pinFilterMode | No | string enum: include, skip, only | How to treat pinned posts. include mixes pinned + regular (default); skip excludes pinned; only returns just pinned posts. | "skip" |
pinnedMode | No | string enum: include, skip, only | Legacy alias of pinFilterMode. | "include" |
publishedWithin | No | string (date picker) | Keep only posts newer than this — absolute YYYY-MM-DD or relative ("3 days", "2 weeks", "1 month"). Empty = all available posts. | "2 weeks" |
recent | No | string (date picker) | Legacy alias of publishedWithin. | "3 days" |
contentTypeFilter | No | string enum: all, photo, video, carousel | Keep only one post type, computed locally from each post's own type flags. Default "all". | "video" |
includeTaggedPosts | No | boolean | Also collect posts the profile is tagged in (Instagram's "Tagged" tab), written as type="taggedPost", isChild=true. Default false. | true |
maxTaggedPosts | No | integer (min 0, max 200) | Tagged posts to collect per profile when includeTaggedPosts is on. 0 skips tagged-post collection. Default 20. | 20 |
requestDelay | No | integer (min 0, max 30) | Base delay in seconds between paginated requests and between profiles. Default 2. | 2 |
maxRetries | No | integer (min 1, max 10) | Retries per request, per proxy tier, before escalating or giving up. Default 3. | 3 |
proxyConfiguration | No | object | Proxy configuration. Residential proxies are strongly recommended (and usually required) for reliable Instagram scraping. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
Example JSON input:
{"profileTargets": ["https://www.instagram.com/cristiano/", "mrbeast"],"postsPerProfile": 50,"pinFilterMode": "include","publishedWithin": "2 weeks","contentTypeFilter": "video","includeTaggedPosts": true,"maxTaggedPosts": 20,"requestDelay": 2,"maxRetries": 3,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
⚠️ The most common input mistake: setting pinFilterMode to "include" (the default) and expecting reliable is_pinned values. In include mode the Actor tries the faster profile-grid engine first, which cannot detect pin state, so is_pinned reads null on those rows. Set pinFilterMode to "skip" or "only" to force the accurate pin-aware engine.
⬆️ Output
Every row is typed, normalized JSON pushed to the Actor's default dataset the moment it is collected, exportable as JSON, CSV, Excel, or HTML directly from the Apify Console.
Scraped post
{"id": "3234567890123456789","pk": "3234567890123456789","shortcode": "Cxxxxxxxxxx","url": "https://www.instagram.com/p/Cxxxxxxxxxx/","post_url": "https://www.instagram.com/p/Cxxxxxxxxxx/","type": "Video","contentType": "video","isChild": false,"parentId": null,"product_type": "clips","is_video": true,"is_carousel": false,"is_pinned": false,"has_audio": true,"posted": "01 Jul 2026, 09:15:00 am","taken_at_timestamp": 1782234900,"date": "2026-07-01T09:15:00+00:00","caption": "New drop 📸 #summer #launch @brandpartner","accessibility_caption": null,"hashtags": ["summer", "launch"],"mentions": ["brandpartner"],"usertags": null,"likes_count": 48213,"comments_count": 612,"views_count": 502113,"video_duration": 14.5,"video_links": ["https://scontent.cdninstagram.com/video1.mp4"],"video_versions": [{"width": 1080, "height": 1920, "url": "https://scontent.cdninstagram.com/video1.mp4", "type": 101}],"display_url": "https://scontent.cdninstagram.com/thumb1.jpg","image_links": ["https://scontent.cdninstagram.com/thumb1.jpg"],"images": [{"url": "https://scontent.cdninstagram.com/thumb1.jpg", "width": 1080, "height": 1350}],"imageVariantsCount": 3,"videoVariantsCount": 2,"dimensions": {"width": 1080, "height": 1920},"carousel_media_count": null,"carousel_media": null,"owner": {"id": "1234567", "pk": "1234567", "username": "cristiano", "profile_pic_url": "https://scontent.cdninstagram.com/pic.jpg", "is_verified": true, "is_private": false},"user": {"pk": "1234567", "id": "1234567", "username": "cristiano", "full_name": "Cristiano Ronaldo", "is_verified": true, "is_private": false},"account_username": "cristiano","account_verified": true,"clips_metadata": {"audio_type": "original_sounds", "original_sound_info": {"original_audio_title": "Original audio"}},"audioTitle": "Original audio","audioArtist": "cristiano","isOriginalAudio": true,"comments": [{"id": "17999", "text": "Great post!", "user": {"username": "fan_account", "is_verified": false}, "comment_like_count": 4}],"latest_comments": [{"id": "17999", "text": "Great post!", "user": {"username": "fan_account", "is_verified": false}, "comment_like_count": 4}],"scrapedAt": "2026-07-30T12:00:00Z"}
Scraped tagged post
{"id": "3239876543210987654","pk": "3239876543210987654","shortcode": "Cyyyyyyyyyy","url": "https://www.instagram.com/p/Cyyyyyyyyyy/","type": "taggedPost","isChild": true,"parentId": "cristiano","mediaType": "Image","isMentionedInCaption": true,"caption": "Great night with @cristiano","likesCount": 9021,"commentsCount": 84,"viewCount": null,"images": [{"url": "https://scontent.cdninstagram.com/tagged1.jpg", "width": 1080, "height": 1080}],"carouselMediaCount": null,"ownerUsername": "some_other_account","ownerId": "9988776","postedByTaggedProfile": false,"scrapedAt": "2026-07-30T12:00:05Z"}
The id, shortcode, caption, hashtags, mentions, usertags, video_links, video_versions, image_links, images, dimensions, carousel_media, carousel_media_count, coauthor_producers, owner, user, account_username, account_verified, account_profile_picture, from_url, crawled_at, and scraped_at fields are also written on every post row alongside the fields shown above; the example is trimmed to the fields that vary most between posts. pk is present on rows collected through the pin-aware pagination engine (used whenever pinFilterMode is skip or only, or as the automatic fallback when the fast profile-grid path returns nothing); on the fast-path engine that field is simply absent from the row rather than set to null. Post-level comments and latest_comments are populated from a fixed internal cap of 10 preview comments per post — this is not exposed as an input parameter.
How does Instagram Profile Post Scraper: Media Details & Tagged Posts compare to other Instagram scrapers?
| Feature | This Actor | Generic Instagram scraper |
|---|---|---|
| Media variants | Full image and video size-variant arrays, no truncation | ✅ / ❌ varies — many expose only a single thumbnail or a top-N sample |
| Tagged-post feed | Returned as its own labeled child rows (type="taggedPost") | ❌ Not commonly offered as a separate labeled dataset section |
| Content-type filter | Built-in contentTypeFilter (photo/video/carousel), computed locally | ❌ Often requires post-processing after export |
| Pin-aware filtering | pinFilterMode switches to a pin-accurate engine for skip/only | ⚠️ Varies — pin detection is not universal |
| Output format | Typed, normalized JSON per row, streamed live to the dataset | Varies by tool |
If you're building an AI agent or RAG pipeline, the output format row is the decision-maker — parsing HTML inside an agent loop is a reliability failure mode, not a feature.
How many results can you scrape with this Instagram scraper?
postsPerProfile accepts up to 10,000 with 0 meaning unlimited, but the paginated collection engine caps itself at 100 pages per profile (roughly 12 posts per page), so a single profile's yield is bounded by that page cap even when a higher postsPerProfile is requested. Pagination stops earlier if Instagram reports no more results, if three consecutive page requests fail, or if a publishedWithin cutoff is set and a page returns no posts newer than the cutoff. maxTaggedPosts is capped at 200 per profile by the input schema itself. There is no cross-profile cap — the Actor processes every entry in profileTargets in sequence.
Integrate Instagram Profile Post Scraper: Media Details & Tagged Posts and automate your workflow
This Actor works with any language or tool that can send an HTTP request, through the Apify API.
REST API integration
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_API_TOKEN>")run_input = {"profileTargets": ["https://www.instagram.com/cristiano/"],"postsPerProfile": 50,"includeTaggedPosts": True,"maxTaggedPosts": 20,}run = client.actor("API-Empire/instagram-profile-post-scraper-media-details-and-tagged-posts").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["type"], item.get("caption") or item.get("ownerUsername"))
Works in Python, Node.js, Go, Ruby, cURL.
Automation platforms (n8n, Make, LangChain)
In n8n or Make, use the Apify HTTP node (or Apify's own integration node) to start a run with your JSON input and read back the dataset items node — no custom scraping code is needed in the workflow. In LangChain or a similar agent framework, wrap the Apify API call as a tool: the agent supplies profileTargets, the tool starts the run and returns the dataset rows as structured input for the next step.
⚖️ Is it legal to scrape Instagram?
Scraping publicly available data is generally lawful in many jurisdictions, but what you do with personal data afterward is regulated. This Actor returns only publicly available Instagram posts, tagged-post activity, and profile fields — it does not access private accounts or login-gated content. Because post rows contain personal data (usernames, full names, profile pictures, comment text tied to individual accounts), GDPR and CCPA (and similar regimes) govern how you store, process, and reuse it once collected — not whether the initial collection of public data is possible. Consult legal counsel for commercial use cases involving bulk personal data.
❓ Frequently asked questions
Does this Instagram scraper work without an Instagram account?
Yes. No Instagram login or API key is required — the Actor requests public profile and post pages over Apify Proxy. Only a proxy configuration is needed, and residential proxies are strongly recommended for reliable results.
How often is the scraped data updated?
Every run performs a live fetch against Instagram at the moment it runs — there is no cache. Re-run the Actor (or schedule it) to get current data.
What happens if a profile is empty, private, or has no matching posts?
If no posts are found, the run logs that the account may be private, unreachable, or that every post was filtered out by contentTypeFilter, and moves on to the next profile in profileTargets — the run does not fail outright for one bad target. An empty result for a single profile means check that the username is correct, the account is public, and your filters (contentTypeFilter, publishedWithin, pinFilterMode) aren't excluding everything.
Can I scrape private Instagram accounts with this Actor?
No. Only publicly accessible profiles and posts are returned. Private accounts return no data because the Actor does not authenticate as a logged-in user.
Is there a free trial or a fixed price per run?
Pricing is pay-per-event: you are charged per row_result — one charge per post or tagged-post row actually written to the dataset. Check the Actor's pricing tab on its Apify Store page for the current per-event price.
Does this Actor work for AI agent workflows and LLM pipelines?
Yes — it is callable as an HTTP endpoint by any agent framework through the Apify API. Every response is typed JSON with stable field names, so it can be passed directly to an LLM context window or indexed into a vector store without a parsing step.
How does this Actor handle Instagram's anti-bot system?
It rotates user agents per request, uses Apify residential proxies (recommended and, per the input schema, usually required for reliable results), and retries failed requests with escalating delay before giving up, up to maxRetries attempts per proxy tier. Instagram's web_profile_info endpoint is known to return HTTP 429 for a large share of automated traffic, which is why the Actor resolves a profile's numeric ID from the already-fetched page HTML first and only calls that endpoint as a fallback.
How does this Actor compare to other Instagram scrapers?
It exposes the full image/video size-variant ladder instead of a top-N sample, flattens audio/music metadata into first-class columns, and returns the profile's Tagged-tab feed as its own labeled rows — capabilities not all general-purpose Instagram scrapers separate out the same way. Evaluate any specific alternative against your own required fields before switching.
Does this Actor return data in a format LLMs can use directly?
Yes. Typed, normalized JSON with stable field names — no HTML, no selectors, no parsing. Pass it directly to an LLM context window, index it into a vector store, or route it through an agent tool.
Can I use this Actor without managing proxies?
Yes. Proxy selection defaults to Apify's residential proxy group in the input schema, and the Actor handles proxy rotation and retry/escalation internally — you only choose the proxy group, not individual IPs.
What happens when Instagram changes its structure or blocks the scraper?
The scraper is maintained, and the output schema — field names and types — stays stable on your end even as the underlying extraction logic is updated internally.
💬 Your feedback
Found a bug or missing a field? We want to know. Reach out through the Actor's page on the Apify Store (Issues tab) or the API-Empire publisher's support contact listed there, so it can be fixed for everyone using this Actor.