Blog/Developer Tools/

Instagram Profile Research API Tutorial | SandBase

Build an Instagram profile-research workflow: read a public profile, pull recent posts, and page the feed — one SandBase key, no Instagram login, no SDK.

Dark cinematic render of an Instagram profile resolving into a grid of recent posts, feeding an agent core

If you research creators or brands on Instagram, you want a repeatable loop: read a public profile for the headline signals, pull recent posts, and page the feed to see how engagement trends. This Instagram Profile Research API tutorial wires that loop with two SandBase endpoints so an agent can run it end to end. It builds on the Instagram public data API hub; read that first for the big picture.

Everything here is public, read-only data. There is no Instagram login and no SDK — a SandBase API key is still required to authenticate. The endpoint API reference is the source of truth for parameters and the response envelope. The reference guarantees only that envelope; the payload field names below come from calls I ran (tested on 2026-09-28, UTC) and are illustrative, observed-only — not documented guarantees — so confirm them against a live response.

Key takeaway

  • Two endpoints form the loop: user-profile (headline signals) → user-posts (recent feed).
  • Each call is POST /v1/api/instagram/v3/<path> with a username, one SANDBASE_API_KEY.
  • Page the feed with the returned next_max_id. Public, read-only data only.
  • Read fields defensively — the envelope is guaranteed, business fields are observed-only.

SandBase vs. the official Instagram API

Your needUse
Public, read-only profiles and postsSandBase Instagram public-data API
Post, act as an account, or use the Graph APIInstagram’s official platform
Private or account-only dataNeither public workflow

The workflow at a glance

  1. Read the profile with instagram/v3/user-profile using a username.
  2. Pull recent posts with instagram/v3/user-posts using the same username, paging with next_max_id.

Each endpoint returns the shared envelope — an id, a status, the model, and the payload on a completed run under outputs[0].data.

SandBase Instagram API page with the endpoints used in this workflow The Instagram endpoints on SandBase — user-profile and user-posts drive this loop.

Step 0: one helper for every call

import os
import requests

API = "https://api.sandbase.ai/v1/api"
HEADERS = {
    "Authorization": f"Bearer {os.environ['SANDBASE_API_KEY']}",
    "Content-Type": "application/json",
}

def call(path: str, payload: dict) -> dict:
    resp = requests.post(f"{API}/{path}", headers=HEADERS, json=payload, timeout=60)
    resp.raise_for_status()
    body = resp.json()
    if body.get("status") != "completed":
        raise RuntimeError(body.get("error", {}).get("message", f"{path} did not complete"))
    # Envelope can vary: prefer a top-level `output`, else `outputs[0].data`.
    output = body.get("output")
    if output is None and body.get("outputs"):
        output = body["outputs"][0].get("data", {})
    return output or {}

Step 1: read the profile

profile = call("instagram/v3/user-profile", {"username": "nasa"})
print(profile.get("full_name"), "|", profile.get("follower_count"), "followers")
print("bio:", profile.get("biography"))

In the response I captured (user-profile run id c52039c0-5a64-4b87-93c2-1b7a6995c23d, tested on 2026-09-28, UTC), the payload carried full_name, biography, category, follower_count, following_count, media_count, and is_verified — illustrative, observed-only fields. Read each with .get() and confirm against a live response.

SandBase API reference for the Instagram user-profile endpoint The user-profile reference — the source of truth for the username parameter and response path.

Step 2: pull recent posts

feed = call("instagram/v3/user-posts", {"username": "nasa"})
posts = feed.get("items", []) or feed.get("data", [])
next_max_id = feed.get("next_max_id")
for p in posts[:5]:
    print(p.get("like_count"), "likes,", p.get("comment_count"), "comments -", p.get("shortcode"))

In my run (user-posts run id 4e058e6d-1e9e-4dd1-8f08-412258df9a7a), the payload carried items (each with caption_text, like_count, comment_count, view_count, is_video, shortcode, and taken_at), a count, and a next_max_id for paging. To page, resend user-posts with the returned next_max_id — confirm the exact parameter name against the reference.

SandBase API reference for the Instagram user-posts endpoint The user-posts reference — pass a username; page with the returned next_max_id.

Putting it together

def research(username: str):
    profile = call("instagram/v3/user-profile", {"username": username})
    feed = call("instagram/v3/user-posts", {"username": username})
    posts = feed.get("items", []) or feed.get("data", [])
    engagement = [
        {"shortcode": p.get("shortcode"), "likes": p.get("like_count"), "comments": p.get("comment_count")}
        for p in posts if isinstance(p, dict)
    ]
    return {
        "followers": profile.get("follower_count"),
        "media_count": profile.get("media_count"),
        "recent": engagement,
    }

Because both endpoints share the same envelope and the same username, the loop stays flat: one status check in call(...) and one .get() pattern across profile and posts.

Common use cases

Creator vetting

Read a creator’s profile for follower count and category, then pull recent posts to gauge real engagement (likes and comments) rather than follower count alone. Input: a username. Output: profile signals plus a recent-post engagement sample. Endpoints: user-profile, user-posts.

Competitor content tracking

Poll a competitor’s user-posts on a schedule and diff by shortcode to catch new posts and track their engagement over time. Input: a username. Output: successive post pages. Endpoint: user-posts.

Audience and niche research

Compare several profiles’ category, follower_count, and posting cadence to map who leads a niche. Input: a set of usernames. Output: comparable profile signals. Endpoint: user-profile.

Engagement-rate estimation

Combine the two endpoints to approximate an engagement rate: pull recent posts, average their like_count and comment_count, and divide by the profile’s follower_count. This gives a rough, comparable signal across creators that follower count alone hides — a small account with high engagement can outperform a large one. Read every field defensively and treat the result as an estimate, since observed fields and post samples vary. Input: a username. Output: an engagement-rate estimate. Endpoints: user-profile, user-posts.

Practical notes

  • Envelope can vary. The reference documents outputs[0].data; read either shape (prefer output, fall back to outputs[0].data).
  • Page with next_max_id. Resend user-posts with the returned value while more posts exist.
  • Business fields are observed-only. Treat follower_count, like_count, caption_text, and the like as observed and confirm live.
  • Public, read-only data only. No posting, no private/account-only data. Authenticate with a SandBase API key.
  • Be a good client. Retry with backoff on transient errors such as HTTP 429; page rather than hammering.

FAQ

Do I need an Instagram/Facebook developer app or login? No. You authenticate to SandBase with your SANDBASE_API_KEY. These read endpoints need no Instagram account or OAuth on your side.

What identifies a profile? A username. Both user-profile and user-posts take the same username.

How do I page through more posts? The user-posts payload carries a next_max_id; resend user-posts with it. Confirm the exact parameter against the reference.

Can I read private accounts? No. The API returns public data only. Private and account-authorized content are out of scope.

Wrap up

Two endpoints, one envelope, one username — that is the whole profile-research loop. For the full endpoint catalog, see the Instagram public data API hub. When you are ready: