Instagram API Access Token: Get, Exchange, Refresh

By Mika ReyesPublished 6 min read

The short answer

An Instagram API access token comes from Meta's OAuth flow. With Instagram Login you get a 1-hour token, exchange it for a 60-day long-lived token on graph.instagram.com, and refresh it before day 60. With Facebook Login you publish with a Page access token. Adeli holds the Meta app and refreshes every connected account's token for you.

An Instagram API access token is the credential Meta issues when an Instagram professional account authorizes your app, and every call to the Instagram API needs one. How you get it depends on the login. With Instagram Login, you trade an authorization code for a 1-hour token, exchange that for a 60-day token, and refresh it before it lapses. With Facebook Login, you publish with a Page access token taken from a long-lived Facebook User token.

Below are both flows with the exact endpoints, then a refresh schedule and the errors you hit when a token dies.

What is an Instagram API access token?

It's a string that authorizes your app to act for one Instagram account. Each connected account has its own token, and that token only carries the permissions the user granted. There's no app-wide Instagram key: your Meta app has an App ID and App Secret, and the tokens come from each user's login.

Tokens are scoped to a login type. A token from Instagram Login works on graph.instagram.com. A token from Facebook Login works on graph.facebook.com. Send a token to the other host and the request fails, so check the host first when a token that worked in testing breaks in production.

Instagram Login vs. Facebook Login tokens

Pick the column that matches how your users connect. Instagram Login needs no Facebook Page. Facebook Login needs the Instagram account linked to a Page the user manages.

Instagram Login Facebook Login
Token you call the API with Instagram User access token Facebook Page access token (for publishing)
API host graph.instagram.com graph.facebook.com
First token Short-lived, 1 hour Short-lived Facebook User token
Long-lived token 60 days, via ig_exchange_token User token about 60 days, via fb_exchange_token
Refresh ig_refresh_token, adds 60 days Long-lived Page token has no expiration date
Base permission instagram_business_basic instagram_basic plus Page permissions
Facebook Page needed No Yes

Sources: Meta's Instagram Platform overview, Business Login for Instagram, and long-lived tokens for Facebook Login.

Both logins serve professional accounts only. Meta says app users "must have an Instagram professional account", meaning Business or Creator. The two logins use different scopes, and our Instagram API permissions guide lists every one.

How to get a short-lived token

With Instagram Login, send the user to authorize, catch the code, and POST it back. The code is valid for 1 hour and can be used once, per Meta's Business Login docs.

  1. Send the user to the authorization URL. Use https://www.instagram.com/oauth/authorize with client_id, redirect_uri, response_type=code, and scope. Add state to guard against CSRF.
  2. Read the code from your redirect URI. Meta appends #_ to the end of the redirect. It isn't part of the code, so strip it.
  3. Exchange the code for a token. POST it to api.instagram.com from your server:
curl -X POST "https://api.instagram.com/oauth/access_token" \
  -F "client_id=<APP_ID>" \
  -F "client_secret=<APP_SECRET>" \
  -F "grant_type=authorization_code" \
  -F "redirect_uri=<REDIRECT_URI>" \
  -F "code=<AUTH_CODE>"

The response holds access_token, user_id, and permissions. That token is short-lived and valid for 1 hour, according to Meta's get started guide. A reused or malformed code returns OAuthException with the message "Matching code was not found or was already used".

For a test on your own account, you can skip the flow and generate a token in the App Dashboard on the Instagram API setup page. Meta says dashboard tokens are long-lived, valid for 60 days.

With Facebook Login, you run the standard Facebook Login flow instead and get a short-lived Facebook User token. The next section turns it into a Page token.

How to exchange it for a long-lived token

Call the exchange endpoint from your server within the hour. It takes your App Secret, so Meta says it must run in server-side code, never client-side.

Instagram Login. A GET to graph.instagram.com/access_token with grant_type=ig_exchange_token (reference):

curl -G "https://graph.instagram.com/access_token" \
  --data-urlencode "grant_type=ig_exchange_token" \
  --data-urlencode "client_secret=<APP_SECRET>" \
  --data-urlencode "access_token=<SHORT_LIVED_TOKEN>"

You get back access_token, token_type (bearer), and expires_in in seconds. The new token lasts 60 days. Store expires_in with it, because your refresh job needs the date.

Facebook Login. A GET to oauth/access_token with grant_type=fb_exchange_token, your App ID, App Secret, and the short-lived User token (guide):

curl -G "https://graph.facebook.com/oauth/access_token" \
  --data-urlencode "grant_type=fb_exchange_token" \
  --data-urlencode "client_id=<APP_ID>" \
  --data-urlencode "client_secret=<APP_SECRET>" \
  --data-urlencode "fb_exchange_token=<SHORT_LIVED_USER_TOKEN>"

That long-lived User token generally lasts about 60 days. Then call GET /<APP_SCOPED_USER_ID>/accounts with it, and each Page in the data array comes with its own access_token. Page tokens generated from a long-lived User token have no expiration date, so that's the token to store for publishing, which Meta's content publishing docs say needs a Page access token.

How to refresh an Instagram access token

Call refresh_access_token before day 60, and each refresh resets the clock to 60 days. This applies to Instagram Login tokens. Meta's refresh reference sets three conditions:

  • At least 24 hours old. A token issued today can't be refreshed until tomorrow.
  • Not expired. An expired token can't be refreshed at all.
  • instagram_business_basic granted. The user must have approved the base permission.
curl -G "https://graph.instagram.com/refresh_access_token" \
  --data-urlencode "grant_type=ig_refresh_token" \
  --data-urlencode "access_token=<LONG_LIVED_TOKEN>"

The response is a new access_token with a fresh expires_in. Save it over the old one. Tokens that go 60 days without a refresh expire and can't be refreshed, per the Business Login docs, so the user has to log in again.

A refresh schedule that keeps tokens alive:

When What your job does
Day 0 Store the token and its expiry from expires_in
Day 1 or later Token becomes eligible for refresh
Around day 45 Refresh, and store the new token and expiry
Refresh fails Retry, then flag the account for reconnection before day 60
Error 190 at any point Mark the account disconnected and ask the user to log in again

Refreshing two weeks early leaves room for retries when a job fails or the queue backs up. With hundreds of connected accounts, run it daily over every account whose expiry falls inside that window.

How to check if a token is valid

For Instagram Login, call /me. For Facebook Login, call debug_token.

Instagram Login. A successful call to /me with fields=user_id,username shows the token works and returns the account's ID and username (get started guide):

curl -G "https://graph.instagram.com/v25.0/me" \
  --data-urlencode "fields=user_id,username" \
  --data-urlencode "access_token=<ACCESS_TOKEN>"

Facebook Login. The debug_token endpoint returns metadata about a token: is_valid, expires_at, data_access_expires_at, and scopes. You call it with an app access token or an app developer's user token for the same app:

curl -G "https://graph.facebook.com/debug_token" \
  --data-urlencode "input_token=<TOKEN_TO_CHECK>" \
  --data-urlencode "access_token=<APP_ACCESS_TOKEN>"

Meta's debug_token reference doesn't mention Instagram Login tokens, so don't build your Instagram Login checks on it.

Why did my Instagram token stop working?

Check the error code first. It usually names the cause, and these codes come from Meta's Graph API error handling codes.

Symptom Likely cause Fix
Error 190, subcode 463 or 467 Token expired, was revoked, or is invalid Send the user back through login
Error 190, subcode 460 The user changed their password (Facebook Login) Have the user log in to your app again
Error 190, subcode 458 The user removed your app Reauthenticate the user
Error 10 or 200–299 A permission was never granted or was removed Request the missing scope again
Calls fail for other people's accounts Your app only has Standard Access Get Advanced Access through App Review

A few more catches:

  • Personal accounts. Neither login supports them. The user has to switch to a Business or Creator account first.
  • Standard Access. Meta's overview says Standard Access is for people with a role on your app. Accounts you don't own or manage need Advanced Access, App Review, and Business Verification. Our Meta app review guide covers the timeline.
  • Old scope names. Meta deprecated the business_* scopes on January 27, 2025. Apps still requesting them can't call the Instagram endpoints until they switch to the instagram_business_* names.
  • Wrong host. An Instagram User token sent to graph.facebook.com, or a Page token sent to graph.instagram.com, fails.
  • Leaked tokens. Keep tokens and your App Secret out of client code, URLs you log, and public repos. Treat a leaked token as compromised and reconnect the account.

Is there a faster way to manage Instagram tokens?

Yes, by letting a unified API hold them. Adeli holds the Meta developer app, carried Meta's review, and refreshes every connected account's tokens. You hold one API key and send it as a bearer header, as the authentication docs describe. There's no refresh job to run and no 60-day clock to watch.

Each of your users connects their own Instagram account, and Adeli's posting API publishes feed posts, Reels, Stories, and carousels from the same endpoint as every other network. You get a per-platform status on every publish and a webhook when anything changes. Your first 3 connected accounts are free, and there are no per-post fees on Instagram.

faq

Frequently asked questions

How long does an Instagram access token last?

With Instagram Login, the token from the login flow lasts 1 hour and the long-lived token lasts 60 days. Tokens generated in the App Dashboard are also long-lived, at 60 days. With Facebook Login, a long-lived User token lasts about 60 days, and a long-lived Page token has no expiration date.

Can an expired Instagram token be refreshed?

No. Meta's refresh endpoint only accepts a long-lived token that is at least 24 hours old and still valid. Once a token expires, or goes 60 days without a refresh, the user has to log in to your app again to produce a new one.

Do Facebook Page access tokens expire?

A long-lived Page access token has no expiration date, according to Meta. It can still be invalidated, for example when the user loses their role on the Page or revokes your app, so check for error 190 and send the user back through login when it happens.

Power your next project
with one social media API

Give your users publishing, scheduling, and analytics through one integration your team can actually maintain.

Try with agents

Start with free credits. No credit card required.