Клиент Instagram: методы Graph API
Instagram — клиент Instagram Graph API в Python SDK Socialift. Он поддерживает два типа подключения: Instagram(app_id, app_secret) — Instagram Login без страницы Facebook, через graph.instagram.com; Instagram.via_facebook(app_secret=...) — токен страницы из Facebook Login, через graph.facebook.com. Клиент читает профиль и публикации, публикует фото, Reels, карусели и истории, модерирует комментарии, ведёт переписку в Direct и получает статистику.
from socialift import InstagramМетодов: 25по версии socialift 1.3.0Обновлено:
Как настроить клиент Instagram?
Подключение без страницы (Instagram Login): Instagram(app_id=..., app_secret=...). Instagram.from_env() берёт значения из INSTAGRAM_APP_ID и INSTAGRAM_APP_SECRET, а версию Graph API — из META_GRAPH_VERSION. Запросы идут на graph.instagram.com с токеном пользователя Instagram; если ig_user_id не передан, используется me. Ключи находятся в настройках Instagram в приложении Meta — см. руководство «Настройка Instagram Login».
Подключение через страницу: Instagram.via_facebook(app_secret=...). app_id здесь не нужен — OAuth проходит в клиенте Facebook. В качестве токена используется токен страницы из Facebook.pages(), а ID аккаунта — Page.instagram_id; в этом режиме ig_user_id обязателен, иначе будет ConfigurationError. Настройка приложения Meta описана в руководстве «Настройка приложения Meta».
В обоих режимах аккаунт должен быть профессиональным (Business или Creator). Если передан app_secret, к каждому запросу добавляется appsecret_proof. Ключи можно хранить в разделе кабинета «Ключи», аккаунт подключить в «Подключениях», а методы проверить в «Playground».
import asyncio
import os
from socialift import Instagram
async def main():
# 1) Instagram Login (без страницы), из окружения:
# INSTAGRAM_APP_ID, INSTAGRAM_APP_SECRET, META_GRAPH_VERSION
ig = Instagram.from_env()
# или: Instagram(app_id=os.environ["INSTAGRAM_APP_ID"],
# app_secret=os.environ["INSTAGRAM_APP_SECRET"])
# 2) Через страницу: токен страницы и Page.instagram_id
# ig = Instagram.via_facebook(app_secret=os.environ["FACEBOOK_APP_SECRET"])
async with ig:
profile = await ig.profile(os.environ["IG_TOKEN"])
print(profile.username, profile.followers_count)
asyncio.run(main())
Подключение и токены
Клиент в двух режимах, ссылка Instagram Login, обмен и обновление токена.
exchange_codefrom_envlogin_urlrefresh_tokenvia_facebook
exchange_code
asyncОбменивает code на краткосрочный токен в api.instagram.com (POST form-data), затем через ig_exchange_token — на долгосрочный и возвращает TokenBundle. Вызывается в callback Instagram Login.
await ig.exchange_code(code: str, *, redirect_uri: str) -> socialift.models.TokenBundle- По документации Meta краткосрочный токен действует 1 час, долгосрочный — 60 дней.
- В
redirect_uriпередайте ровно то же значение, что было в ссылке входа. - Если краткосрочный токен не получен, будет
ApiError.
from_env
classmethodСоздаёт клиент в режиме Instagram Login из окружения: INSTAGRAM_APP_ID, INSTAGRAM_APP_SECRET и META_GRAPH_VERSION. Для работы через страницу используйте via_facebook.
Instagram.from_env(**kwargs) -> Instagram- Конструктор не проверяет пустые ключи: отсутствие
app_idпроявится какConfigurationErrorпри вызовеlogin_url.
Формирует ссылку на диалог Instagram Login (https://www.instagram.com/oauth/authorize). Метод синхронный и запросов не отправляет.
ig.login_url(
*,
redirect_uri: str,
state: Optional[str] = None,
scopes: Optional[list[str]] = None,
) -> str- Scope по умолчанию:
instagram_business_basic,instagram_business_manage_messages,instagram_business_manage_comments,instagram_business_content_publish,instagram_business_manage_insights; сократите список черезscopes=. - Без
app_idбудетConfigurationError. - SDK не хранит
state: сгенерируйте случайное значение и сравните его в callback. - По документации Meta
codeиз callback действует 1 час и используется только один раз.
url = ig.login_url(redirect_uri="https://siz.uz/cb", state=state)refresh_token
asyncОбновляет долгосрочный токен пользователя Instagram через ig_refresh_token и возвращает новый TokenBundle. Запускайте регулярно по расписанию (cron), чтобы аккаунт не отвалился незаметно.
await ig.refresh_token(token: str) -> socialift.models.TokenBundle- Правило Meta: токену должно быть не меньше 24 часов, и он не должен быть истёкшим; обновлённый токен действует 60 дней с даты обновления.
- Только для токенов Instagram Login — при подключении через страницу используется токен страницы.
- Если токен не вернулся, будет
ApiError.
bundle = await ig.refresh_token(token)via_facebook
classmethodСоздаёт клиент для сценария Facebook Login: запросы идут на graph.facebook.com, в качестве токена ожидается токен страницы. app_id не нужен — OAuth проходит в клиенте Facebook, а секрет нужен для appsecret_proof.
Instagram.via_facebook(*, app_secret: str, **kwargs) -> Instagram- В методах профиля, медиа, статистики и публикации
ig_user_idобязателен (meздесь означает страницу); берите ID изPage.instagram_id. - В
conversationsиsend_messageобязателен такжеpage_id. login_url,exchange_codeиrefresh_tokenотносятся к Instagram Login и в этом режиме не используются.
Профиль и публикации
Профиль аккаунта, список публикаций и данные одной публикации.
media
asyncВозвращает список публикаций аккаунта в виде сырых словарей. limit — общее число публикаций; пагинацию SDK проходит сам.
await ig.media(
token: str,
*,
ig_user_id: Optional[str] = None,
limit: int = 25,
) -> list[dict]- Через страницу
ig_user_idобязателен. - Для одной публикации используйте
media_details.
Нужные разрешения:instagram_basic
posts = await ig.media(page_token, ig_user_id=ig_user_id, limit=25)media_details
asyncВозвращает данные одной публикации по media_id. publish возвращает только ID, поэтому permalink и остальные поля после публикации получайте этим методом.
await ig.media_details(media_id: str, token: str) -> dictНужные разрешения:instagram_basic
post = await ig.media_details(media_id, page_token)profile
asyncВозвращает профиль профессионального аккаунта в виде Profile: username, имя, фото, био, сайт, число подписчиков, подписок и публикаций. Нужен для отображения или синхронизации аккаунта после подключения.
await ig.profile(
token: str,
*,
ig_user_id: Optional[str] = None,
) -> socialift.models.Profile- Через страницу
ig_user_idобязателен; в этом режиме SDK не запрашиваетaccount_type, поэтому он будетNone. - Полный ответ — в
Profile.raw.
Нужные разрешения:instagram_basic
profile = await ig.profile(page_token, ig_user_id=ig_user_id)Публикация
Публикация фото, Reels и каруселей по публичным HTTPS-ссылкам.
publishpublish_carouselpublish_container
publish
asyncПубликует одно фото или видео: создаёт контейнер, для видео ждёт его готовности, затем вызывает media_publish. Возвращает {container_id, media_id}.
await ig.publish(
token: str,
*,
ig_user_id: Optional[str] = None,
caption: Optional[str] = None,
image_url: Optional[str] = None,
video_url: Optional[str] = None,
is_reel: bool = False,
share_to_feed: Optional[bool] = None,
wait_timeout: float = 300.0,
) -> dictimage_url/video_url— публичная HTTPS-ссылка: Meta сама скачивает файл; изображения только в JPEG.- Видео всегда уходит как
REELS— с 9 ноября 2023 года Meta не принимаетmedia_type=VIDEO.is_reelвыбирает только значениеshare_to_feedпо умолчанию. - Если контейнер видео не готов за
wait_timeout(по умолчанию 300 секунд) или получил статусERROR, будетContainerNotReadyError— передайте егоcontainer_idвpublish_container(). - Лимит Meta: до 100 публикаций через API за скользящие 24 часа на аккаунт (на части страниц Meta указывает 50) — точный остаток отдаёт
content_publishing_limit.
Нужные разрешения:instagram_content_publish
post = await ig.publish(page_token, ig_user_id=ig_user_id, caption="Yangi mahsulot",
image_url="https://cdn.siz.uz/photo.jpg")publish_carousel
asyncПубликует 2–10 изображений одной каруселью: дочерний контейнер на каждое фото (параллельно), затем контейнер CAROUSEL, ожидание готовности и публикация. Возвращает {container_id, media_id, children}.
await ig.publish_carousel(
token: str,
*,
ig_user_id: Optional[str] = None,
image_urls: Sequence[str],
caption: Optional[str] = None,
wait_timeout: float = 300.0,
) -> dict- Если ссылок больше 10, берутся первые 10; если меньше 2 —
ConfigurationError. - Принимаются только ссылки на изображения — публичные HTTPS и в формате JPEG.
- Если родительский контейнер не готов за
wait_timeout(по умолчанию 300 секунд), будетContainerNotReadyError— продолжите черезpublish_container().
publish_container
asyncПубликует ранее созданный контейнер: нужен, чтобы продолжить после ContainerNotReadyError из publish(), publish_carousel() или publish_story() без повторной загрузки файла.
await ig.publish_container(
token: str,
container_id: str,
*,
ig_user_id: Optional[str] = None,
wait_timeout: float = 300.0,
) -> dictcontainer_idберите из исключения (ContainerNotReadyError.container_id); метод дожидается готовности контейнера и вызываетmedia_publish.- Контейнер живёт 24 часа: если за это время его не опубликовать, он получает статус
EXPIREDи медиа придётся загружать заново. - Для длинного видео увеличьте
wait_timeout— Meta рекомендует опрашивать статус раз в минуту и не дольше 5 минут.
Истории (Stories)
Публикация истории и список активных историй. История живёт 24 часа, подписи у неё нет.
publish_story
asyncПубликует фото или видео как историю (Stories). Поток тот же, что у publish() (контейнер → ожидание → media_publish), отличие одно: в контейнер добавляется media_type=STORIES. Возвращает {container_id, media_id}.
await ig.publish_story(
token: str,
*,
ig_user_id: Optional[str] = None,
image_url: Optional[str] = None,
video_url: Optional[str] = None,
wait_timeout: float = 300.0,
) -> dictcaptionздесь нет намеренно: история — не пост в ленте, текст подписи в ней не показывается. Нужный текст должен быть вшит в само фото или видео.- Передаётся ровно один из
image_urlиvideo_url— публичная HTTPS-ссылка, как вpublish()(файл скачивает сама Meta). Если переданы оба, будетConfigurationError. - Требования Meta (SDK их не проверяет): фото — JPEG до 8 МБ, рекомендуемое соотношение 9:16; видео — MOV или MP4, 3–60 секунд, до 100 МБ, кодек H264 или HEVC, звук AAC 48 кГц.
- Если контейнер видео не готов за
wait_timeout(по умолчанию 300 секунд), будетContainerNotReadyError; продолжить можно черезpublish_container()с егоcontainer_id. - История тоже публикуется через
media_publish, то есть входит в суточный лимит публикаций. В самой документации Meta это число на разных страницах отличается — узнавайте остаток запросомGET /{ig-user-id}/content_publishing_limit. - Опубликованная история исчезает через 24 часа (архива и «актуального» в API нет). В эти 24 часа работают
media_details()иmedia_insights(); что это история, показываетmedia_product_type == "STORY". - Разрешения: для Instagram Login —
instagram_business_basicиinstagram_business_content_publish; для Facebook Login —instagram_basic,instagram_content_publishиpages_read_engagement.
Нужные разрешения:instagram_content_publishpages_read_engagement
story = await ig.publish_story(page_token, ig_user_id=ig_user_id,
image_url="https://cdn.siz.uz/story.jpg")stories
asyncВозвращает истории аккаунта, активные прямо сейчас. Истории не попадают в edge media — для них у Meta отдельный edge stories, поэтому это отдельный метод.
await ig.stories(
token: str,
*,
ig_user_id: Optional[str] = None,
limit: int = 25,
) -> list[dict]- Работает только в сценарии Facebook Login: в документации Meta этот edge помечен «Instagram API with Facebook Login only». В клиенте Instagram Login метод выбрасывает
ConfigurationError, не отправляя запрос, — официального способа получить список активных историй там нет. - Видны только последние 24 часа: архива и «актуального» в API нет вовсе.
- Каждая запись — объект IG Media;
media_typeи для истории равенIMAGE/VIDEO, а историю выдаётmedia_product_type == "STORY"— SDK запрашивает это поле принудительно. - Ограничения Meta: истории прямых эфиров не возвращаются; новая история, созданная репостом чужой, в список не попадает; если у истории несколько подписей, вернётся одна.
- Разрешения (Facebook Login):
instagram_basicиpages_read_engagement.
Нужные разрешения:instagram_basicpages_read_engagement
stories = await ig.stories(page_token, ig_user_id=ig_user_id, limit=25)Комментарии
Чтение, ответы, скрытие и удаление комментариев.
commentsdelete_commenthide_commentreply_comment
delete_comment
asyncУдаляет комментарий через DELETE /{comment_id}. Действие необратимо — часто достаточно hide_comment.
await ig.delete_comment(comment_id: str, token: str) -> dictНужные разрешения:instagram_manage_comments
await ig.delete_comment(comment_id, page_token)hide_comment
asyncСкрывает комментарий (hide=true) или снова показывает его при hidden=False. Обратимая альтернатива удалению.
await ig.hide_comment(comment_id: str, token: str, hidden: bool = True) -> dictНужные разрешения:instagram_manage_comments
await ig.hide_comment(comment_id, page_token, hidden=True)reply_comment
asyncОтвечает на комментарий от имени аккаунта (POST /{comment_id}/replies) и возвращает id нового комментария.
await ig.reply_comment(comment_id: str, token: str, message: str) -> dictНужные разрешения:instagram_manage_comments
await ig.reply_comment(comment_id, page_token, "Rahmat!")Сообщения Direct
Диалоги, история сообщений, профиль собеседника и отправка сообщений.
contactconversationsmessagessend_message
contact
asyncВозвращает профиль собеседника (User Profile API) по IGSID. При ошибке исключение не выбрасывается: возвращается {id, available: False, reason}, при успехе добавляется available: True.
await ig.contact(igsid: str, token: str) -> dict- Правило Meta: профиль доступен только после согласия пользователя — если он написал бизнесу, нажал icebreaker или пункт постоянного меню. Профиль человека, который только оставил комментарий, получить нельзя.
- По документации Meta ссылка
profile_picистекает через несколько дней — не кешируйте её надолго.
Нужные разрешения:instagram_manage_messages
contact = await ig.contact(igsid, page_token)conversations
asyncВозвращает список диалогов Direct в виде {data, paging}: в каждом contact (клиент), contacts, last_message, updated_time. При enrich=True профиль каждого собеседника параллельно запрашивается через User Profile API.
await ig.conversations(
token: str,
*,
ig_user_id: Optional[str] = None,
page_id: Optional[str] = None,
limit: int = 25,
after: Optional[str] = None,
enrich: bool = True,
) -> dict- Возвращается одна страница: для следующей передайте курсор из
pagingвafter=. - Через страницу
page_idобязателен, к запросу добавляетсяplatform=instagram; в Instagram Login вызывается/me/conversations. ig_user_idиpage_idнужны, чтобы отделить бизнес от клиента, — передавайте их, иначе вcontactможет попасть сам бизнес.- Ограничение Meta: доступны детали только 20 последних сообщений диалога; диалоги из папки «Запросы», неактивные 30 дней, не возвращаются.
Нужные разрешения:instagram_manage_messages
chats = await ig.conversations(page_token, page_id=page_id, ig_user_id=ig_user_id)
for chat in chats["data"]:
print(chat["contact"]["name"])messages
asyncЧитает сообщения одного диалога из edge messages и возвращает ответ Graph API (data, paging). Для следующей страницы передайте курсор after.
await ig.messages(
conversation_id: str,
token: str,
*,
limit: int = 50,
after: Optional[str] = None,
) -> dict- Ограничение Meta: детали доступны только для 20 последних сообщений; на более старое вернётся ошибка, что сообщение удалено.
Нужные разрешения:instagram_manage_messages
history = await ig.messages(conversation_id, page_token, limit=50)send_message
asyncОтправляет текстовое сообщение в Direct (POST /{id}/messages, recipient.id — IGSID). Нужен для ответа клиенту, пришедшему из вебхука или conversations.
await ig.send_message(
recipient_id: str,
token: str,
text: str,
*,
ig_user_id: Optional[str] = None,
page_id: Optional[str] = None,
) -> dict- Окно 24 часа: Meta разрешает ответить в течение 24 часов после сообщения клиента, потом отклоняет запрос (в SDK —
PermissionError). - Требование Meta: текст в UTF-8 и не длиннее 1000 байт.
- Через страницу
page_idобязателен; в Instagram Login используетсяig_user_idилиme. - Только текст: изображений, шаблонов и тегов сообщений в этом методе нет.
Нужные разрешения:instagram_manage_messages
await ig.send_message(recipient_id, page_token, "Salom!", page_id=page_id)Подписка на вебхуки
Подписка аккаунта на вебхуки приложения в сценарии Instagram Login.
subscribe_account
asyncПодписывает аккаунт на вебхуки приложения в сценарии Instagram Login (subscribed_apps) и возвращает bool. Даже при настроенном в App Dashboard вебхуке события комментариев и Direct не приходят, пока аккаунт не подписан.
await ig.subscribe_account(
token: str,
*,
ig_user_id: Optional[str] = None,
fields: Optional[Sequence[str]] = None,
) -> bool- Вызывайте сразу после
exchange_code()— иначе первые события будут потеряны. - Без
fieldsотправляется список по умолчанию:comments,messages,messaging_postbacks,message_reactions. - Для аккаунта, подключённого через страницу, метод не используется: там подписка оформляется на странице (
Facebook.subscribe_page), и события IG приходят через неё. В этом режиме метод выбрасываетConfigurationError.
Статистика
Метрики аккаунта, демография подписчиков и статистика публикаций.
demographicsinsightsmedia_insights
demographics
asyncВозвращает демографию подписчиков в разрезах age,gender, city и country (follower_demographics, timeframe=this_month). Каждый разрез — отдельный запрос: если один не сработал, остальные всё равно вернутся.
await ig.demographics(token: str, *, ig_user_id: Optional[str] = None) -> dict- Результат:
{разрез: {available, values}};values— плоский словарь с ключами вида25-34 / F, при ошибке —available: Falseиreason. - Правило Meta: для аккаунтов с менее чем 100 подписчиками демография не возвращается.
Нужные разрешения:instagram_manage_insights
demo = await ig.demographics(page_token, ig_user_id=ig_user_id)insights
asyncВозвращает суммарные метрики аккаунта за период в виде {since, until, metrics}. SDK запрашивает reach, profile_views, website_clicks, accounts_engaged и total_interactions с period=day и metric_type=total_value.
await ig.insights(
token: str,
*,
ig_user_id: Optional[str] = None,
since: Optional[datetime.date] = None,
until: Optional[datetime.date] = None,
) -> dict[str, Any]- Период ограничивается в SDK:
untilв будущем сдвигается на сегодня, безsinceберутся последние 30 дней, период длиннее 30 дней обрезается. - Meta убрала
profile_viewsиwebsite_clicksиз метрик аккаунта для всех версий с 8 января 2025 года. Если Graph API отклонит такой запрос, будетApiError. - По документации Meta данные могут запаздывать до 48 часов.
Нужные разрешения:instagram_manage_insights
stats = await ig.insights(page_token, ig_user_id=ig_user_id)media_insights
asyncВозвращает статистику одной публикации как {метрика: значение}. Набор зависит от типа: reach, likes, comments, saved, shares, total_interactions; для фото добавляется profile_visits, для видео и Reels — views, для Stories — reach, replies, navigation, total_interactions.
await ig.media_insights(media_id: str, token: str) -> dict[str, Any]- При ошибке API исключение не выбрасывается — возвращается
{}. - Правила Meta: метрики Stories доступны только 24 часа; для отдельных элементов внутри альбома (карусели) статистики нет.
Нужные разрешения:instagram_manage_insights
stats = await ig.media_insights(media_id, page_token)Общие методы всех клиентов
У каждого HTTP-клиента (Telegram, Facebook, Instagram, LinkedIn, TikTok, Ads) есть эти низкоуровневые методы: чтобы вызвать эндпоинт, для которого в SDK ещё нет обёртки, или читать данные постранично. По завершении блока async with соединение закрывается автоматически.
request
asyncОтправляет произвольный HTTP-запрос и возвращает JSON-ответ — для эндпоинта, у которого в SDK пока нет отдельного метода. Токен и параметры подписи (access_token, для Meta — appsecret_proof через socialift.crypto.appsecret_proof) вы передаёте сами в params или headers.
await ig.request(
method: str,
url: str,
*,
params: Optional[Mapping[str, Any]] = None,
data: Optional[Any] = None,
json: Optional[Any] = None,
headers: Optional[Mapping[str, str]] = None,
) -> Any- Значения
Noneвparamsне отправляются. - При лимите (
RateLimitError) и временных ошибках сервера (HTTP 429, 500, 502, 503, 504) запрос повторяется поRetryPolicy; если есть заголовокRetry-After, SDK ждёт указанное время. Обрыв сети выбрасывается какTransportError.
get
asyncКороткая форма request("GET", ...).
await ig.get(url: str, **kw) -> Anypost
asyncКороткая форма request("POST", ...).
await ig.post(url: str, **kw) -> Anydelete
asyncКороткая форма request("DELETE", ...).
await ig.delete(url: str, **kw) -> Anypaginate
asyncПроходит по курсорной пагинации Meta (paging.next) и возвращает все элементы data одним списком.
await ig.paginate(
url: str,
*,
params: Optional[Mapping[str, Any]] = None,
max_items: int = 500,
page_size: int = 100,
) -> list[dict]max_items(по умолчанию 500) — защитный предел: у крупного аккаунта могут быть десятки тысяч записей.page_size—limitодного запроса.
close
asyncЗакрывает HTTP-сессию, созданную самим SDK (переданную извне сессию не трогает). При использовании async with Client(...) вызывается автоматически.
await ig.close() -> NoneЧастые вопросы
Нужна ли страница Facebook для Instagram API?
Не обязательно. Через Instagram Login (Instagram(app_id, app_secret)) профессиональный аккаунт подключается без страницы. Путь через Facebook Login (Instagram.via_facebook) требует аккаунт, привязанный к странице, и токен страницы. В обоих случаях аккаунт должен быть Business или Creator.
Сколько действует токен Instagram и как его обновить?
По документации Meta в Instagram Login краткосрочный токен действует 1 час, долгосрочный — 60 дней; exchange_code сразу возвращает долгосрочный. refresh_token обновляет токен, которому не меньше 24 часов и срок которого не истёк, — новый снова действует 60 дней. Запускайте обновление регулярно по расписанию.
Почему не получается отправить сообщение клиенту в Instagram Direct?
Правило Meta: ответить на сообщение пользователя можно в течение 24 часов, после этого запрос отклоняется. Кроме того, текст должен быть в UTF-8 и не длиннее 1000 байт. При подключении через страницу передайте в send_message ещё и page_id.
Как опубликовать видео или Reels в Instagram через API?
Вызовите publish(token, video_url=...). Видео должно лежать по публичной HTTPS-ссылке — Meta сама скачивает файл, а SDK ждёт готовности контейнера до wait_timeout (по умолчанию 300 секунд). С 9 ноября 2023 года Meta не принимает media_type=VIDEO, поэтому SDK всегда отправляет видео как REELS. Параметр is_reel теперь задаёт только значение share_to_feed по умолчанию: False — Reels попадает и в ленту, True — как у Meta. Для точного контроля укажите share_to_feed сами.
Можно ли опубликовать историю (Stories) в Instagram через API?
Да. publish_story(token, ig_user_id=..., image_url=...) создаёт контейнер с media_type=STORIES и публикует его — это работает в обоих сценариях подключения. Подписи у истории нет: нужный текст должен быть вшит в само фото или видео. Требования Meta: фото в JPEG до 8 МБ, видео 3–60 секунд. Через 24 часа история исчезает, архива и «актуального» в API нет. А вот stories() со списком активных историй работает только через Facebook Login: Meta пометила этот edge как «Instagram API with Facebook Login only».
Сколько постов в день можно публиковать через Instagram API?
По документации Meta один аккаунт может опубликовать через API до 100 постов за скользящие 24 часа, но на других страницах Meta указывает 50 — поэтому остаток лучше узнавать запросом GET /{ig-user-id}/content_publishing_limit. Истории входят в тот же лимит. Карусель содержит до 10 элементов; publish_carousel в SDK принимает от 2 до 10 изображений.
comments
asyncВозвращает комментарии к публикации списком сырых словарей.
limit— общее число комментариев, пагинация автоматическая.instagram_basic,instagram_manage_commentsиpages_read_engagement, для Instagram Login —instagram_business_basicиinstagram_business_manage_comments.Нужные разрешения:
instagram_manage_comments