TL;DR, Quick Answer
8 min readMeta trades a short-lived User access token for a long-lived one through GET oauth/access_token with grant_type=fb_exchange_token. The response carries expires_in 5183944 seconds, which is 56 seconds short of 60 days. Page access tokens generated from a long-lived User token carry no expiration date at all. Meta says it will never tell you when a token dies, so read expires_at from debug_token instead of trusting the 60-day figure.
What is a Facebook long lived access token?
Meta issues a Facebook long lived access token in exchange for a short-lived one, and its documentation puts the life of that token at about 60 days. The exchange is a single server-side call. The reason it exists is stated in the first line of Meta's guide: "Default User and Page access tokens are short-lived, expiring in hours, however, you can exchange a short-lived token for a long-lived token."
Meta draws the distinction in one sentence on its access tokens overview: "Access tokens come in two forms: short-lived and long-lived. Short-lived tokens typically last about one to two hours, while long-lived tokens last about 60 days."
The sentence that follows it is the one most integrations ignore. Meta writes that you should not depend on these lifetimes remaining the same, because "they may change without warning or expire early."
How do you exchange a short-lived token for a long-lived one?
You query the GET oauth/access_token endpoint with grant_type=fb_exchange_token. Meta's own curl sample:
curl -i -X GET "https://graph.facebook.com/{graph-api-version}/oauth/access_token?
grant_type=fb_exchange_token&
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={your-access-token}"Four inputs, three of which are yours. client_id is the App ID, client_secret is the App Secret, and fb_exchange_token is the short-lived User access token you already hold. The response:
{
"access_token": "{long-lived-user-access-token}",
"token_type": "bearer",
"expires_in": 5183944
}Meta annotates expires_in in the sample itself as "The number of seconds until the token expires." That number is worth doing the arithmetic on. Sixty days is 5,184,000 seconds. Meta's documented value is 5,183,944, which lands 56 seconds short of a round 60 days. The gap is trivial in practice and instructive in principle: the documented figure is not a promise of exactly 60 days, it is a sample value, and Meta says the underlying lifetime can change.
Three caveats come attached to the exchange, in Meta's wording:
- "You can not use an expired token to request a long-lived token." Once the short-lived token is dead, the user has to go through login again.
- "Make this call from your server, not a client. Your app secret is included in this API call, so you should never make the request client-side."
- "Do not use the same long-lived tokens on more than one web client."
The second caveat also carries a storage instruction that gets skipped: the long-lived token "will be a different string than the original token, so if you're storing these tokens, replace the old one."
Short-lived against long-lived, in one table
| Short-lived User token | Long-lived User token | Page token from a long-lived User token | |
|---|---|---|---|
| Documented life | "about one to two hours" | "about 60 days" | No expiration date |
| How you get it | Web login flow | grant_type=fb_exchange_token | GET {app-scoped-user-id}/accounts |
| Where the call runs | Client or server | Server only, it carries the app secret | Server |
Sample expires_in | Not published | 5183944 | Not returned |
Mobile is the exception that confuses people reading about web integrations. Meta writes that "Native mobile apps using Facebook's SDKs get long-lived User access tokens, good for about 60 days. These tokens are refreshed once per day, when the person using your app makes a request to Facebook's servers." The daily refresh only happens if the person keeps using the app, since "If no requests are made, the token will expire after about 60 days."

Why does a Page access token behave differently?
A Page access token derived from a long-lived User access token has no expiry. Meta states it plainly: "Long-lived Page access token do not have an expiration date and only expire or are invalidated under certain conditions."
You get one by calling the accounts edge with the long-lived User token:
curl -i -X GET "https://graph.facebook.com/{graph-api-version}/{app-scoped-user-id}/accounts?
access_token={long-lived-user-access-token}"The response returns one object per Page, each carrying its own access_token, plus category, name, id and a tasks array holding values like ANALYZE, ADVERTISE, MODERATE, CREATE_CONTENT and MANAGE. There is no expires_in in that payload, which is the response-shape version of the same claim.
Two conditions gate it. Meta requires that "The person requesting the token must have a role on the Page," and it notes elsewhere that "Page access tokens are unique to each Page, admin, and app combination." Change any of those three and you have a different token, so a Page token does not survive the admin who created it losing their role.
This is the single biggest structural reason publishing integrations are built on Page tokens rather than User tokens. A queue that has to survive a 60-day clock needs a refresh strategy; a queue on a Page token does not have a clock to survive. It is also why connecting an Instagram account to a Facebook Business Page matters for API work rather than just for cross-posting, since the Instagram API with Facebook Login authenticates with a Facebook Page access token.
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant

What invalidates a token before 60 days?
Meta never publishes a complete list. The long-lived token page says Page tokens "only expire or are invalidated under certain conditions" and links to its debugging page for those conditions. That page names one general cause and shows three specific error responses, and it never enumerates the conditions as a list.
The general cause, quoted: "Due to security related events, access tokens may be invalidated before the expected expiration time."
The three documented failures, each returning code 190:
| Subcode | Message | What triggered it |
|---|---|---|
463 | "Error validating access token: Session has expired on..." | The token reached its expiry time |
460 | "Error validating access token: The session is invalid because the user logged out." | Meta: "a person logged out of your app or changed their password" |
458 | "Error validating access token: User {user-id} has not authorized application {your-app-id}." | Authorization revoked, or never granted |
A password change is the one that catches teams off guard, because it invalidates tokens through no fault of the integration and generates no signal. Meta is explicit about the absence of that signal: "Facebook will not notify you that an access token has become invalid. Unless you have sent the expiry time to your app along with the access token, your app may only learn that a given token has become invalid when you attempt to make a request to the API."
That sentence is the operational heart of the whole topic. There is no webhook for a dead token. A scheduled post is where most teams discover the problem, which is why a dead token sits high on the list of reasons Facebook scheduled posts stop working with no obvious change at the publishing end.
How do you check what a token actually has left?
Query debug_token rather than trusting the 60-day figure:
curl -i -X GET "https://graph.facebook.com/debug_token?
input_token={input-token}&
access_token={valid-access-token}"Meta adds one constraint: "The tokens must be from the same app." The response returns app_id, type, application, expires_at, data_access_expires_at, is_valid, scopes, granular_scopes and user_id, and Meta notes that "For long-lived access tokens the issued_at field is also returned."
Two of those fields are separate clocks and get conflated constantly. expires_at is when the token stops working. data_access_expires_at is a different deadline governing continued access to user data. A token can be valid against the first and restricted by the second.
Build the check into the pipeline, not into a runbook. Reading expires_at before a publish costs one request and turns a silent failure into a scheduled reauthorization, in the same way that reading Instagram's content_publishing_limit before you publish turns a rate limit into a queue decision. Both are cheap reads that replace an error you cannot predict with a number you can.
One class of app escapes the clock entirely. Meta writes that "Apps with Standard access to the Marketing API receive long-lived tokens that do not expire based on time, though they are still subject to invalidation for other reasons," and it extends that to System User tokens in Business Manager. Time stops being the failure mode; the security-event invalidations do not.
Frequently asked questions
How long does a Facebook long-lived access token last?
About 60 days. Meta's sample response returns expires_in: 5183944 seconds, which is 56 seconds under 60 days, and Meta warns that the lifetime "may change without warning."
What is the exact exchange endpoint?
GET https://graph.facebook.com/{graph-api-version}/oauth/access_token with grant_type=fb_exchange_token, client_id, client_secret and fb_exchange_token. It must run server-side because it carries the app secret.
Can you refresh a long-lived token before it expires?
Meta documents the exchange only as short-lived to long-lived, and states that "You can not use an expired token to request a long-lived token." It does not document a refresh of an already long-lived User token on the web.
Do Page access tokens ever expire?
Meta says Page tokens generated from a long-lived User access token "do not have an expiration date and only expire or are invalidated under certain conditions," and it never publishes those conditions as a complete list.
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant
Will Facebook tell you when a token dies?
No. Meta's documentation states directly that "Facebook will not notify you that an access token has become invalid," and that your app may only find out when a request fails.
Which error means the user changed their password?
Code 190, subcode 460, with the message "Error validating access token: The session is invalid because the user logged out." Meta attributes that response to a person who "logged out of your app or changed their password."
What happens if your short-lived token already expired before you exchange it?
Meta blocks the exchange outright: "You can not use an expired token to request a long-lived token." The short-lived token has to still be alive when you call oauth/access_token, so if you wait too long after login, the only fix is sending the user through the login flow again.
Can one long-lived token serve two different web clients?
Meta's caveat is explicit: "Do not use the same long-lived tokens on more than one web client." Each web client is meant to run its own exchange call and hold its own token rather than sharing one across properties.
What happens to the short-lived token string after you exchange it?
The long-lived token Meta returns "will be a different string than the original token," so whatever storage layer held the short-lived token needs an update. Meta's instruction is direct: if you're storing these tokens, replace the old one instead of keeping both around.
Do Marketing API tokens follow the same 60-day clock?
Apps with Standard access to the Marketing API get long-lived tokens that don't expire based on time, per Meta's documentation, though they remain subject to invalidation for other reasons. Meta extends the same exception to System User tokens in Business Manager. The 60-day clock simply doesn't apply there, and security-event invalidations still do.
Put this into practice with AdaptlyPost
Was This Article Helpful?
Let us know what you think!
See us more often in Google
One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.
Before you go...
AdaptlyPost
Schedule your content across all platforms
Manage all your social media accounts in one place with AdaptlyPost.
All-platform analytics
Social Inbox
AI-powered assistant
Related Glossary Terms


Why Your Social Media Scheduler Keeps Disconnecting Accounts
A social media scheduler keeps disconnecting when a token expires or dies early. Token lifetimes for Meta, LinkedIn, X and TikTok, and what kills them.


What Instagram's content_publishing_limit Endpoint Returns
Instagram's content_publishing_limit endpoint returns quota_usage plus a config block holding quota_total 50 and quota_duration 86400 seconds.


Reading the Instagram Container status_code Before You Publish
Every Instagram container status_code value Meta documents, the polling cadence it recommends, the 24-hour expiry window, and what to do on ERROR.
Related Articles


How the Instagram API 100 Posts per 24 Hours Limit Works
Meta's Instagram API 100 posts per 24 hours limit is a rolling window counted at publish. Carousels count once, and the page's 50-post sentence goes unresolved.


How a Bluesky threadgate Decides Who Can Reply to a Post
A Bluesky threadgate limits replies to mentioned users, followers, people you follow or a list. How the record works, and the postgate that stops quotes.


Meta Documents Four Different Limits for Facebook scheduled_publish_time
The Facebook scheduled_publish_time field needs a time at least 10 minutes out, and Meta gives four maximums for it: 29 days, 30 days, 75 days and 6 months.

