Skip to main content
Socialift
Guide

How to get a Facebook Page access token

To get a Facebook Page access token, the user goes through Facebook Login and grants pages_show_list plus the pages_* permissions you need. Your server exchanges the short-lived user token for a long-lived one (about 60 days) and calls /me/accounts, which returns a token for each Page. Page tokens obtained this way have no expiration date, but they can still be invalidated.

Updated:

In short: how do you get a Page access token?

You never request a Page token directly — you derive it from a user token. The chain is: Facebook Login → code → short-lived user token → server-side exchange with fb_exchange_token for a long-lived user token → GET /me/accounts. Each Page in the response carries an access_token. Call /me/accounts with the long-lived token and the Page token has no expiration date.

The classic mistake is listing Pages with the short-lived token. The Page token then dies within hours and the integration "randomly" breaks the next morning.

The second mistake is reading "no expiration date" as "forever". Meta's docs say these tokens only expire or get invalidated under certain conditions — so your code must expect token errors and support reconnecting an account.

Meta token types and lifetimes

Who each token acts for and how long it lives, per Meta's documentation.

Meta token types and lifetimes — Capability matrix by platform
TokenActs on behalf ofLifetimeHow you get it
Short-lived user tokenUserTypically 1–2 hoursExchange the code after Facebook Login
Long-lived user tokenUserAbout 60 daysServer-side grant_type=fb_exchange_token
Page token (from short-lived user token)PageHours/me/accounts with the short-lived token
Page token (from long-lived user token)PageNo expiration date, but can be invalidated/me/accounts with the long-lived token
System user tokenBusiness portfolio (Business Manager)Never expires, or 60 days with set_token_expires_in_60_days=trueBusiness Settings or POST /{system-user-id}/access_tokens
App tokenAppFor app settings and service callsServer-side with the app secret, e.g. for debug_token

Meta warns that these lifetimes may change without notice and tokens can expire early. Key your logic off API errors, not dates.

Getting a never-expiring Page token in 5 steps

  1. Configure the app

    Add Facebook Login in the Meta App Dashboard and register the exact redirect URI. In a Business-type app (Facebook Login for Business) permissions live in a configuration, and the login URL carries config_id instead of scope.

  2. Send the user to login

    Add a random state to the URL (CSRF protection) and keep it in the session. The minimum is pages_show_list; add the rest per use case (pages_manage_posts for publishing, and so on).

  3. Exchange the code on the server

    In the callback, compare state, exchange code for a short-lived user token, then use fb_exchange_token to get a long-lived one. The app secret stays on the server — Meta requires server-side token generation anyway.

  4. Fetch the Page tokens

    Call GET /me/accounts with the long-lived user token. Each Page comes back with id, name, access_token and the tasks the user can perform.

  5. Inspect and store encrypted

    Check expires_at, data_access_expires_at and scopes in the Access Token Debugger or via debug_token. Store the token encrypted and keep it out of the frontend and logs.

Python: from login to Page token

With the Socialift SDK the whole flow is four methods: login_url, exchange_code, granted_scopes, pages.

facebook_pages.py
import secrets
from socialift import Facebook

REDIRECT = "https://example.com/facebook/callback"
SCOPES = ["pages_show_list", "pages_read_engagement", "pages_manage_posts"]

def login_link(fb: Facebook) -> tuple[str, str]:
    state = secrets.token_urlsafe(32)  # keep it in the session
    return fb.login_url(redirect_uri=REDIRECT, state=state, scopes=SCOPES), state

async def on_callback(code: str) -> None:
    async with Facebook.from_env() as fb:
        user = await fb.exchange_code(code, redirect_uri=REDIRECT)  # ~60 days
        granted = await fb.granted_scopes(user.access_token)
        missing = set(SCOPES) - set(granted)
        if missing:
            raise RuntimeError(f"Declined permissions: {missing}")
        for page in await fb.pages(user.access_token):
            save_page(page.id, page.name, page.access_token)  # encrypt

exchange_code performs two calls: code → short-lived token → long-lived token. The redirect_uri must match the login URL character for character.

granted_scopes reads what was actually granted via debug_token — users can untick permissions in the dialog.

Business-type apps pass config_id instead of scopes. save_page is your storage function: the SDK stores nothing.

Which permissions a Page integration needs

Dependencies from the Permissions Reference — request the dependencies along with the permission.

Which permissions a Page integration needs — Capability matrix by platform
PermissionWhat it allowsDepends on
pages_show_listList the Pages a person managesno
pages_read_engagementPage posts, photos, videos, follower data and metadatapages_show_list
pages_manage_postsCreate, edit and delete Page postspages_read_engagement, pages_show_list
pages_read_user_contentRead user-generated posts, comments and ratingspages_show_list
pages_manage_engagementCreate, edit and delete comments on the Pagepages_read_user_content, pages_show_list
pages_manage_metadataWebhook subscriptions and Page settingspages_show_list
read_insightsPage insightspages_read_engagement, pages_show_list

yesno

Notes and limits

With Standard Access only people who hold a role on the app can grant these. Serving other people's Pages requires Advanced Access, which goes through App Review and Business Verification.

Permissions granted, still can't post? Check Page tasks

A Page token is limited by the user's tasks on the Page, not just by permissions. Per the Pages API docs: CREATE_CONTENT publishes as the Page, MODERATE replies to and deletes comments, ANALYZE views insights, ADVERTISE creates ads, MESSAGING sends messages and MANAGE assigns tasks.

Rule of thumb: store the tasks array from /me/accounts at connect time and surface it in your UI. If a teammate with only ANALYZE connects the Page, insights work and publishing fails — and that is not a bug in your code.

Why a Page token stops working

The Graph API distinguishes token problems by error_subcode. The common ones:

Why a Page token stops working — Capability matrix by platform
SubcodeCauseWhat to do
460The user changed their passwordAsk them to log in again and fetch new tokens
463The token expired or was revokedRe-login; delete the old token
467Invalid token (revoked or expired)Re-login
458The user removed your appMark the connection as broken
492The token owner lacks the required Page roleAsk a Page admin for a role or reconnect via another admin

The top-level code is usually 190. The Socialift SDK raises code 190 as AuthError — catch it and move the account to a "reconnect required" state.

Data access expiration (90 days) is a separate clock

Beyond token lifetime, Meta has data access expiration: if a user hasn't been active in the last 90 days, they can still log in, but your app loses access to their data. This runs independently of token expiry.

Server-side you can read the date from data_access_expires_at in the debug_token response. To restore access, ask the user to re-grant permissions (auth_type=reauthorize).

System user tokens: server-to-server without a human

A system user is a programmatic identity inside a business portfolio. Its token doesn't depend on an employee's password or session, which makes it the right fit for automating your own company's Pages and ad accounts.

There are two kinds: the admin system user (creates other system users and assigns access — Meta advises against using it to work with assets) and the regular system user (only the assets it's been given). Standard Access allows 1 regular and 1 admin system user; Advanced Access allows 10 regular and 1 admin.

Tokens are generated in Business Settings or via POST /{system-user-id}/access_tokens. The app must belong to the same business, and the requested permissions must have passed App Review. A token either never expires or lasts 60 days with set_token_expires_in_60_days=true; Meta recommends expiring tokens for integrations and they are refreshed with fb_exchange_token. Revoke with /oauth/revoke.

Which to pick: a SaaS serving customers' Pages uses Facebook Login (Facebook Login for Business can also issue a Business Integration System User token, which never expires by default). Automation of your own business assets uses a system user.

Disconnecting: revoke the token properly

Deleting the token from your database isn't enough — the permission stays alive on Facebook's side.

disconnect.py
from socialift import AuthError, Facebook

async def disconnect(user_token: str, account_id: int) -> None:
    async with Facebook.from_env() as fb:
        print("Granted:", await fb.granted_scopes(user_token))
        try:
            await fb.revoke(user_token)  # DELETE /me/permissions
        except AuthError:
            pass  # token already invalid — nothing left on Meta's side
    delete_tokens(account_id)  # remove user and Page tokens from your DB

When all permissions are revoked, the person's user tokens are invalidated and they must grant permissions again on the next connect.

For manual checks, the Access Token Debugger (developers.facebook.com/tools/debug/accesstoken) shows a token's owner, expiry and permissions.

Production checklist

  • Derive Page tokens only from a long-lived user token.
  • Check granted_scopes and show declined permissions in your UI.
  • Store tokens encrypted; keep them out of the frontend, logs and error reports.
  • Send appsecret_proof with every call (the SDK adds it automatically).
  • On error 190, flag the account as "reconnect required" and notify the owner.
  • On disconnect, call revoke and delete the tokens.

← Back to blog

Frequently asked questions

Is there a Facebook Page access token that never expires?

Yes: a Page token obtained with a long-lived user token has no expiration date. It is still invalidated by a password change, a lost Page role or the app being removed, so you must watch for token errors.

Why does my Page token expire after an hour or two?

It was fetched with a short-lived user token. Exchange the user token for a long-lived one with fb_exchange_token on your server, then call /me/accounts again.

Can I use a token from Graph API Explorer in production?

Explorer is a testing tool. In production, tokens come from an OAuth flow on your server: the app secret must never reach the browser, and every customer gets their own token.

What's the difference between a system user token and a Page token?

A Page token comes from the permission of a person who manages the Page and breaks if that person loses their role. A system user token belongs to the business portfolio, isn't tied to an employee and is designed for automating your own business assets.

Does deleting the token from my database revoke access?

No. The permission stays on Facebook's side. Call DELETE /{user-id}/permissions (fb.revoke in the SDK) and then delete the token.

Sources

  1. Meta: Access Token Guide
  2. Meta: Long-Lived Access Tokens
  3. Meta: System user tokens
  4. Meta: Permissions Reference
  5. Meta: Graph API error handling
  6. Meta: Authentication vs Data Access

Related pages