Instagram Public Data API

Read public Instagram posts and comments without logging in

The Instagram API returns public Instagram data — profiles, posts, reels and hashtags — as clean JSON.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a Instagram Public Data endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
I
/instagram/v1

10 active endpoints. Every call is 1 credit.

  • POST/instagram/v1/profile
  • POST/instagram/v1/posts
  • POST/instagram/v1/reels
  • POST/instagram/v1/similar_accounts
  • POST/instagram/v1/search
  • POST/instagram/v1/users_search
  • POST/instagram/v1/hashtag_search
  • +3 more

What Instagram Public Data endpoints does ReefAPI ship?

10 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

10 endpoints

profile

1 cr

public profile facts and first-page recent posts.

required
username
optional

posts

1 cr

public profile grid posts, newest first, with max_id pagination.

required
username
optional
limit, max_id, cursor, rich

reels

1 cr

public profile reels tab, newest first, with max_id pagination.

required
username
optional
limit, max_id, cursor

similar_accounts

1 cr

public related profiles from web_profile_info.

required
username
optional
limit

search

1 cr

topsearch blended public users, hashtags, and places.

required
query
optional

users_search

1 cr

public user lookup by handle (exact / near-exact match).

required
query
optional

hashtag_search

1 cr

topsearch public hashtags only.

required
query
optional

post_info

1 cr

maximally-complete public post/reel detail by shortcode (URL) or media_id.

required
optional
shortcode, media_id

post_comments

1 cr

public comments for a post/reel by shortcode (URL) or media_id, with CURSOR pagination.

required
optional
shortcode, media_id, limit, cursor

audio_media

1 cr

public reels feed that use a given audio/music track, with pagination.

required
audio_id
optional
limit, max_id, cursor

Every parameter, every allowed value →

Instagram Public Data API

3 of 10 endpoints, ready to run

View docs ↗

The public facts about an account: the bio with its links parsed out, follower and following counts, the verified, private and business flags, category and external site.

1 credit1 required · 0 optional
POST/instagram/v1/profile
ok1676 ms · 1 records · sample
{
  "ok": true,
  "meta": {
    "api": "instagram",
    "endpoint": "profile",
    "mode": "live",
    "latency_ms": 1675.8,
    "record_count": 1,
    "cache_hit": false
  },
  "data": {
    "biography": "Making the seemingly impossible, possible. ✨",
    "bio_links": [
      {
        "title": "NASA.gov Homepage",
        "url": "https://www.nasa.gov",
        "link_type": "external"
      },
      {
        "title": "Nancy Grace Roman Space Telescope",
        "url": "https://science.nasa.gov/mission/roman-space-telescope/",
        "link_type": "external"
      },
      {
        "title": "NASA Internships",
        "url": "http://intern.nasa.gov",
        "link_type": "external"
      }
    ],
    "pronouns": [],
    "follower_count": 104440596,
    "following_count": 91,
    "is_verified": true,
    "is_private": false,
    "is_business": false,
    "bio_mentions": [],
    "bio_hashtags": [],
    "external_url": "https://www.nasa.gov",
    "is_regulated_c18": false,
    "recent_posts": [],
    "timeline_page_info": {}
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Instagram Public Data API works

Instagram Public Data is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /instagram/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

A post URL is the only identifier you need

Everything on this page keys off something you already hold — a handle, or the code out of a post URL. There is no id to look up first and nothing to authenticate.

01post_info
POST/instagram/v1/post_info
{"shortcode": "DZz4bjIjhdm"}

Caption, media type, the carousel's items and taken_at, in under two seconds, from the code in the post's own URL.

02post_comments
POST/instagram/v1/post_comments
{"shortcode": "DZz4bjIjhdm", "limit": 30}

Thirty comments back, with comment_count 3,671 in the same response so you know the size of the job, and a next_cursor to continue.

03post_comments
POST/instagram/v1/post_comments
{"shortcode": "...", "cursor": "<next_cursor>"}

Repeat while has_more is true. Short calls, no timeout to fight, and the cursor is the whole pagination story.

The post and its conversation, from a URL somebody pasted into your product, with no Instagram account of yours anywhere near it.

request
curl -X POST https://api.reefapi.com/instagram/v1/profile \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"username":"nike"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "instagram",
    "endpoint": "profile",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Every id form Instagram uses, and which one each action will accept

Instagram identifies the same post three different ways and the same account two different ways, and the values are not interchangeable. This table is the mapping, taken from measured responses on @nasa and @natgeo. The row that costs people the most time is the third: post_info returns a media_id it will not accept back.

IdFormatWhere it comes from and what takes it
shortcode11 characters, mixed case, e.g. DcOX3hWFieyThe code in instagram.com/p/<code>/ or /reel/<code>/. Accepted by post_info and post_comments, and a full post URL works too.
media_id (bare)19-digit numeric string, e.g. 3967213292204992434Returned by profile, posts and reels. Accepted by post_info and post_comments.
media_id (from post_info)The same number with a POLARIS_ prefix, e.g. POLARIS_3967213292204992434post_info returns this form. It is not accepted as input: a measured call with the prefixed value came back MISSING_PARAM. Strip POLARIS_ before sending it back.
user_idNumeric string, no fixed length528817151 for @nasa, 787132 for @natgeo, 25025320 for @instagram. Accepted wherever an id-based lookup is offered.
fbid17 digits, starting 178417841401474538262 for @nasa. Returned only by profile. It is a second account identifier, not a substitute for user_id.
comment_id17 digits17914942803450269, returned by post_comments.
hashtag id17 digits17843701351037088 for #nasa, returned by hashtag_search and search alongside media_count 10088759.
audio_idNumeric stringRead it from post_info as post.music.audio_id and feed it to audio_media.

Instagram never hands you a shortcode for a carousel slide. carousel_media[] entries carry their own media_id, media_type, display_url and dimensions, but no shortcode of their own, because the shortcode belongs to the album as a whole.

What answered, what did not, and what an account of yours would buy you (nothing)

Measured on 2026-08-28 across several large accounts and one post carrying 3,671 comments. Two of these lines go against us, and they are the two to read first.

No Instagram account of yours, and no app review

You send a ReefAPI key and a handle or a shortcode. There is no Instagram login of yours, no session cookie of yours, no Graph API application to register and no app review to pass — so there is no account of yours that can be flagged, rate-limited or disabled for reading public content. Your own key's quota is the only ceiling, and a blocked or failed call is not charged.

The profile facts arrive whole

For each account we pulled: handle, full name, biography, the bio links parsed into title, url and type, follower and following counts, the verified, private and business flags, category, external site, and the @mentions and #hashtags found inside the bio. One to four seconds.

Comments go as deep as the thread does

The post we opened reports comment_count 3,671. One call returned thirty with next_cursor and has_more true, and the response also reports how many upstream pages it walked to get them. Comment text was filled on 28 of 30 rows; the two blanks are emoji-only comments, which is what the source stores for them. Every comment carries its own created_at as a unix timestamp.

🔴 The profile-timeline listings did not answer on the day we measured

Against us, and the reason this page is built on post URLs rather than on a profile walk. The posts and reels actions returned TARGET_BLOCKED on six and four separate attempts, spread across two hours and three different large accounts — and the recent_posts array inside profile, which reads the same surface, came back empty for all of them. In those same runs post detail, comments, profile facts, hashtag lookup and related accounts all answered normally, and none of the blocked calls was charged. Read that alongside the id and field reference further down this page, which describes what those two actions return and is accurate: it was measured while they were answering. Availability is a live number rather than a written one, so check /status for this engine before you commit to a pipeline that walks a profile timeline, and key off post URLs you already hold if you would rather not depend on it.

🔴 Fuzzy people-search falls back to an exact handle

Against us. Both search and users_search reported topsearch_status blocked_public_fallback and method_note exact_profile_fallback, and each returned exactly one user: the account whose handle matched the query. The hashtag half of the same response was healthy — 55 tags with counts. Treat users_search as a handle resolver, not as discovery.

Hashtag volumes are real numbers

A hashtag lookup for one word returned 55 tags, each with a media_count and a formatted count, the largest of them at 10,090,758 posts. That is the surface for sizing a topic, and it answered in 1.5 seconds.

Related accounts come back for any public profile

Twenty related profiles for one account in 4.3 seconds, each with the handle, the name and the verified and private flags. It is the source's own adjacency, not our guess at one.

What comes back, and what does not

Public content only: public profiles, public posts and reels, public comments, public hashtag counts, public related accounts. Not private accounts, not direct messages, not follower or following lists, not stories. A comment is written by a private individual and we return it as the source shows it, without adding anything to it.

What people build with Instagram Public Data

The jobs this data is most often used for.

10

endpoints

1

credit per call

01

Creator and influencer platforms call profile to pull follower counts, verification and bio for any public account.

02

Brand-monitoring tools use hashtag_search and posts to track a campaign's reach and engagement.

03

Social-analytics products use reels and post_comments to measure content performance and audience sentiment.

What Instagram Public Data data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/instagram/v1/profile \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"username":"nike"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/instagram/v1/profile",
    headers={"x-api-key": REEF_KEY},
    json={
  "username": "nike"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Instagram Public Data.

Get a free key →
I passed the media_id that post_info gave me straight back and got MISSING_PARAM. Why?

post_info reports media_id with a POLARIS_ prefix, and the parameter only takes the bare number. A measured call with media_id "POLARIS_3967213292204992434" returned MISSING_PARAM ("missing: shortcode or media_id") in 32 ms, while the same call with "3967213292204992434" returned the post. The bare form is what profile, posts and reels give you, so round-tripping from those needs no handling. Store the shortcode if you want one key that works everywhere.

media_type is a word in one action and a number in another. Which is which?

posts, reels and profile.recent_posts return media_type as a string, and the measured values were "image", "video" and "carousel". post_info returns Instagram's own numeric enum instead: 1 for an image, 2 for a video, 8 for a carousel, all three confirmed on live posts. post_info also adds product_type, which is finer grained: "feed" for a normal image, "clips" for a reel, "carousel_container" for an album. Normalize at your boundary if you key on type.

How does a carousel (album) post come back?

As one post with carousel_media[] attached. A measured @natgeo album returned media_type 8, product_type "carousel_container" and five entries in carousel_media[], each with its own media_id, media_type, display_url and dimensions, and no shortcode. The album's own display_url is the first slide, so a feed that reads only display_url shows the cover and silently drops the other four. The list action flags them too: a carousel row in posts has media_type "carousel" and carries the same array.

Which fields come back null, and which are simply absent?

The distinction matters if you key on presence. Fields Instagram has no value for are usually dropped rather than nulled: video_view_count exists only on video rows (measured 480980 on one, with the key entirely missing on every image row), and tagged_users and coauthor_producers appear only when the post actually has them. category on profile came back null on all four accounts measured, @nasa and @instagram included. Write your reader to treat missing and null the same way.

What time format are the timestamps in?

Unix seconds, UTC, as integers. taken_at_timestamp on a post measured 1787148707, and created_at on a comment measured 1787782760, so the same unit under a different field name, which is worth knowing when you join posts to their comments. Nothing here is milliseconds and nothing is a formatted string, so multiply by 1000 before handing either to a JavaScript Date.

How do I page through posts and comments?

Two different cursors. For posts and reels, page_info returns next_max_id and end_cursor holding the identical base64 string, and you pass either back as max_id (cursor is accepted as an alias). For comments, next_cursor is a JSON document serialized into a string, measured as {"is_server_cursor_inverse":true,"server_cursor":"AQHT..."}, so pass it back verbatim as cursor without trying to parse it. Stop when has_more is false or next_cursor is null.

Does comment_count match the number of comments I can pull?

comment_count is the total on the post; returned_count is what this call handed you. A measured @nasa post reported comment_count 2994 with returned_count 5 for a limit of 5. Comments come back newest first and paging with cursor walks backwards from there. The two numbers will not converge on a busy post because new comments arrive while you page, so use comment_count as the denominator for a progress bar and not as a termination condition.

A username that does not exist returned TARGET_BLOCKED rather than NOT_FOUND. Is that a bug?

It is expected, and worth designing around. A measured call for a handle that does not exist came back TARGET_BLOCKED with retryable true rather than NOT_FOUND, because the public surface does not distinguish the two clearly enough for us to promise a difference, and telling you an account is gone when it might be a transient miss would be worse. Retry a TARGET_BLOCKED once; if one handle keeps returning it while other handles succeed in the same window, treat it as gone.

What is the Instagram Public Data API?

Instagram Public Data API is a ReefAPI endpoint group for instagram public data It returns live JSON through POST requests under /instagram/v1.

Is the Instagram Public Data API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Instagram Public Data calls use the same shared credit balance as every other ReefAPI engine.

Do I need an Instagram Public Data login or account?

No login to Instagram Public Data is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Instagram Public Data data?

The page example is captured from a live profile call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Instagram Public Data API use?

Instagram Public Data actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Instagram Public Data from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call instagram actions with the same key, credit pool and JSON envelope used by normal REST requests.

10 Social Media APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Instagram Public Data, you are one call away from the rest of the category — no second contract, no second integration.

Already paying for something else?Instagram Public Data vs Apify

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.