DEV Community

Intropix-team
Intropix-team

Posted on Edited on AI-assisted

Instagram scraper API without login: posts and reels with music, shares, location and business contacts (Python)

The Instagram Basic Display API was shut down on 04-12-2024. What is left on the official side is the Graph API, which is built around accounts you manage: your own professional account, a Meta app, app review, and even then a narrow view of anyone else's content. If the job is "pull public posts and reels from a list of brand accounts into a pipeline, with everything Instagram shows on them", the official route does not get you there.

The jobs that kept coming to me were all versions of that: which brands a creator works with, which tracks brands put behind their reels, where an event brand posts from, which accounts in a list are businesses with a public contact. Each one needs more than likes and a caption. This post is the scraper I built for them.

Why not instaloader and a burner account?

You can, until the account dies. The open-source libraries are good, but a burner running against them collects checkpoint challenges within days, and anything beyond a shallow scrape wants a logged-in session. Then you are maintaining accounts instead of doing analysis.

So the session problem sits with me. The PRO Instagram Posts & Reels Scraper runs on Apify: usernames or post links in, one JSON item per post out. No Instagram login, no cookies, no OAuth, no Instagram account of your own. Full disclosure: it's mine, so factor that in.

What it returns

Every item has the same 54 keys, null (or []) when a value is absent, never a made-up zero. Basics first:

  • Media: every image and video URL with width, height and duration. A carousel is one item with its slides nested in media.
  • Post: post_pk, shortcode, permalink, post_type (photo, video, reel, carousel), taken_at, caption, hashtags, mentions.
  • Metrics: like_count, comment_count, real reel and video plays in view_count, and engagement_rate ((likes + comments) / followers, as a fraction).

Then the details:

  • Music: audio_title, audio_artist, audio_id, and is_original_audio to separate licensed tracks from the account's own sound.
  • Shares: share_count and repost_count, plus fb_play_count and fb_like_count when the post was cross-posted to Facebook.
  • Location: location_name, location_id, location_city, location_lat, location_lng, from the venue the publisher tagged.
  • Tagged accounts and partners: tagged_usernames, coauthors, and sponsor_usernames (the brand on the paid partnership label) next to is_paid_partnership.
  • Flags: is_pinned, caption_edited, has_audio, counts_hidden, is_off_grid.
  • Account profile: owner_account_type, owner_category, owner_website, owner_bio_links, owner_post_count, follower counts, and owner_public_email, owner_public_phone, owner_city, owner_address where the profile shows them publicly. Hidden contact details stay null.
  • Partner enrichment (optional): with enrichPartners on, partners holds a short profile of every co-author and sponsor brand (followers, verified badge, category, account type).

It reads public business, creator and brand accounts, including age-gated (18+) accounts in alcohol, vape, tobacco and nightlife that anonymous visitors cannot see. Private accounts are out of scope by design.

Python quickstart

pip install apify-client
Enter fullscreen mode Exit fullscreen mode
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("intropix/instagram-posts-reels-scraper-pro").call(
    run_input={"usernames": ["redbull"], "maxPosts": 10}
)

for post in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(post["taken_at"], post["post_type"], post["like_count"],
          post["share_count"], post["audio_title"], post["location_name"])
Enter fullscreen mode Exit fullscreen mode

call() blocks until the run finishes.

The input, and the one detail that catches people out

  • usernames: accounts to read, newest posts first.
  • postUrls: links to specific posts or reels. Each valid link is delivered as one post, whatever maxPosts and the filters say.
  • maxPosts: default 10. A carousel counts as one post.
  • sinceDate, untilDate: only posts on or after / on or before a date (YYYY-MM-DD, UTC).
  • mediaType: any, image or video. Filtered posts are never delivered or billed.
  • includeViews (on by default), includeOffGridReels (reels missing from the grid but public on the reels tab), enrichPartners.

maxPosts is ONE budget for the whole run, spent account by account in the order you list them. It is not a per-account allowance. Give it three usernames and maxPosts: 100, and the first account can use all 100 while the other two return nothing. For multi-account jobs, run one account per run (an Apify task or a short loop), or set a high maxPosts and let sinceDate and untilDate decide what comes back. A paid run delivers at most 1,000 posts, so larger jobs split across runs anyway.

What the output looks like

A real item, trimmed (Red Bull, 17-10-2026; URLs shortened, some fields cut):

{
  "username": "redbull",
  "follower_count": 34172188,
  "post_pk": "4009548556935342118",
  "permalink": "https://www.instagram.com/p/DekxytFz6gm/",
  "post_type": "reel",
  "taken_at": "2026-10-17T00:08:53Z",
  "like_count": 46317,
  "comment_count": 344,
  "view_count": 1588744,
  "share_count": 3450,
  "repost_count": 937,
  "engagement_rate": 0.001365,
  "audio_title": "Original audio",
  "audio_artist": "redbull",
  "audio_id": "26590578263972833",
  "is_original_audio": true,
  "coauthors": ["asavermette", "redbullbike"],
  "tagged_usernames": ["redbullbike", "asavermette"],
  "sponsor_usernames": [],
  "location_name": "Cypress Mountain",
  "location_lat": 49.39541,
  "location_lng": -123.20219,
  "owner_account_type": "business",
  "owner_website": "https://onein.bio/redbull",
  "owner_public_email": "info@redbull.com"
}
Enter fullscreen mode Exit fullscreen mode

post_pk is the dedup key. engagement_rate 0.001365 is 0.14%: accounts with tens of millions of followers often sit below 1%.

Node quickstart

const res = await fetch(
  "https://api.apify.com/v2/acts/intropix~instagram-posts-reels-scraper-pro" +
    "/run-sync-get-dataset-items",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      // Token in a header, never in the query string.
      Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
    },
    body: JSON.stringify({ usernames: ["redbull"], maxPosts: 10 }),
  }
);
const posts = await res.json();
for (const p of posts) console.log(p.post_type, p.share_count, p.audio_title);
Enter fullscreen mode Exit fullscreen mode

Node 18+ has fetch built in. Save as scrape.mjs for top-level await.

What does it cost?

Pay per event, no subscription: $0.005 per run start, $0.002 per scanned profile, $0.0039 per delivered post ($3.90 per 1,000). Every field above is in that price. Partner enrichment is the one option: $0.005 per enriched profile, charged once per profile per run. Failed lookups are never charged.

Worked example, ten brand accounts, newest 100 posts each, in one run with maxPostsPerAccount: 100: $0.005 + 10 x $0.002 + 1,000 x $0.0039 = $3.925. If the run enriches 50 partner profiles, add 50 x $0.005 = $0.25.

Free Apify accounts can test with up to 10 results per run and 40 per day, shared across my Instagram actors. Enrichment needs a paid plan.

Knowing why a run returned nothing

Every run writes an OUTPUT record to its key-value store: outcome (ok or denied), delivered, failed_targets and failed_target_reasons. Branch on that, not on the item count.

out = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")
print(out["value"]["outcome"], out["value"]["failed_target_reasons"])
Enter fullscreen mode Exit fullscreen mode

n8n, Make and AI agents

In n8n, the verified Apify node's "Run actor and get dataset" operation takes the id intropix~instagram-posts-reels-scraper-pro and the same JSON input. Make and Zapier have Apify integrations that work the same way. For scheduled jobs, let Apify own the schedule and have the workflow react to a webhook.

For an AI agent, point any MCP client at Apify's hosted MCP server, limited to this one actor:

https://mcp.apify.com?tools=intropix/instagram-posts-reels-scraper-pro
Enter fullscreen mode Exit fullscreen mode

Authenticate with your Apify account and the agent sees one tool with this input schema. Put a maxPosts ceiling in the prompt: a model asked to "get everything" will ask for a lot, and you pay per delivered post.

For coding agents there are ready-made skills: npx skills add Intropix-team/instagram-scraper-skills installs seven, from saving stories and reels to a competitor audit, brand deals and business contacts. Each one picks the right scraper, runs it in your Apify account and writes the files (repo).

Honest limits

  • Private accounts, direct messages, comment text and commenter identities are out. So are highlights and the tagged-photos tab.
  • Instagram trial reels are shown only to their author and are not returned.
  • Counts are what Instagram showed at scrape time. When the owner hides counts, counts_hidden is true and the count fields are null.
  • Location is the venue the publisher tagged, not where the camera was, and many posts have none.
  • Contact fields are only what the profile shows publicly. Many accounts show none.
  • Media URLs point at Instagram's CDN and expire; download promptly if you need the files.

This is an independent, unofficial tool. It is not affiliated with, endorsed by, or connected to Instagram or Meta Platforms, Inc.

When the base scraper is enough

I also run the standard Instagram Posts & Reels Scraper at $1.90 per 1,000 posts. It returns 24 fields: media, caption, likes, comments, views, dates, follower counts, and the paid-partnership and co-author signals. Those 24 are identical to the first 24 here, so code moves between the two unchanged. If that is the whole job, use it. As soon as shares, music, location, sponsors or account details are the point, this one is cheaper than collecting them anywhere else.

Wrap-up

Walkthroughs of my other two actors: How to scrape Instagram stories without login and How to scrape Instagram posts and engagement data without login. Runnable stories, posts and PRO examples (brand deals and business leads to CSV) are in github.com/Intropix-team/instagram-scraper-examples.

Short posts on single jobs with this actor: tracking brand deals, the music brands use in reels, business contacts for lead lists, mapping post locations and a competitor engagement audit. If you have a job that does not fit, leave a comment.

Top comments (0)