Post to Instagram via API in 2026: No Facebook App Review Headaches
Instagram publishing via the Graph API requires Facebook Business verification, app review, and page linking. Here's what the native path involves — and how to skip it with a unified publishing API.
Instagram’s publishing barrier
Instagram has 2 billion monthly active users. It is the default platform for visual content, product launches, and brand storytelling. It is also one of the most restrictive platforms for programmatic publishing.
To post to Instagram via API, you need a Facebook account, a Facebook Business account, a Facebook Page, an Instagram professional account linked to that Page, a Meta developer app, and approval through Meta’s app review process — with a separate submission for each publishing permission.
Every one of these is a hard prerequisite. You cannot skip any of them.
This guide covers what the native Instagram API path involves, where it breaks down, and how developers bypass it with a unified social media publishing API.
Why the setup is this complicated
Meta’s Instagram Graph API was designed for businesses and agencies managing professional accounts, not for individual developers or lightweight automation. That design choice permeates the entire integration.
The key consequences:
Personal accounts are excluded. The Instagram publishing API only works with Professional accounts (Business or Creator). If a user has a standard personal Instagram account, they cannot use a third-party publishing app — they must first convert to a professional account and link it to a Facebook Page.
App review is mandatory for production use. Before your app can publish on behalf of accounts you do not own, Meta requires formal app review. Each permission needs its own submission. The review involves a screencast showing how your app uses that specific permission in context.
The review takes weeks. Meta’s documented timeline is 2–4 weeks per submission. If your submission is rejected — for missing context in the screencast, for an unclear use case, or for a UX issue Meta flags — you fix it and submit again.
For developers building their own automation on their own Instagram account, the setup is a one-time annoyance. For developers building a product where other users connect their Instagram accounts, the friction compounds: every user needs a professional account and a linked Facebook Page before they can connect.
The permissions you need
Publishing to Instagram requires two permissions approved through app review:
instagram_business_basic— Access basic profile information. Required before other permissions can be used.instagram_business_content_publish— Create media containers and publish them to the account.
Each requires a separate screencast submission. The screencast must show the complete user journey: how a user connects their Instagram account, how your app requests the permission, and what happens when the permission is used.
If your app publishes on behalf of accounts you do not own (which is most use cases), you need Advanced Access. Advanced Access has additional requirements: a detailed explanation of your use case, your data handling practices, and your privacy policy.
During the review period, your app is in development mode. In development mode, only accounts explicitly listed as test users in your Meta app dashboard can connect and use the app. You cannot onboard real users until review is approved.
The four-step setup for your users
Before a user can connect their Instagram account to any third-party publishing app, they need:
- A Facebook account. Instagram API access flows through Meta’s authentication. No Facebook account, no API access.
- A Facebook Page. The Instagram account must be linked to a Facebook Page. Business accounts without a Page cannot use the publishing API.
- An Instagram Professional account. The account must be set to Business or Creator in Instagram settings. Personal accounts are excluded from the API entirely.
- Page linking. In Instagram settings, the professional account must be connected to the Facebook Page.
If any of these are missing, the OAuth connection will fail or return limited permissions. This user setup requirement affects onboarding: you need to guide users through this process or document it clearly.
How the Instagram Graph API actually publishes
Once permissions are approved, posting to Instagram is a two-step process:
Step 1: Create a media container
POST to /{ig-user-id}/media:
{ "image_url": "https://example.com/photo.jpg", "caption": "Caption text #hashtag @mention"}Returns a container ID on success. If the container is not published within 24 hours, it expires.
Step 2: Publish the container
POST to /{ig-user-id}/media_publish:
{ "creation_id": "<CONTAINER_ID>"}Returns the published media ID.
If the publish does not return a media ID, check the container status: GET /{ig-container-id}?fields=status_code. Status values: IN_PROGRESS, FINISHED, PUBLISHED, EXPIRED, ERROR.
Format restrictions that will catch you
Instagram’s format requirements are stricter than most platforms and will surface as API validation errors if you do not handle them:
Images: JPEG only. No PNG, no WebP, no GIF. If you send a PNG URL, you get an error. Extended JPEG formats (MPO, JPS) are also unsupported.
Image aspect ratio: Feed posts must be between 4:5 (portrait) and 1.91:1 (landscape). Square (1:1) is fine. If your image is outside this range, the container creation will fail.
Videos: MP4 format. H.264 codec recommended. Videos must be 3–60 seconds for feed posts. Reels support up to 15 minutes.
Captions: Up to 2,200 characters. Hashtags and @mentions work inline. No markdown formatting. Instagram does not support bold or italic text in captions via API.
Daily limit: 100 API-published posts per 24-hour rolling period per account. Carousels count as one post.
Carousels, Reels, and Stories
All three use the same container model with different media_type values and slightly different steps.
Carousels (2–10 images or videos):
- Create a container for each item with
is_carousel_item: true - Create a parent container with
media_type: CAROUSELand the comma-separated list of item container IDs - Publish the parent container
Note: all carousel images are cropped to match the aspect ratio of the first image. If your first image is 1:1 and the rest are 4:5, the 4:5 images will be cropped to 1:1.
Reels:
- Create container with
media_type: REELSandvideo_url - Optionally set
share_to_feed: trueto also show in the main feed - Publish container
Stories:
- Create container with
media_type: STORIES - Publish container
Stories expire after 24 hours. There is no API to extend or archive them.
For large videos, use the resumable upload flow through rupload.facebook.com instead of a URL reference. The Instagram API integration guide has the full upload flow details.
The instagram_character_limit and other content rules
Instagram captions max out at 2,200 characters. The first 125 characters show without truncation in the feed; users must tap to expand the rest.
The practical character limit for algorithmic reach is shorter — most high-performing Instagram captions are under 300 characters. But 2,200 is the API hard limit.
For hashtags: Instagram allows up to 30 hashtags per post. Hashtags beyond 30 are ignored. Hashtag-only or hashtag-heavy captions have historically had reduced reach — adding them at the end of a substantive caption is common practice.
Publishing to Instagram without the friction
Postproxy maintains Instagram permissions through Meta’s app review. When a user connects their Instagram account to Postproxy via OAuth, they publish through Postproxy’s approved app — not through a review process you need to manage.
The publishing request is the same as any other platform:
curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "post": { "body": "3 things we learned shipping this feature." }, "profiles": ["instagram"], "media": ["https://example.com/photo.jpg"] }'For carousels, pass multiple items in the media array:
curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "post": { "body": "A thread of lessons from six months of building in public." }, "profiles": ["instagram"], "media": [ "https://example.com/slide1.jpg", "https://example.com/slide2.jpg", "https://example.com/slide3.jpg" ] }'To publish the same content to Instagram and other platforms simultaneously:
curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "post": { "body": "We just launched. Here is what we built." }, "profiles": ["instagram", "threads", "linkedin"], "media": ["https://example.com/photo.jpg"] }'What Postproxy handles for Instagram:
instagram_business_content_publishand related permissions approved through Meta app review- Instagram User access token exchange and 60-day token refresh
- The two-step container creation and publish flow
- Resumable video uploads via
rupload.facebook.com - Images, videos, carousels, Reels, and Stories
- Container status polling when needed
- Rate limit monitoring (100 posts per 24h) and request pacing
Your account still needs to be an Instagram Professional account linked to a Facebook Page — that is a Meta requirement that no third-party can waive. But the app review process, the permission management, and the API implementation are handled by Postproxy.
Connect your Instagram account and start publishing through the Postproxy API. For the complete technical reference on Instagram’s Graph API, see the Instagram API integration guide. For publishing across all platforms from a single API, see the social media API developer guide.