🔥 Instagram Profile Scraper avatar

🔥 Instagram Profile Scraper

Pricing

from $0.50 / 1,000 results

Go to Apify Store
🔥 Instagram Profile Scraper

🔥 Instagram Profile Scraper

Scrape Instagram profile data and profile statistics from public Instagram pages with an Apify Actor. This actor focuses on profiles (not posts) and returns a clean dataset with the essentials (identity, stats, and account flags), plus optional previews like latest_posts, etc.

Pricing

from $0.50 / 1,000 results

Rating

0.0

(0)

Developer

Instagram Scraper

Instagram Scraper

Maintained by Community

Actor stats

9

Bookmarked

1K

Total users

148

Monthly active users

1.4 hours

Issues response

a day ago

Last modified

Share

Instagram Profile Scraper

Actor Stats

Scrape Instagram profile data and profile statistics from public Instagram pages with an Apify Actor.

This actor focuses on profiles (not posts) and returns normalized profile fields (identity, stats, and account flags), plus additional raw Instagram profile metadata when available, along with optional previews like latest_posts and discovery via related_profiles.


What this actor can do

  • Scrape Instagram profile stats: followers, following, number of posts
  • Get key profile attributes: verified/private flags, profile pictures, bio, external links, and counts
  • Keep additional raw profile metadata from Instagram when available in the public payload
  • Optionally scrape a linked Facebook profile into fb_profile when scrapeFacebookProfile is enabled
  • Return latest posts as lightweight previews or opt-in detailed post data
  • Return a list of related profiles from Accounts you might like when that enrichment succeeds
  • Accept both usernames and profile URLs

Want to get other details from Instagram?

This actor is optimized for profiles (not full post feeds). If you want to scrape other Instagram data, use a dedicated scraper for that specific data type.

Related actors from the instagram-scraper:

ActorDescriptionStats
Instagram Profile FinderFind Instagram profilesInstagram Profile Finder Actor Stats
Fast Instagram Profile Posts ScraperScrape post data from Instagram profile pagesFast Instagram Profile Posts Scraper Actor Stats
Instagram Profile Posts ScraperExtract profile post details such as hashtags, counts, media, and shortcodeInstagram Profile Posts Scraper Actor Stats
Fast Instagram Profile Reels ScraperScrape public Instagram Reels from profile pagesFast Instagram Profile Reels Scraper Actor Stats
Instagram Posts & Reels ScraperScrape public Instagram posts and Reels from URLs or shortcodesInstagram Posts & Reels Scraper Actor Stats
Instagram Hashtags Posts ScraperScrape public Instagram hashtag pagesInstagram Hashtags Posts Scraper Actor Stats
Instagram Related Profiles ScraperDiscover related accounts and recursively expand profile networksInstagram Related Profiles Scraper Actor Stats

What data can I scrape from Instagram profiles?

Using this Instagram Profile API, you can extract both normalized fields and additional Instagram profile metadata (when available on the public profile):

CategoryFieldsWhat you get
Identity & IDspk, id, pk_id, username, full_name, urlBasic profile identifiers returned by Instagram, plus the canonical profile URL built by the actor.
Profile media & linksprofile_pic_url, profile_pic_url_hd, profile_pic_id, has_profile_pic, profile_pic_genai_tool_info[], biography, contact_email, bio_links[], external_url, external_url_linkshimmed, pronouns[]Profile picture fields (including HD URL mapped from hd_profile_pic_url_info), profile bio text, extracted contact email, profile links, and external website fields available on the Instagram profile. external_url_linkshimmed is passed through from Instagram's external_lynx_url when present. Each bio_links[] item may include fields such as image_url, is_pinned, link_type, lynx_url, media_accent_color_hex, media_type, title, url, and creation_source. profile_pic_genai_tool_info[] is a raw Instagram array and is often empty.
Facebook enrichmentfb_profileOptional Facebook profile lookup from one detected profile URL in external_url, bio_links, fb_profile_biolink, biography, or full_name when scrapeFacebookProfile is enabled. The nested payload includes url, status, message, bio, profile_type, profile_name, page_id, counts, and other status fields when available.
Counts & activityfollowers, following, post_count, total_clips_count, has_any_clips, mutual_followers_count, latest_reel_media, live_broadcast_visibility, live_broadcast_idHigh-level counts for analysis, monitoring, and profile summaries, plus activity hints exposed by Instagram. With skipAdditionalData: false, an available main-profile count is retained; if none is available, public profiles parse post_count from profile-page HTML og:description (for example, <meta property="og:description" content="42M Followers, 1,455 Following, 14K Posts - …">). Instagram abbreviates counts above ~10k in that tag (14K, 1.2M, and so on), so values are approximate rather than exact. post_count is null when skipAdditionalData is enabled (the default), or when the main profile has no count and the optional page is skipped or cannot provide one. has_any_clips is derived from total_clips_count when available. latest_reel_media, live_broadcast_visibility, and live_broadcast_id are raw pass-through fields and are commonly null.
Account flags & capabilitiesis_private, is_verified, show_text_post_app_badge, text_post_app_badge_label, is_active_on_text_post_app, is_unpublished, is_memorialized, is_coppa_enforced, is_regulated_c18, account_type, is_business, is_professional_account, category, should_show_category, is_embeds_disabled, is_cannes, has_story_archiveVisibility, verification, account-type, audience-safety, and account-status fields available on the Instagram profile. These fields are always emitted on found profiles, using explicit null when Instagram does not return a value (except category, which may be an empty string).
Profile context & relationship hintslinked_fb_info, profile_context_links_with_user_ids, profile_context_facepile_users, supervision_info, has_chainingExtra profile-context blocks returned by Instagram for social graph, supervision, or related-surface hints. These are pass-through fields and are often null on public profile pages.
Business & locationaddress_street, city_name, zipOptional business/contact location metadata when Instagram exposes it on the public profile. These fields are usually null for non-business accounts.
Transparency & badgesaccount_badges[], show_account_transparency_details, transparency_label, transparency_product, hide_creator_marketplace_badge, is_ring_creator, show_ring_awardTransparency, badge, and creator-surface metadata exposed by Instagram. These are stable pass-through fields when present; arrays such as account_badges[] are emitted as [] when empty.
Latest postslatest_posts[]latestPostsMode: "preview" (default) uses a fixed 17-field shape with identifiers, captions, hashtags, mentions, preview images, authors, media type, and scrape time. "detailed" includes richer media and business fields when available. See Latest posts output below.
Related profilesrelated_profiles[]Suggested accounts from the Accounts you might like enrichment: id, username, full_name, is_verified, profile_pic_url. When enabled, the actor returns the full related-profiles list Instagram exposes for that profile. On final enrichment failure, the actor emits [] and logs a warning instead of failing the whole profile.
Scrape metadatacrawled_at, ig_statusTimestamp of the scrape and a simple status indicator. ig_status is ok when profile data is returned and not_found when the profile does not exist or is restricted. Invalid input entries are listed in run logs and skipped before scraping; they do not create Dataset rows.

Notes:

  • Field availability depends on what Instagram returns for a given profile (especially for private accounts).
  • Some fields are normalized by the actor (followers, following), while other raw Instagram profile fields may still be passed through when present.
  • Raw Instagram metadata can change over time, so downstream consumers should treat optional fields as non-guaranteed.
  • When skipAdditionalData is false, post_count retains a usable main-profile value or falls back to the public profile page's og:description meta tag. Instagram abbreviates large counts (for example, 14K Posts), so HTML-derived values are approximate. Private profiles skip HTML and retain only a count already supplied by the main profile. With additional data skipped (the default), or no usable source after retries, post_count is null.
  • contact_email is extracted from biography or full_name when an email address is present on a found profile, and is null otherwise.
  • fb_profile is null when the toggle is disabled or no Facebook profile URL is found. If a Facebook lookup fails after retries, the actor returns fb_profile.status = "error" or fb_profile.status = "not_found" instead of throwing. Successful fb_profile payloads include bio instead of the older intro name.
  • Preview posts contain exactly the 17 fields documented below. Detailed posts use the expanded shape described below. Known missing scalar/object values are null; known list fields use [] when empty.
  • Additional data is skipped by default. Set skipAdditionalData: false to include available first-page posts in the selected mode and a post count; private profiles skip additional lookups.

Typical use cases

  • Influencer discovery and enrichment (profile stats, verification, public profile metadata)
  • Competitor monitoring (track follower growth over time)
  • Lead enrichment for sales/marketing (public business profiles)
  • Content research (quick look at latest post captions and preview images)

Input

Configure these fields in the Actor’s Input tab in the Apify Console:

instagramUsernames (required)

A list of Instagram usernames or profile URLs you want to scrape.

Usernames support 2–256 ASCII letters, digits, periods, or underscores, with an optional leading @. Complete profile URLs support up to 8,192 characters and may point to the profile itself or its reels or tagged tab. These are input format limits; a syntactically valid entry does not guarantee that a profile exists or is available to the scraper.

Before creating scraping tasks, the Actor validates each entry and removes duplicates without regard to capitalization. Invalid entries are skipped and listed in run logs with their original list position and rejection reason. Credential-bearing values are redacted in logs. Only valid, unique profiles enter the scraping queue and contribute to the requested-profile total. If every entry is invalid or the list is empty, the run ends without scraping or creating Dataset rows.

Examples:

  • google
  • https://www.instagram.com/google/

scrapeFacebookProfile (optional)

When enabled, the actor looks for one Facebook profile URL in this order: external_url, bio_links, fb_profile_biolink, biography, then full_name. In the current public payload model, bio_links is usually the main place where profile links are exposed.

The nested fb_profile payload includes url, status, message, bio, profile_name, page_id, followers, following, is_business_page_active, category_name, and profile_type when available.

skipAdditionalData (optional, default: true)

Controls enrichment for both latest_posts[] and post_count. Keep it enabled for faster scraping. Set it to false to include available posts in the selected latestPostsMode and the post count for public profiles. Preview mode shares a page lookup with the post count; detailed mode fetches posts separately and only needs the page lookup when the main profile has no usable count.

When enabled, latest_posts is [] and post_count is null, including when the main profile response contains a post count. This takes precedence over latestPostsMode, including "detailed". Private profiles skip additional post and page lookups. If an optional lookup fails after retries, the main profile is still saved successfully.

This option replaces skipLatestPosts and skipPostCount. Saved inputs with those removed keys are accepted and ignored; use skipAdditionalData: false to request both values.

{
"instagramUsernames": ["instagram"],
"skipAdditionalData": false
}

latestPostsMode (optional, default: "preview")

Choose how much detail to include in latest_posts. Requires skipAdditionalData: false; setting this mode alone does not enable enrichment.

ValueBehavior
"preview"Basic post previews using the fixed 17-field shape below. This is the default and preserves existing output.
"detailed"Richer post information when available, including publication times, engagement counts, video details, tagged users, music, and carousel previews. May take longer and adds a post event charge per saved post at the configured Actor price.

Both modes fetch only the first page for public profiles. Detailed mode requests 12 posts for all users; the actual number returned can differ. Neither mode paginates, pads the result, truncates the returned posts locally, or performs per-post lookups. Private profiles return latest_posts: []. Unrecognized mode values are rejected during input validation.

For backward compatibility, latestPostsV2: true selects "detailed", including when latestPostsMode is set to "preview". A false or omitted latestPostsV2 leaves latestPostsMode unchanged. This compatibility input also requires skipAdditionalData: false to enable enrichment and uses the same detailed output and post event charges.

To request detailed posts:

{
"instagramUsernames": ["instagram"],
"skipAdditionalData": false,
"latestPostsMode": "detailed"
}

The equivalent input using the compatibility option is:

{
"instagramUsernames": ["instagram"],
"skipAdditionalData": false,
"latestPostsV2": true
}

Latest posts output: preview

Post previews come from the public profile page and include only the first page available there, commonly 12 posts. The Actor keeps all valid previews without padding, local truncation, pagination, or per-post lookups. Pinned and collaborative posts can appear; the media author can differ from the profile. Missing, damaged, or unavailable previews produce latest_posts: [] without failing or retrying the main profile. Post-count retries can still occur independently, and any successfully parsed previews are retained.

Each post contains exactly these 17 fields:

FieldsCurrent output
pk, idSource identifiers and types; missing values are null
code, shortcode, urlMatching shortcodes and a canonical post or Reel URL; null if unavailable
media_type, product_typeSource media classification, or null
captionPlain text; missing text is null, an explicit empty string stays ""
hashtags, mentionsUnprefixed, deduplicated lists in order of first appearance; [] if absent
accessibility_captionSource accessibility text, or null
display_uri, imagePreview image URL, or null
is_videoBoolean indicating whether the source identifies the preview as video
userAuthor object containing id and username, or null; absent author values are null
carousel_media_countSource carousel count, or null; carousel children are not fetched
crawled_atUTC ISO 8601 scrape time shared by the batch; this is not a publication time

Previews do not include publication times, engagement counts, video URLs or durations, dimensions, music, tagged users, or carousel children. Those values are unavailable from this preview source and are not reconstructed.

Latest posts output: detailed

With latestPostsMode: "detailed", the same latest_posts[] field contains expanded post objects. This mode has a separate output shape; consumers that require exactly 17 fields should keep "preview".

FieldsDetailed output
pk, id, code, shortcode, urlSource identifiers, matching shortcode aliases, and a canonical post or Reel URL.
caption, hashtags, mentionsPlain-text caption and deduplicated, unprefixed hashtags/mentions. Empty lists use [].
taken_at_timestamp, taken_atPublication time as Unix seconds and a UTC ISO 8601 string, or null when unavailable.
like_count, comment_count, play_count, view_countAvailable engagement counts; unavailable counts remain null, and counts with different meanings are not substituted.
media_type, product_type, is_video, accessibility_captionMedia classification and accessibility text when available.
display_uri, image, image_versions2, video_url, video_versions, video_duration, dimensions, original_height, original_widthAvailable image/video sources, duration in seconds, and dimensions.
user, owner, coauthor_producers, tagged_user, locationAvailable author, collaboration, tagging, and location information. Known list fields, including tagged_user, use [] when empty.
clips_metadata, clips_music_attribution_info, music_metadataAvailable music and clip metadata. Some source-specific fields are present only when returned.
carousel_media_count, carousel_mediaReported carousel size and available child-media previews. Children can be partial; the Actor does not fetch the remaining slides.
timeline_pinned_user_ids, clips_tab_pinned_user_ids, is_paid_partnershipAvailable pinning and partnership information.
crawled_atUTC ISO 8601 scrape time shared by the batch, separate from publication time.

Additional returned business fields are preserved. Known missing scalar/object fields use null, and known missing list fields use []. Nested business objects retain their available structure. Carousel children retain source caption and timestamp types and receive media convenience fields; their shape is not identical to a root post. Media authors can differ from the requested profile for collaborative posts.

Detailed post failures are retried up to six attempts. If they remain unavailable, the Actor saves the profile with latest_posts: [] and retains any available post_count. It does not silently fall back to preview mode. Post count lookup failures likewise do not discard successful detailed posts.

Selected fields from a detailed post are shown below. Other root fields are omitted for readability; the included nested objects are shown in full.

{
"pk": null,
"id": "1",
"code": "SHORT",
"shortcode": "SHORT",
"url": "https://www.instagram.com/p/SHORT/",
"media_type": 2,
"product_type": null,
"caption": "hello #news @caption_mention",
"hashtags": [
"news"
],
"mentions": [
"caption_mention"
],
"taken_at_timestamp": 1772730134,
"taken_at": "2026-03-05T17:02:14Z",
"like_count": null,
"comment_count": null,
"play_count": null,
"view_count": null,
"image": "https://example.com/top-candidate.jpg",
"video_url": "https://example.com/top-video.mp4",
"video_duration": null,
"dimensions": {
"height": 1137,
"width": 640
},
"is_video": true,
"user": null,
"tagged_user": [
{
"pk": "10",
"full_name": "Top User",
"username": "top_user",
"profile_pic_url": "https://example.com/u.jpg",
"is_verified": true,
"id": "10",
"is_private": true,
"profile_pic_id": "pic-10"
}
],
"clips_music_attribution_info": {
"artist_name": "Sample Artist",
"song_name": "Sample Song",
"uses_original_audio": false,
"should_mute_audio": false,
"should_mute_audio_reason": null,
"audio_id": "audio-1"
},
"carousel_media_count": null,
"crawled_at": "2026-09-27T00:00:00Z"
}

Detailed post billing

On pay-per-event runs, latestPostsMode: "detailed" adds a post charge for each post saved in latest_posts[], in addition to existing profile and optional Facebook charges. Preview mode does not trigger this event. The Actor uses the event price configured on Apify; it does not accept or hardcode a separate price.

After each successful batch save, the Actor sums the lengths of latest_posts for the profiles confirmed saved and submits one post charge for that total. The account-wide post_count is not used. Carousel children do not count as additional posts. Empty post lists, skipped enrichment, and failed Dataset writes do not trigger a post charge. If only part of the batch is saved, only those saved profiles contribute to the charge.

A Post billing estimate log lists the saved profiles, their post counts, the total, the event count reported as charged by the SDK, and an estimated cost in USD. unitPriceUsd is the runtime event price used for this estimate. Counts are integers; USD values are decimal strings. Refer to the Actor's pricing and your Apify billing records for actual charges. For illustration only, a runtime price of $0.001 per post would produce this estimate for 22 posts:

{
"eventName": "post",
"status": "charged",
"profileCount": 2,
"totalPostCount": 22,
"chargedPostCount": 22,
"unchargedPostCount": 0,
"unitPriceUsd": "0.001",
"estimatedCostUsd": "0.022",
"billingNote": "Estimated cost only. Refer to the Actor's pricing and your Apify billing records for actual charges.",
"eventChargeLimitReached": false,
"profiles": [
{ "username": "username1", "postCount": 12 },
{ "username": "username2", "postCount": 10 }
]
}

profiles[].postCount describes saved posts. If the budget permits only a partial charge, chargedPostCount reflects the SDK-reported count and estimatedCostUsd is calculated from that count and the runtime unit price. unchargedPostCount shows the difference. The Actor stops further work when the post charge limit is reached. Already saved profiles remain available and are not charged again when the run resumes.

If the post event is not configured, the log says not_configured and reports zero charged posts and zero estimated post cost. Non-pay-per-event runs report not_pay_per_event; empty batches of posts report empty. If the charge outcome cannot be confirmed, the log says unconfirmed and uses null for the charged count and estimated cost. These estimates cover only the post event, not the total run cost. The Actor retains the saved profiles and does not automatically retry an uncertain charge or backfill charges for profiles already found in the Dataset during recovery.

skipRelatedProfiles (optional, default: true)

If related_profiles is not required for your use case, keeping this enabled helps speed up scraping.

When disabled, the actor returns the full related_profiles list Instagram exposes.

Quick start (Apify Console)

  1. Add one or more values to instagramUsernames (either usernames like nypost or URLs like https://www.instagram.com/google/).
  2. Adjust retries only if you hit temporary errors.
  3. Click Run → open the Dataset tab to view/export results (JSON, CSV, Excel, etc.).

Invalid usernames and malformed profile URLs are listed in run logs with a rejection reason and skipped before tasks are created. They do not create Dataset rows.

This makes the actor usable as an Instagram profile scraping API, because datasets can be consumed programmatically via Apify’s API.


Example input

{
"instagramUsernames": ["kevinhart4real"],
"scrapeFacebookProfile": true,
"skipAdditionalData": false,
"skipRelatedProfiles": false
}

Example output

{
"pk": "123",
"username": "sampleprofile",
"full_name": "Sample Profile",
"is_private": false,
"is_verified": false,
"is_business": false,
"requested_by_viewer": false,
"business_email": null,
"profile_pic_url": "https://example.com/profile.jpg",
"profile_pic_url_hd": "https://example.com/profile-hd.jpg",
"biography": "Sample profile",
"external_url": "https://example.com/",
"bio_links": [],
"post_count": 42,
"id": "123",
"url": "https://www.instagram.com/sampleprofile/",
"contact_email": null,
"followers": 321,
"following": 12,
"latest_posts": [
{
"pk": "media-0",
"id": "opaque-media-0",
"code": "SHORT0",
"shortcode": "SHORT0",
"url": "https://www.instagram.com/p/SHORT0/",
"media_type": 8,
"product_type": "carousel_container",
"caption": "Example post 0 #sample @collaborator",
"hashtags": [
"sample"
],
"mentions": [
"collaborator"
],
"accessibility_caption": "Example preview",
"display_uri": "https://example.com/preview-0.jpg",
"image": "https://example.com/preview-0.jpg",
"is_video": false,
"user": {
"id": "author-0",
"username": "sampleprofile"
},
"carousel_media_count": 7,
"crawled_at": "2026-10-31T00:00:00Z"
}
],
"related_profiles": [],
"fb_profile": null,
"ig_status": "ok",
"crawled_at": "2026-10-31T00:00:00Z",
"is_professional_account": null,
"category": null,
"should_show_category": null
}

Example dataset item when a profile is not found:

{
"username": "11",
"ig_status": "not_found",
"message": "Profile not found or restricted",
"url": "https://www.instagram.com/11/",
"crawled_at": "2026-02-06T08:03:20.522Z"
}

Here, ig_status: "not_found" means Instagram did not return profile data for that username because the profile does not exist or access to it is restricted.


Tips & troubleshooting

Don’t overload the actor. If you need to scrape large lists, split inputs into batches.


You are responsible for ensuring your use of this actor complies with:

  • Instagram’s Terms of Service
  • Applicable laws and regulations (privacy, data protection, etc.)

Only scrape data you have the right to access, and avoid collecting personal data without a lawful basis.