Back to Blog
General

Instagram Posts Scraper API: Pull Any Profile's Posts in 2026

June 18, 2026
4 min read
S
By SociaVault Team
instagramposts scraperapicontent analysis

Instagram Posts Scraper API: Pull Any Profile's Posts in 2026

If you've tried to get another account's posts out of Instagram's official Graph API, you already know it's a no-go: Graph API only hands you your own posts, after a Business account link and app review. For competitor analysis, influencer vetting, or content research, that's a wall.

This endpoint is the way around it. Give it a public handle, get that profile's posts back as JSON, with captions, likes, comments, views, and media URLs. No OAuth, no review queue.

A quick honesty check before you build: this works on public profiles only (private accounts are off-limits, by design), and if you want stories you'll want the highlights endpoint instead. If those fit, here's everything you can pull.

What you get per post

FieldWhat it is
pk / idUnique post ID
codeShortcode for the URL (instagram.com/p/{code})
caption.textFull caption
like_countLikes
comment_countComments
play_countViews (video/reel posts)
media_type1 = photo, 2 = video, 8 = carousel
video_versionsVideo URLs at various qualities
image_versions2Image URLs at various sizes
taken_atUnix timestamp
usertagsTagged users

One thing worth knowing in 2026: Instagram removed view counts from the single Post/Reel Info endpoint. This posts endpoint is now the reliable place to get a reel's play_count, so if you were leaning on post-info for views, switch your lookups here.

The call

const res = await fetch(
  "https://api.sociavault.com/v1/scrape/instagram/posts?handle=opi",
  { headers: { "x-api-key": process.env.SOCIAVAULT_API_KEY } },
);
const result = await res.json();
const posts = Object.values(result.data.items);

Add trim=true if you want a lighter response without the embedded media CDN payloads.

{
  "success": true,
  "data": {
    "more_available": true,
    "next_max_id": "3822431353875645727_270598518",
    "items": {
      "0": {
        "code": "DUTZgACiaFr",
        "media_type": 2,
        "caption": { "text": "The next generation of icons has arrived. 馃拝" },
        "like_count": 2531,
        "comment_count": 62,
        "play_count": 100404,
        "taken_at": 1770137534
      }
    }
  },
  "credits_used": 1,
  "endpoint": "instagram/posts"
}

Note the items object uses numeric string keys, not an array, so Object.values(result.data.items) is your friend.

What people actually build with it

Competitor content audits. Pull a rival's last few dozen posts, average the engagement, and surface the top performers, the single most common request we see:

const posts = Object.values((await getPosts("competitor")).data.items);
const avgLikes = posts.reduce((s, p) => s + p.like_count, 0) / posts.length;
const top = [...posts].sort((a, b) => b.like_count - a.like_count).slice(0, 10);
console.log(
  "Avg likes:",
  Math.round(avgLikes),
  "Top posts:",
  top.map((p) => p.code),
);

Posting-time analysis. Bucket taken_at by hour to find when an account actually posts:

const byHour = {};
posts.forEach((p) => {
  const h = new Date(p.taken_at * 1000).getHours();
  byHour[h] = (byHour[h] || 0) + 1;
});

Content-mix breakdown. Photos vs videos vs carousels, straight from media_type:

const TYPES = { 1: "photo", 2: "video", 8: "carousel" };
const mix = posts.reduce((a, p) => {
  const t = TYPES[p.media_type] || "other";
  a[t] = (a[t] || 0) + 1;
  return a;
}, {});

Influencer vetting. Engagement rate from real posts beats a follower count every time. Pull the last 30 posts, compute likes-plus-comments over followers, and you have a defensible number to judge a creator on.

Getting a full post history

Each call returns ~12 posts. Page with next_max_id:

async function getAllPosts(handle) {
  let all = [],
    nextMaxId = null;
  do {
    const url = new URL("https://api.sociavault.com/v1/scrape/instagram/posts");
    url.searchParams.set("handle", handle);
    if (nextMaxId) url.searchParams.set("next_max_id", nextMaxId);
    const result = await (
      await fetch(url, {
        headers: { "x-api-key": process.env.SOCIAVAULT_API_KEY },
      })
    ).json();
    all.push(...Object.values(result.data.items));
    nextMaxId = result.data.more_available ? result.data.next_max_id : null;
  } while (nextMaxId);
  return all;
}

Each page costs 1 credit, so deep histories on big accounts add up, cache what you pull.

FAQ

Private accounts? No. Public only. Do I get the actual files? You get URLs to the media; download them if you need the bytes. How far back? A profile's full public history. Stories? Not here, those are ephemeral. Use highlights for saved story content.

Start pulling posts

Create an account for 50 free credits (no card), grab your sk_live_... key, and run the snippet above. Full reference in the Instagram Posts API docs.


Related: Instagram Profile ScraperInstagram Reels APIPost/Reel InfoScrape Instagram comments

Found this helpful?

Share it with others who might benefit

Ready to Try SociaVault?

Start extracting social media data with our powerful API. No credit card required.