Как получить и обновить токен доступа Instagram API
Токен доступа Instagram получают из OAuth-кода: код меняется на короткоживущий токен (1 час), а затем на долгоживущий (60 дней). В варианте с Instagram Login такой токен обновляется через graph.instagram.com, если ему не меньше 24 часов. В варианте с Facebook Login получают долгоживущий пользовательский токен, а затем берут со страницы её токен и ID аккаунта Instagram.
Обновлено:
Какой токен Instagram вам нужен?
Зависит от варианта подключения. Instagram API with Instagram Login работает на graph.instagram.com с Instagram User access token, который выдаёт instagram.com. Instagram API with Facebook Login работает на graph.facebook.com с токенами Facebook: пользовательский токен нужен, чтобы получить список страниц, а токен страницы — чтобы вызывать эндпоинты Instagram. Каждое семейство токенов работает со своим хостом.
Любой запрос токена, в котором участвует секрет приложения (app secret), выполняется только на сервере. Meta отдельно подчёркивает это и для обмена на долгоживущий токен Instagram, и для вызова fb_exchange_token в Facebook.
Таблица ниже сводит все типы токенов в одном месте: большинство ошибок интеграции возникают именно из-за путаницы типа токена и хоста.
Типы токенов Instagram и срок их действия
| Токен | Вариант | Срок действия | Откуда берётся |
|---|---|---|---|
| Authorization code | Instagram Login | 1 час, одноразовый | Редирект с instagram.com/oauth/authorize |
| Короткоживущий Instagram User token | Instagram Login | 1 час | POST api.instagram.com/oauth/access_token |
| Долгоживущий Instagram User token | Instagram Login | 60 дней, обновляется | GET graph.instagram.com/access_token (ig_exchange_token) |
| Короткоживущий Facebook User token | Facebook Login | Несколько часов | graph.facebook.com/{version}/oauth/access_token с кодом |
| Долгоживущий Facebook User token | Facebook Login | Около 60 дней | Тот же эндпоинт, grant_type=fb_exchange_token |
| Page access token | Facebook Login | Без срока действия, если получен долгоживущим user token | GET /me/accounts |
Даже бессрочный токен страницы может быть аннулирован при определённых условиях — типичные причины видны в подкодах ошибки 190 ниже.
Instagram Login: от кода до долгоживущего токена
Отправьте пользователя в окно входа
Перенаправьте на https://www.instagram.com/oauth/authorize с client_id, redirect_uri, response_type=code, scope через запятую (например, instagram_business_basic,instagram_business_manage_messages) и случайным state.
Получите код
Instagram вернёт пользователя на redirect_uri с ?code=...; хвост #_ не является частью кода — отрежьте его. Код действует 1 час и используется один раз.
Обменяйте на короткоживущий токен
Отправьте POST на https://api.instagram.com/oauth/access_token с полями формы client_id, client_secret, grant_type=authorization_code, redirect_uri и code. В ответе — короткий токен, user_id и выданные разрешения.
Получите долгоживущий токен
GET https://graph.instagram.com/access_token с grant_type=ig_exchange_token, client_secret и access_token. expires_in — около 5 184 000 секунд, то есть 60 дней.
Сохраните вместе со сроком
Храните токен в зашифрованном виде вместе с expires_at (текущее время + expires_in) — эта дата понадобится задаче обновления.
Тот же поток в Socialift SDK
import os
from socialift import Instagram
async def instagram_callback(code: str, state: str, expected_state: str) -> dict:
if state != expected_state:
raise ValueError("state не совпадает") # защита от CSRF
async with Instagram.from_env() as ig:
bundle = await ig.exchange_code(code, redirect_uri=os.environ["IG_REDIRECT_URI"])
profile = await ig.profile(bundle.access_token)
return {
"username": profile.username,
"token": bundle.access_token, # зашифруйте перед сохранением
"expires_at": bundle.expires_at, # примерно через 60 дней
}exchange_code делает оба шага: POST с form-data на api.instagram.com и вызов ig_exchange_token. Возвращает TokenBundle с access_token, expires_in и вычисленным expires_at.
ig.login_url(redirect_uri=..., state=...) собирает ссылку входа со стандартными scope SDK instagram_business_*; чтобы сузить набор, передайте scopes=[...]. SDK не хранит state — держите его в сессии.
Как обновить долгоживущий токен Instagram?
Отправьте GET https://graph.instagram.com/refresh_access_token с grant_type=ig_refresh_token и текущим токеном. В ответе придёт новый долгоживущий токен, снова примерно на 60 дней.
Условий три: токену не меньше 24 часов, срок его действия не истёк, пользователь выдал разрешение instagram_business_basic. Токен, который не обновляли 60 дней, истекает окончательно и обновлению не подлежит — пользователю придётся войти заново.
На практике достаточно ежедневной или еженедельной cron-задачи, которая обновляет токены, истекающие в ближайшие одну-две недели. Обновление стоит копейки, а потеря аккаунта из-за упавшего cron — дорого.
Задача автоматического обновления токенов
from datetime import datetime, timedelta, timezone
from socialift import AuthError, Instagram
async def refresh_instagram_tokens(accounts) -> None:
soon = datetime.now(timezone.utc) + timedelta(days=10)
async with Instagram.from_env() as ig:
for acc in accounts: # записи из вашей базы
if acc.expires_at > soon:
continue
try:
bundle = await ig.refresh_token(acc.token)
except AuthError:
acc.status = "reconnect_required" # истёк или отозван
continue
acc.token, acc.expires_at = bundle.access_token, bundle.expires_atAuthError не лечится повтором: переведите аккаунт в состояние «нужно переподключить» и уведомите пользователя.
Facebook Login: user token → токен страницы → ID аккаунта Instagram
Вход через Facebook
Проведите пользователя через Facebook Login (в Business-приложениях — с ID конфигурации) и запросите instagram_basic, pages_show_list и разрешения нужной функции.
Обменяйте код
GET /oauth/access_token на graph.facebook.com с client_id, client_secret, redirect_uri и code вернёт короткоживущий пользовательский токен, который истекает через несколько часов.
Получите долгоживущий user token
Вызовите тот же эндпоинт с grant_type=fb_exchange_token, client_id, client_secret и fb_exchange_token. Такой токен обычно действует около 60 дней.
Страницы и их токены
GET /me/accounts с долгоживущим токеном вернёт страницы, где у пользователя есть задачи MANAGE, CREATE_CONTENT, MODERATE или ADVERTISE, вместе с access_token. Полученные так токены страниц бессрочные.
Найдите аккаунт Instagram
GET /{page-id}?fields=instagram_business_account вернёт ID привязанного профессионального аккаунта Instagram. Именно этот ID используется во всех запросах Instagram.
Вызывайте эндпоинты Instagram
Отправляйте запросы на graph.facebook.com/{version}/<IG_ID>/... с токеном страницы.
Поток Facebook Login в SDK
import os
from socialift import Facebook, Instagram
async def facebook_callback(code: str) -> list[dict]:
async with Facebook.from_env() as fb:
user = await fb.exchange_code(code, redirect_uri=os.environ["FB_REDIRECT_URI"])
print("выдано:", await fb.granted_scopes(user.access_token))
pages = await fb.pages(user.access_token)
accounts = [p for p in pages if p.instagram_id]
async with Instagram.via_facebook(app_secret=os.environ["FACEBOOK_APP_SECRET"]) as ig:
for page in accounts:
profile = await ig.profile(page.access_token, ig_user_id=page.instagram_id)
print(page.name, "->", profile.username)
return [{"page_id": p.id, "ig_user_id": p.instagram_id, "page_token": p.access_token} for p in accounts]fb.exchange_code выполняет оба обмена за один вызов и возвращает долгоживущий user token; redirect_uri должен совпадать со ссылкой входа символ в символ.
fb.pages запрашивает instagram_business_account в том же вызове /me/accounts — отдельный запрос на каждую страницу не нужен.
fb.granted_scopes читает debug_token: пользователь может снять галочки в диалоге, поэтому проверяйте, что реально выдано.
Как проверить (отладить) токен Instagram?
Для токенов Facebook вызовите GET /debug_token?input_token=<токен> с маркером приложения ({app-id}|{app-secret}) или пользовательским токеном разработчика приложения. В ответе есть is_valid, expires_at, data_access_expires_at, scopes, granular_scopes (с целевыми объектами, например ID страниц) и user_id. То же показывает Access Token Debugger в инструментах разработчика Meta.
Для Instagram User token самая быстрая проверка — дешёвый запрос вроде GET graph.instagram.com/me?fields=user_id,username. Нормальный ответ — токен рабочий; ошибка 190 — пользователю нужно переподключиться.
Пишите в лог поля ошибки code, error_subcode и fbtrace_id, но никогда не сам токен. Поддержка Meta просит именно fbtrace_id.
Ошибка 190 и другие ошибки токена
| Код | Что означает | Что делать |
|---|---|---|
| 190 | Токен недействителен или истёк | Не повторять; пометить аккаунт отключённым и попросить войти заново |
| 190 / 458 | Пользователь не входил в приложение | Повторная авторизация |
| 190 / 459 | Аккаунт на checkpoint | Пользователь должен сначала войти на facebook.com |
| 190 / 460 | Сменён пароль | Попросить войти заново |
| 190 / 463 | Срок действия токена истёк | Повторная авторизация; в следующий раз обновлять раньше |
| 190 / 464 | Неподтверждённый пользователь | Подтвердить аккаунт на facebook.com |
| 190 / 467 | Недействительный токен | Получить новый токен через вход |
| 10, 200–299 | Нет разрешения или оно не одобрено | Исправить scope или App Review; повтор не поможет |
В Socialift SDK коды 190 и 102 выбрасывают AuthError, коды 10 и 200–299 — PermissionError; в обоих есть code и subcode из ответа Meta.
Как безопасно хранить токены Instagram
В кабинете Socialift OAuth-токены подключённых аккаунтов шифруются на сервере и не передаются в браузер. В своём бэкенде придерживайтесь тех же правил:
- Секрет приложения и все обмены токенов — только на сервере; секрет никогда не попадает в браузер или мобильное приложение.
- Храните токены в базе в зашифрованном виде вместе с expires_at.
- Не пишите токены в логи и трекеры ошибок — только ID аккаунта и fbtrace_id.
- Генерируйте случайный state на каждый вход и сверяйте его в callback — это защита от CSRF.
- Считайте
AuthErrorсменой состояния («нужно переподключить»), а не временной ошибкой для повтора. - При отключении аккаунта не только удаляйте запись, но и отзывайте разрешения на стороне Meta (для Facebook Login —
fb.revoke).
Частые вопросы
Сколько действует токен Instagram API?
В Instagram Login короткоживущий токен действует 1 час, долгоживущий — 60 дней, и каждое обновление даёт ещё 60 дней. В Facebook Login долгоживущий user token живёт около 60 дней, а полученный из него токен страницы бессрочный.
Можно ли обновить истёкший токен Instagram?
Нет. refresh_access_token работает только с долгоживущим токеном, которому не меньше 24 часов и который ещё действителен. Токен, не обновлённый за 60 дней, истекает окончательно — пользователь должен пройти вход заново.
Что означает ошибка 190 в Instagram API?
190 — это OAuthException: токен недействителен, истёк или отозван. Причину уточняет error_subcode (463 — истёк, 460 — сменён пароль, 458 — пользователь не входил в приложение). Повтор не поможет — нужен новый токен.
Почему Instagram User token не работает на graph.facebook.com?
Токены Instagram Login предназначены для graph.instagram.com, а Facebook Login использует токены пользователя и страницы на graph.facebook.com. Используйте хост, который соответствует потоку входа, выдавшему токен.
Нужен ли токен страницы для Instagram?
Только в Facebook Login. Там эндпоинты Instagram вызываются токеном страницы, к которой привязан аккаунт, а ID аккаунта Instagram берётся из поля instagram_business_account. Для Instagram Login страница не нужна вовсе.