At a glance
Status, checked 2026-09-18: the Basic Display API has failed every request since 2024-12-04. The Instagram API with Instagram Login replaces it for Business and Creator accounts; personal accounts get no feed API.
- Use it when
- a feed, plugin or script stopped showing Instagram posts after December 2024, or inherited code still requests
user_profile,user_media. - Do not use it when
- you already call the Instagram API with Instagram Login and only need field details; see media fields.
- What the human does
- the account owner decides the account type. A personal account has to be switched to Business or Creator before any feed API can list its posts.
- Next step
- pick a row in the options table, then follow the migration table if you keep your own code.
What happened and what broke
Meta announced the end of the Basic Display API on 2024-09-04 and switched it off on 2024-12-04; since then every request to it fails, and Meta names the Instagram API with Instagram Login as the replacement (Meta developer blog, 2024-09-04, checked 2026-09-18).
| Date | Change |
|---|---|
| 2024-09-04 | Shutdown of the Basic Display API announced. |
| 2024-12-04 | Basic Display API off; all requests fail. |
| 2025-01-27 | Instagram Login scope values business_basic, business_content_publish, business_manage_comments and business_manage_messages deprecated. |
| 2025-11-03 | instagram_oembed stops returning thumbnail_url, thumbnail_width, thumbnail_height and author_name. |
| 2026-05-15 | instagram_oembed callable without an access token, 1,000 requests per hour. |
Sources: Meta developer blog, 2024-09-04, checked 2026-09-18; Meta: Instagram API with Instagram Login, checked 2026-09-18; Meta developer blog, oEmbed updates, checked 2026-09-18; Meta: Instagram Platform changelog, checked 2026-09-18.
Three things stopped working on the shutdown date:
- Code on the old endpoints. Plugins, widgets and scripts built on Basic Display kept working only if their authors moved them to another API; the rest get errors.
- Old tokens. Tokens granted with
user_profileanduser_mediabelonged to the retired API. Each account has to authorize again underinstagram_business_basic. - Personal accounts. Basic Display could read them. Its replacement serves professional accounts only (Meta: Instagram Platform overview, checked 2026-09-18).
The options
Four routes are left. Three are legitimate; reject the fourth.
| Option | Lists a feed | Accounts | What it needs | Limits |
|---|---|---|---|---|
| Instagram API with Instagram Login (your code) | Yes, with cursor paging | Business and Creator only | A Meta app, the instagram_business_basic scope, a token refreshed within 60 days | Accounts you do not own or manage need Advanced Access: App Review plus Business Verification |
oEmbed (instagram_oembed) | No: one post per call, by URL | Public accounts, except inactive, age-restricted or embed-disabled ones | No token since 2026-05-15 | 1,000 requests per hour; no thumbnail or author name since 2025-11-03; no Stories |
| Hosted feed or widget | Yes | Set by each service | The owner connects the account on the service | Plan limits and image handling differ by vendor |
| Scraping instagram.com | Until it breaks | Any, in theory | Proxies or headless browsers | Breaks on markup changes and violates Instagram's terms; do not use |
Sources: Meta: Instagram Platform overview, checked 2026-09-18; Meta: Instagram Platform App Review, checked 2026-09-18; Meta: access_token reference, checked 2026-09-18; Meta: Instagram Platform changelog, checked 2026-09-18; Meta developer blog, oEmbed updates, checked 2026-09-18.
Instagram API with Instagram Login
This is the successor Meta points to, and the host is still graph.instagram.com, so most request code survives. What changes is the account type, the scope and the app setup. A sibling variant, the Instagram API with Facebook Login, uses the instagram_basic permission instead (Meta: Instagram API with Instagram Login, checked 2026-09-18); choose one and do not mix their scopes.
For accounts you own or manage, Standard Access is enough and no App Review is needed. A product that connects other people's accounts needs Advanced Access, which requires App Review and Business Verification (Meta: Instagram Platform App Review, checked 2026-09-18). Details are on App Review.
In Development mode the Instagram account usually also needs the Instagram Tester role; without it, calls fail with "Insufficient developer role", according to one integrator's documentation (Chatwoot docs on Instagram Business Login, checked 2026-09-18).
oEmbed
oEmbed turns a single post URL into embed HTML. Since 2025-11-03 it no longer returns thumbnail fields or author_name (Meta developer blog, oEmbed updates, checked 2026-09-18), so it cannot feed images into a grid you design. Since 2026-05-15 it can be called without an access token, up to 1,000 requests per hour (Meta: Instagram Platform changelog, checked 2026-09-18).
One Meta page describing the oEmbed feature still lists App Review as a requirement. The changelog entry is newer, so test an unauthenticated call before planning around either (changelog checked 2026-09-18).
Terminal
curl -sG "https://graph.facebook.com/v25.0/instagram_oembed" \
--data-urlencode "url=https://www.instagram.com/p/EXAMPLE/"
It fits a page that shows a few chosen posts. It is not a feed: every post URL must be known in advance, and new posts never appear on their own.
A hosted feed or widget
A service holds the Instagram connection and gives the site an embed or a JSON feed. The ElectricBlaze widget is one: the owner connects the account in the dashboard and the site pastes two lines of HTML. Which Instagram account types it can connect is not established yet. Its data fields are listed on media fields, and other services are compared, with check dates, in the feed API comparison.
Scraping
Scrapers of instagram.com break whenever the markup or the login wall changes, and automated collection without permission violates Instagram's Terms of Use. Do not ship one to a client site.
Move Basic Display code to Instagram Login
If the account is Business or Creator, most existing code stays. The table pairs what Basic Display code called with its current counterpart.
| Piece | Basic Display (retired) | Instagram Login (current) |
|---|---|---|
| Accounts | Personal and professional | Business or Creator only |
| Scopes | user_profile,user_media | instagram_business_basic |
| List media | GET graph.instagram.com/me/media | GET graph.instagram.com/v25.0/<IG_ID>/media, or /me/media |
| Media fields | id, caption, media_type, media_url, thumbnail_url, permalink, timestamp, username | Same names. caption is documented for Facebook Login only; test it |
| Short-lived token | From the authorization code | Expires in 1 hour |
| Long-lived token | ig_exchange_token | ig_exchange_token, server only (it carries the app secret); valid 60 days |
| Refresh | ig_refresh_token | ig_refresh_token; the token must be at least 24 hours old, unexpired, with instagram_business_basic granted |
Sources: Meta: Instagram API with Instagram Login, checked 2026-09-18; Meta: get started with Instagram Login, checked 2026-09-18; Meta: IG Media reference, checked 2026-09-18; Meta: access_token reference, checked 2026-09-18; Meta: refresh_access_token reference, checked 2026-09-18.
The Basic Display column reflects code written against the retired API, not a Meta source we checked on 2026-09-18. The right column comes from the sources under the table.
Scope names changed again after the shutdown: business_basic and the other business_* values were deprecated on 2025-01-27 in favor of the instagram_-prefixed names (Meta: Instagram API with Instagram Login, checked 2026-09-18). Code written in late 2024 may still carry the short spelling.
Take the authorization URL and redirect settings from the Instagram Login setup of your Meta app rather than editing the old Basic Display URL. A minimal code change then looks like this:
lib/instagram.ts
-const SCOPES = "user_profile,user_media";
+const SCOPES = "instagram_business_basic";
-const MEDIA = "https://graph.instagram.com/me/media";
+const MEDIA = "https://graph.instagram.com/v25.0/me/media";
// Field names did not change. caption is documented for Facebook Login only: test it.
const FIELDS = "id,caption,media_type,media_url,thumbnail_url,permalink,timestamp";
What /me/media returns under Instagram Login: the field names a Basic Display parser already reads (example values)
{
"data": [
{
"id": "17900000000000001",
"caption": "Example caption.",
"media_type": "IMAGE",
"media_url": "https://scontent.cdninstagram.com/v/example/photo-1.jpg?oe=6AB05820",
"permalink": "https://www.instagram.com/p/EXAMPLE1/",
"timestamp": "2026-09-12T07:41:00+0000"
},
{
"id": "17900000000000002",
"caption": "Example caption for a video.",
"media_type": "VIDEO",
"media_url": "https://scontent.cdninstagram.com/v/example/video-1.mp4?oe=6AB05820",
"thumbnail_url": "https://scontent.cdninstagram.com/v/example/video-1-cover.jpg?oe=6AB05820",
"permalink": "https://www.instagram.com/reel/EXAMPLE2/",
"timestamp": "2026-09-10T16:05:00+0000"
}
],
"paging": {
"cursors": { "before": "EXAMPLE_BEFORE", "after": "EXAMPLE_AFTER" }
}
}
After the first authorization, a refresh has to run inside each 60-day window (access tokens), and image links still expire (media URL expired).
If the account is personal
The Instagram API with Instagram Login does not serve personal accounts (Meta: Instagram Platform overview, checked 2026-09-18), and no app setting changes that. The consequence: to list a personal account's posts through any API, its owner has to switch it to a professional account, Business or Creator, in the Instagram app.
That switch is the owner's call, not the developer's. Routes that need no switch:
- Embed chosen public posts with oEmbed, one call per post. It does not work for private, inactive, age-restricted or embed-disabled accounts, or for Stories (Meta: Instagram Platform changelog, checked 2026-09-18).
- Link to the profile instead of mirroring it. A button to instagram.com has no token to maintain.
- Ask a hosted service whether it accepts personal accounts, and get the answer in writing before you build on it.
Avoid tools that offer a personal-account feed in exchange for the Instagram password or a session cookie. They are scrapers under another name, and the account owner carries the risk.