# Instagram feed not working: API errors, empty data and missing fields

**Status, checked 2026-09-18:** requests to the Basic Display API have failed since 2024-12-04 ([Meta developer blog, 2024-09-04](https://developers.facebook.com/blog/post/2024/09/04/update-on-instagram-basic-display-api/), checked 2026-09-18); Instagram Login tokens stop working after 60 days unless refreshed ([Meta: access_token reference](https://developers.facebook.com/docs/instagram-platform/reference/access_token), checked 2026-09-18); throttled calls return error `80002`. For the ElectricBlaze widget, three checks on the page itself are listed at the end.

> Start from what you see, match it to a cause Meta documents, apply the fix. Each row names its source and the date we checked it.

Canonical: https://electricblaze.com/developer/instagram-feed/feed-not-working.html

## At a glance

- **Use it when:** a feed built on `graph.instagram.com` returns an error, an empty `data` array, posts without images or captions, or images that break some time after the page was built.
- **Do not use it when:** the code still calls the Instagram Basic Display API. There is nothing to fix there; migrate as described in [Basic Display alternative](https://electricblaze.com/developer/instagram-feed/basic-display-api-alternative.html).
- **What the human does:** the account owner logs in again after an expired or invalidated token, confirms the account is Business or Creator, and in Development mode accepts the Instagram Tester invite.
- **Next step:** run the check script below with your token. It prints the HTTP status, the usage header, and the error code with its subcode, which is enough to find your row in the table.

## Run one request and read all of it

Before changing code, make the call your feed makes and read the raw answer, headers included. The URL uses `v25.0` because the Instagram examples from Meta do; v26.0 has been out since 2026-07-29 ([Meta: Graph API changelog](https://developers.facebook.com/docs/graph-api/changelog), checked 2026-09-18). Pin the version you tested and upgrade on purpose.

```sh
# -D - prints the response headers before the JSON body
curl -sS -D - "https://graph.instagram.com/v25.0/me/media?fields=id,media_type,media_url,permalink,timestamp&limit=5&access_token=$IG_ACCESS_TOKEN"
```

The same check in Node 18+, with a verdict instead of raw JSON:

scripts/check-instagram.mjs:

```js
// Usage: IG_ACCESS_TOKEN=... node scripts/check-instagram.mjs
const url = new URL("https://graph.instagram.com/v25.0/me/media");
url.searchParams.set("fields", "id,caption,media_type,media_url,permalink,timestamp");
url.searchParams.set("limit", "10");
url.searchParams.set("access_token", process.env.IG_ACCESS_TOKEN ?? "");

const res = await fetch(url);
const body = await res.json();
console.log("HTTP", res.status);
console.log("X-Business-Use-Case-Usage:", res.headers.get("x-business-use-case-usage") ?? "(absent)");

if (body.error) {
  const { type, code, error_subcode, message } = body.error;
  const hints = {
    "190/463": "token expired: the owner logs in again, then schedule refreshes",
    "190/460": "password changed: the owner logs in again",
    "190/467": "token invalid: check the stored value, then log in again",
  };
  console.log(type, code, error_subcode ?? "-", message);
  console.log("->", hints[`${code}/${error_subcode}`] ?? (code === 80002 ? "throttled: cache and call less often" : "see the table"));
} else {
  const items = body.data ?? [];
  console.log("items:", items.length, "| more pages:", Boolean(body.paging?.next));
  console.log("no media_url:", items.filter((m) => !m.media_url).map((m) => m.id));
  console.log("no caption field:", items.filter((m) => !("caption" in m)).length); // also counts posts with no caption
}
```

## Symptom, cause, fix

Take the first row that matches. Rows that name a code or a message come from the `error` object; the others come from the shape of `data` or the setup.

| Symptom | Cause | Fix |
|---|---|---|
| `OAuthException`, code 190, `error_subcode` 463 | The long-lived token reached 60 days without a refresh | The owner logs in again; then schedule monthly refreshes ([access tokens](https://electricblaze.com/developer/instagram-feed/access-token.html)) |
| Code 190, subcode 460 | The account password changed | The owner logs in again |
| Code 190, subcode 467 | The token is invalid for another reason | Check the stored value is complete and belongs to this app, then get a new one through Instagram Login |
| Every item has only `id` | No `fields=` parameter in the request | List the fields: `fields=id,media_type,media_url,permalink,timestamp` |
| `data` is `[]` although fields were requested | The account has no posts, or the token belongs to another account than you think | Call `/v25.0/me?fields=username` with the same token and compare the handle |
| One post has no `media_url` | Meta leaves it out for copyrighted or copyright-flagged media, for example a reel that uses licensed music | Skip the item or show a link to its `permalink`; it is not an error |
| No `caption` or `media_product_type` | Both are marked as Facebook Login only in the IG Media reference | Test with your token; render without them when absent |
| Images answer 403 "URL signature expired" | The signed link passed the expiry encoded in its `oe` parameter | Fetch fresh URLs before serving cached HTML ([media URL expired](https://electricblaze.com/developer/instagram-feed/media-url-expired.html)) |
| Error `80002`, high values in `X-Business-Use-Case-Usage` | The app used up its Instagram Platform call budget | Cache on the server and call once per refresh interval, not once per page view |
| "Insufficient developer role" | Development mode, and the account lacks the Instagram Tester role (reported by a secondary source) | Invite the account as an Instagram Tester; the owner accepts under Settings, Apps and websites, Tester invites in Instagram |
| Code written before December 2024 fails on every call | It targets the Instagram Basic Display API, shut down on 2024-12-04 | Move to the Instagram API with Instagram Login ([Basic Display alternative](https://electricblaze.com/developer/instagram-feed/basic-display-api-alternative.html)) |
| The authorize URL still requests `business_basic` | That scope value was deprecated on 2025-01-27 | Request `instagram_business_basic` |
| The owner's account is personal | Only professional accounts are served | The owner switches it to Business or Creator in the Instagram app |

Sources: [Meta: Graph API error handling](https://developers.facebook.com/docs/graph-api/guides/error-handling), checked 2026-09-18; [Meta: get started with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/get-started), checked 2026-09-18; [Meta: IG Media reference](https://developers.facebook.com/docs/instagram-platform/reference/instagram-media), checked 2026-09-18; [verbb/social-feeds issue 21 (2026-01)](https://github.com/verbb/social-feeds/issues/21), checked 2026-09-18 (secondary); [Meta: rate limiting](https://developers.facebook.com/docs/graph-api/overview/rate-limiting), checked 2026-09-18; [Chatwoot docs on Instagram Business Login](https://developers.chatwoot.com/self-hosted/configuration/features/integrations/instagram-via-instagram-business-login), checked 2026-09-18 (secondary); [Meta developer blog, 2024-09-04](https://developers.facebook.com/blog/post/2024/09/04/update-on-instagram-basic-display-api/), checked 2026-09-18; [Meta: Instagram API with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login), checked 2026-09-18; [Meta: Instagram Platform overview](https://developers.facebook.com/docs/instagram-platform/overview), checked 2026-09-18.

## Reading the error object

Every failed call carries an `error` object. Branch on `code` and `error_subcode`; the `message` text embeds timestamps and varies from call to call.

An expired long-lived token (example values):

```json
{
  "error": {
    "message": "Error validating access token: Session has expired on Saturday, 12-Sep-26 09:15:42 PDT. The current time is Friday, 18-Sep-26 03:02:11 PDT.",
    "type": "OAuthException",
    "code": 190,
    "error_subcode": 463,
    "fbtrace_id": "AbCdEfGhIjK_example"
  }
}
```

- Code 190 means the token is unusable: 463 expired, 460 password changed, 467 invalid ([Meta: Graph API error handling](https://developers.facebook.com/docs/graph-api/guides/error-handling), checked 2026-09-18). All three end with the owner logging in again.
- Do not branch on `type` alone. `OAuthException` also shows up on errors that have nothing to do with tokens.
- Log `fbtrace_id` with the time of the call. It identifies the request if you ever report the problem to Meta.

## Empty or partial data

An empty or short feed with HTTP 200 carries no `error` object. Three causes explain it:

1. **No fields requested.** Without `fields=`, the media edge returns each item as an id and nothing more ([Meta: get started with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/get-started), checked 2026-09-18). The renderer has no image to draw.
2. **Another account, or no posts.** A token belongs to exactly one account. Ask `/me?fields=username` which one before debugging the rest.
3. **Pagination stopped early.** A page can hold fewer items than `limit`, so a short page is not the end of the feed; stop only when `paging.next` is absent ([Meta: Graph API paginated results](https://developers.facebook.com/docs/graph-api/results), checked 2026-09-18).

A missing field on one item is often expected. `media_url` is omitted when the media contains copyrighted material or was flagged for it ([Meta: IG Media reference](https://developers.facebook.com/docs/instagram-platform/reference/instagram-media), checked 2026-09-18). `thumbnail_url` exists only on VIDEO items ([Meta: IG Media reference](https://developers.facebook.com/docs/instagram-platform/reference/instagram-media), checked 2026-09-18). Carousel `children` come back as bare ids until you expand them as `children{media_type,media_url,thumbnail_url}` ([Meta: IG Media children](https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-media/children), checked 2026-09-18).

> Available for Instagram API with Facebook Login only
>
> [Meta: IG Media reference](https://developers.facebook.com/docs/instagram-platform/reference/instagram-media), checked 2026-09-18, on `caption` and `media_product_type`

Many tutorials request `caption` from `graph.instagram.com` regardless. We make no promise in either direction: test with your own token and keep the layout intact when the field is absent. [Media fields](https://electricblaze.com/developer/instagram-feed/media-fields.html) covers each field in detail.

## Throttling: error 80002

Instagram Platform calls, messaging aside, share a budget of 4800 × the number of impressions per 24 hours ([Meta: rate limiting](https://developers.facebook.com/docs/graph-api/overview/rate-limiting), checked 2026-09-18). Past it, calls fail with `80002`. The `X-Business-Use-Case-Usage` response header reports how much of the budget is used, so log it on every call and slow down before the limit, not after.

Codes 4, 17 and 613 are general Graph API limits. Back off on them too, but for Instagram Platform calls look for `80002` first.

One call per refresh window is enough for a feed. Serve page views from a server-side cache; a browser calling Instagram directly would also expose the token.

## Checks for the ElectricBlaze widget

For the ElectricBlaze embed, the token rows above do not apply to your site. Three page-side checks do:

1. **The id is the container's first class.** The loader takes the widget id from the first class and ignores the rest, so `class="electricblaze-id-w42 feed"` mounts and `class="feed electricblaze-id-w42"` does not.
2. **The Content Security Policy lets the widget through.** `script-src` must allow `https://s.electricblaze.com`. `connect-src` must allow `https://api.electricblaze.com`, `https://proxy.electricblaze.com`, which serves the data of connected accounts, and `https://s.electricblaze.com` for demo data. The browser console names any other blocked host and directive.
3. **The state class tells you where it stopped.** The loader sets `electricblaze-state-loading`, `-mounting`, `-mounted` or `-error` on the container. A container left in `electricblaze-state-error` did not mount: check the widget id and the `/v1/package` request in the network panel.

```http
Content-Security-Policy: script-src 'self' https://s.electricblaze.com; connect-src 'self' https://api.electricblaze.com https://proxy.electricblaze.com https://s.electricblaze.com; img-src 'self' https: data:
```

The loader also picks up containers added after page load, such as after a client-side route change, and ignores a second copy of `widget.js`. What the widget displays once a Free plan passes 1000 views in a month is not established yet; this page will say when it is.

## FAQ

### Why does /me/media return only ids?

The request has no `fields=` parameter. Without it the media edge returns every item as a bare id. Add `fields=id,media_type,media_url,permalink,timestamp`.

### What does OAuthException 190 with error_subcode 463 mean?

The access token expired. Tokens from Instagram Login last 60 days and cannot be refreshed after that, so the account owner has to log in again.

### Why is caption missing from the Instagram API response?

The IG Media reference marks `caption` as available with Facebook Login only ([Meta: IG Media reference](https://developers.facebook.com/docs/instagram-platform/reference/instagram-media), checked 2026-09-18). Test with your token and render posts without a caption when the field is absent.

### Why do Instagram images stop loading some time after the page was built?

`media_url` is a signed link whose `oe` parameter holds the expiry; after it the server answers 403 "URL signature expired" ([verbb/social-feeds issue 21 (2026-01)](https://github.com/verbb/social-feeds/issues/21), checked 2026-09-18, secondary). Meta publishes no lifetime, so fetch fresh URLs before serving cached pages.

### Does the Instagram Basic Display API still work?

No. Meta shut it down on 2024-12-04, and every request to it fails. The replacement is the Instagram API with Instagram Login, for Business and Creator accounts.

### What is Instagram API error 80002?

The Instagram Platform throttling error. The budget is 4800 × impressions per 24 hours, and the `X-Business-Use-Case-Usage` header shows how close you are. Cache responses on the server.

## Related pages

- [Access tokens](https://electricblaze.com/developer/instagram-feed/access-token.html)
- [Media URL expired](https://electricblaze.com/developer/instagram-feed/media-url-expired.html)
- [Media fields](https://electricblaze.com/developer/instagram-feed/media-fields.html)
- [Basic Display alternative](https://electricblaze.com/developer/instagram-feed/basic-display-api-alternative.html)
- [App Review](https://electricblaze.com/developer/instagram-feed/app-review.html)
- [Instagram feed for developers](https://electricblaze.com/developer/instagram-feed/)

---

ElectricBlaze, updated 2026-09-18. Source of this page: https://electricblaze.com/developer/instagram-feed/feed-not-working.html
