Quick reference
| Limit / capability | Value |
|---|---|
| Caption character limit | 2,200 graphemes |
| Items per carousel | 2 – 10 (mixed image + video allowed) |
| Image format | JPEG only (PNG, WebP, HEIC, GIF rejected by Meta) |
| Image size | 8,000,000 bytes (8 MB) |
| Video formats | mp4, mov |
| Video size | 1,000,000,000 bytes (1 GB) |
| Reels duration | ≤ 90 s (platform-enforced) |
| Alt text per item | 2,200 graphemes |
| Post types supported | single image, single video (Reels), carousel |
| Text-only post | Not supported — every post requires media |
| Scheduling | Yes (via scheduledAt) |
| Reply / thread support | Not supported in v1 |
| First comment | Not supported in v1 |
| Story | Not supported in v1 |
| Inbox / DM | Not supported in v1 |
| Analytics | Not supported in v1 |
Connect an account
Instagram has its own OAuth (since the 2024 Instagram Login product) — distinct from Facebook Login. There is no FB fan-out anymore; connecting Instagram does not also connect Facebook.POST /v1/accounts/connect/instagram produces an authorize URL at instagram.com/oauth/authorize. After the user grants, the callback runs three Graph calls:
- Exchange
code→ short-lived token (1 h). - Swap short-lived → long-lived (60 d).
GET /me?fields=id,user_id,username,account_type— the Content Publishing API expectsid(the IG-scoped user id), notuser_id— the provider persistsidasplatformAccountId. Ifaccount_type === "PERSONAL"the connect is rejected.
Scopes
extended scopes (off by default) cover comment + insight reads — not required for publishing.
Token lifecycle
Long-lived tokens last 60 days and are refreshable any time after the first 24 hours viaGET /refresh_access_token. The provider refreshes on schedule; token.expiring fires before expiry.
Post types
Single image
single-image.json
Single video (Reels)
Single-video posts route through theREELS container — Instagram retired the legacy VIDEO product surface in 2024.
reels.json
Carousel (2 – 10, mixed)
Carousel children can mix image and video items.carousel.json
is_carousel_item=true), polls each to FINISHED, then creates a CAROUSEL parent with the child ids and publishes the parent.
Wisdom (platform-specific things that bite)
Common errors
| Error rule | What it means | How to fix |
|---|---|---|
instagram.media.required | No media on the post | Attach at least one image or video; Instagram has no text-only feed surface. |
instagram.text.max_graphemes | Caption > 2,200 graphemes | Trim under 2,200. |
instagram.media.count_max | More than 10 items in a carousel | Reduce to ≤10, or split into multiple posts. |
instagram.media.mime_allowed | Image isn’t JPEG, or video isn’t mp4/mov | Re-encode to JPEG (images) or mp4/mov (video). |
instagram.media.image_size_max | Image > 8 MB | Compress under 8,000,000 bytes. |
instagram.media.video_size_max | Video > 1 GB | Compress under 1,000,000,000 bytes. |
instagram.container.expired | Container aged past Instagram’s 24 h window | Re-create and publish in one flow. |
instagram.account_type.requires_professional | Connect attempted with a PERSONAL account | Switch the IG account to Business or Creator in-app, then reconnect. |
What you can’t do (yet)
- Stories (Stories use a separate
STORIEScontainer type not in v1). - Direct messages.
- First comment as the author.
- Tagging users or product tags.
- Editing or deleting a published post.
- Posting from a Personal Instagram account (Meta’s API restriction — switch to Business or Creator).
- Reading comments, replies, or insights (requires
extendedscopes plus read endpoints not in v1).
API reference
POST /v1/posts— primary publish.POST /v1/media— upload images/videos formediaIdreferences.POST /v1/accounts/connect/instagram— start an Instagram OAuth flow.

