Instagram Content Publishing API: публикация фото, Reels и каруселей
Публикация через Instagram API — это два вызова: POST /<IG_ID>/media создаёт медиаконтейнер, POST /<IG_ID>/media_publish его публикует. Meta скачивает файл по публичному URL в момент попытки, а изображения принимаются только в JPEG. Каждый аккаунт может опубликовать через API 100 постов за скользящие 24 часа; карусель считается одним постом.
Опубликовано: Обновлено:
Как работает публикация через Instagram API?
В стандартной схеме файл не передаётся в теле запроса. Сначала создаётся контейнер со ссылкой на медиа по публичному URL — Meta сама скачивает и обрабатывает файл. Когда status_code контейнера становится FINISHED, вы публикуете его через media_publish и получаете ID медиа в Instagram. Видео обрабатывается не сразу, поэтому его статус нужно опрашивать. Для больших видео есть и resumable upload.
Схема одинакова для обоих вариантов подключения. Instagram Login обращается к graph.instagram.com с Instagram User token, Facebook Login — к graph.facebook.com с токеном страницы и ID аккаунта Instagram, полученным со страницы.
Публиковать могут только профессиональные аккаунты. Отметки товаров (shopping tags) и фильтры через API не поддерживаются.
Разрешения и токен для публикации
| Instagram Login | Facebook Login | |
|---|---|---|
| Хост | graph.instagram.com | graph.facebook.com |
| Токен | Instagram User access token | Page access token |
| Разрешения | instagram_business_basic, instagram_business_content_publish | instagram_basic, instagram_content_publish, pages_read_engagement |
| Если роль на странице выдана через Business Manager | нет | Дополнительно ads_management, ads_read |
| Уровень доступа | Standard для своих аккаунтов; Advanced (App Review) для чужих | Standard для своих аккаунтов; Advanced (App Review) для чужих |
естьнет
Поддерживаемые типы медиа и требования
| Тип | Как создать контейнер | Ключевые требования |
|---|---|---|
| Фото | image_url | Только JPEG (MPO и JPS не поддерживаются), до 8 МБ, соотношение сторон от 4:5 до 1.91:1 |
| Reels | media_type=REELS + video_url | От 3 секунд до 15 минут, до 300 МБ, H.264 или HEVC, 23–60 fps; share_to_feed управляет показом в ленте |
| Карусель | Дочерние контейнеры с is_carousel_item=true, затем media_type=CAROUSEL + children | До 10 фото, видео или их смеси; в лимите считается одним постом |
| История | media_type=STORIES + URL фото или видео | Исчезает через 24 часа; стикеры ссылки, опроса и места не поддерживаются; в документации Facebook Login — только для бизнес-аккаунтов |
Примечания и ограничения
Подпись: до 2200 символов, 30 хештегов и 20 @-упоминаний. Фотопосты принимают alt_text (с 24 марта 2025 года; не для Reels и историй), а с 22 июня 2026 года параметр is_ai_generated=true добавляет метку AI info. media_type=VIDEO не поддерживается с 9 ноября 2023 года — одиночное видео публикуется как REELS.
Как опубликовать пост через Instagram API: пошагово
Разместите медиа публично
Положите файл по публичному HTTPS-адресу без авторизации. Meta скачивает медиа через cURL в момент попытки публикации, поэтому ссылка должна работать именно тогда.
Создайте контейнер
POST /<IG_ID>/media с image_url (или media_type=REELS и video_url) и необязательной подписью caption. В ответе — ID контейнера.
Дождитесь обработки
Для видео и каруселей запрашивайте GET /<CONTAINER_ID>?fields=status_code, пока не будет FINISHED. Meta рекомендует проверять не чаще раза в минуту и не дольше 5 минут.
Опубликуйте
POST /<IG_ID>/media_publish с creation_id=<CONTAINER_ID>. ID в ответе — это ID опубликованного медиа Instagram.
Прочитайте результат
Запросите поля медиа по новому ID (например, permalink) и сохраните ссылку на пост.
Как выглядят «сырые» запросы
Вызовы на уровне платформы с хостом Instagram Login. Для Facebook Login замените хост на graph.facebook.com, а токен — на токен страницы.
# 1. Контейнер для JPEG-изображения
curl -X POST "https://graph.instagram.com/v23.0/$IG_ID/media" \
-H "Authorization: Bearer $IG_TOKEN" \
-d "image_url=https://cdn.example.com/photo.jpg" \
--data-urlencode "caption=Новая коллекция"
# -> {"id": "<CONTAINER_ID>"}
# 2. Проверка статуса (для видео и каруселей)
curl -G "https://graph.instagram.com/v23.0/$CONTAINER_ID" \
-H "Authorization: Bearer $IG_TOKEN" -d "fields=status_code"
# 3. Публикация
curl -X POST "https://graph.instagram.com/v23.0/$IG_ID/media_publish" \
-H "Authorization: Bearer $IG_TOKEN" -d "creation_id=$CONTAINER_ID"Публикация через Socialift SDK
import asyncio, os
from socialift import Instagram
CDN = "https://cdn.example.com"
async def main():
token = os.environ["IG_USER_TOKEN"]
async with Instagram.from_env() as ig:
photo = await ig.publish(token, image_url=f"{CDN}/photo.jpg", caption="Новая коллекция")
reel = await ig.publish(token, video_url=f"{CDN}/teaser.mp4", is_reel=True, caption="За кадром")
album = await ig.publish_carousel(
token, image_urls=[f"{CDN}/1.jpg", f"{CDN}/2.jpg", f"{CDN}/3.jpg"], caption="Лукбук"
)
post = await ig.media_details(photo["media_id"], token)
print(post.get("permalink"), reel["media_id"], len(album["children"]))
asyncio.run(main())publish создаёт контейнер и публикует его, возвращая container_id и media_id. Для видео метод опрашивает status_code каждые 2 секунды до 60 секунд и выбрасывает ApiError при ERROR или по таймауту — для длинных Reels может понадобиться собственный повтор в фоновой задаче.
Для видео всегда передавайте is_reel=True: Meta больше не принимает media_type=VIDEO.
publish_carousel параллельно создаёт дочерние контейнеры, ждёт готовности родительского и публикует. Принимает только URL изображений, оставляет первые 10 и выбрасывает ConfigurationError, если их меньше 2.
Для Facebook Login используйте Instagram.via_facebook(app_secret=...), токен страницы и ig_user_id=. Истории, alt_text, share_to_feed и видео в карусели не входят в параметры этих методов — для них вызывайте Graph API напрямую.
Сколько постов в сутки можно опубликовать через API?
Аккаунты Instagram ограничены 100 публикациями через API за скользящие 24 часа, карусель считается одним постом. Сброса в полночь нет: окно сдвигается непрерывно.
Текущий расход показывает GET /<IG_ID>/content_publishing_limit. В ответе есть quota_usage (сколько постов опубликовано в окне) и объект config с quota_total и quota_duration; необязательный параметр since принимает Unix-время не старше 24 часов. Не зашивайте число в код — читайте quota_total из ответа.
У контейнеров свой потолок: аккаунт может создать 400 контейнеров за скользящие 24 часа. Неопубликованный контейнер истекает через 24 часа, поэтому не создавайте их сильно заранее.
Коды статуса контейнера
| status_code | Что означает | Что делать |
|---|---|---|
| IN_PROGRESS | Контейнер ещё обрабатывается | Проверить позже |
| FINISHED | Контейнер готов к публикации | Вызвать media_publish |
| PUBLISHED | Медиа контейнера уже опубликовано | Не публиковать повторно |
| ERROR | Обработка не удалась | Сверить медиа с требованиями и создать новый контейнер |
| EXPIRED | Не опубликован в течение 24 часов | Создать новый контейнер |
Частые ошибки публикации и как их избежать
- URL требует авторизации, редиректит на страницу входа или истёк (подписанные ссылки) — Meta не может скачать файл.
- Изображение в PNG, WebP или другом формате — сначала конвертируйте в JPEG.
- Соотношение сторон вне диапазона 4:5–1.91:1 — обрежьте перед загрузкой.
- media_publish вызван до того, как контейнер видео или карусели стал FINISHED.
- Отправлен media_type=VIDEO — для одиночного видео используйте REELS.
- В карусели больше 10 элементов или подпись длиннее 2200 символов, 30 хештегов или 20 упоминаний.
- Массовый импорт упёрся в окно 100 постов — сначала проверьте content_publishing_limit.
- Ожидание shopping tags, фильтров или стикеров в историях — API их не поддерживает.
Частые вопросы
Сколько постов в сутки можно публиковать через Instagram API?
Один аккаунт может опубликовать через API 100 постов за скользящие 24 часа, карусель считается одним постом. Текущий расход и значение лимита возвращает GET /<IG_ID>/content_publishing_limit.
Можно ли публиковать истории Instagram через API?
Да, через контейнер с media_type=STORIES. Стикеры ссылки, опроса и места не поддерживаются, а в документации Meta по Facebook Login публикация историй доступна только бизнес-аккаунтам. В Socialift SDK для этого есть отдельный метод — publish_story() (с версии 1.3.0); publish() публикует только в ленту.
Можно ли смешивать фото и видео в карусели?
Да, карусель принимает до 10 фото, видео или их смесь; каждый элемент — отдельный контейнер с is_carousel_item=true. Метод publish_carousel в SDK при этом работает только с изображениями.
Почему Instagram отклоняет моё изображение?
Чаще всего дело в формате: принимается только JPEG до 8 МБ с соотношением сторон от 4:5 до 1.91:1. Вторая частая причина — URL закрыт или не работал в момент публикации, ведь Meta скачивает файл именно тогда.
Можно ли запланировать пост через Instagram API?
Задокументированная схема публикует пост в момент вызова media_publish, поэтому отложенный постинг обычно реализуют в своём бэкенде через очередь или cron. Контейнер истекает через 24 часа — создавайте его ближе ко времени публикации.