You can use the Content Publishing API to publish single images, videos, reels (i.e., single media posts), or posts containing multiple images and videos (carousel posts) on Instagram Professional accounts.
Beginning July 1, 2023, all single feed videos published through the Instagram Content Publishing API will be shared as reels.
All requests must include the app user's User access token.
Publishing relies on a combination of the following permissions. The exact combination depends on which endpoints your app uses. Refer to our endpoint references to determine which permissions each endpoint requires.
If your app will be used by app users who do not have a role on your app or a role in a Business that has claimed your app, you must request approval for each permission via App Review before non-role app users can grant them to your app.
We cURL media used in publishing attempts so the media must be hosted on a publicly accessible server at the time of the attempt.
Instagram Professional accounts connected to a Page that requires Page Publishing Authorization (PPA) cannot be published to until PPA has been completed.
It's possible that an app user may be able to perform Tasks on a Page that initially does not require PPA but later requires it. In this scenario, the app user would not be able to publish content to their Instagram Professional account until completing PPA. Since there's no way for you to determine if an app user's Page requires PPA, we recommend that you advise app users to preemptively complete PPA.
For additional limitations, refer to each endpoint's reference.
Instagram accounts are limited to 50 API-published posts within a rolling 24-hour period. Carousels count as a single post. This limit is enforced on the POST /{ig-user-id}/media_publish
endpoint when attempting to publish a media container. We recommend that your app also enforce the publishing rate limit, especially if your app allows app users to schedule posts to be published in the future.
To check an Instagram Professional account's current rate limit usage, query the GET /{ig-user-id}/content_publishing_limit
endpoint.
The API consists of the following endpoints. Refer to each endpoint's reference document for usage requirements.
POST /{ig-user-id}/media
— upload media and create media containers.POST /{ig-user-id}/media_publish
— publish uploaded media using their media containers.GET /{ig-container-id}?fields=status_code
— check media container publishing eligibility and status.GET /{ig-user-id}/content_publishing_limit
— check app user's current publishing rate limit usage.Publishing single image, video, story or reel is a two-step process:
POST /{ig-user-id}/media
endpoint to create a container from an image or video hosted on your public server.POST /{ig-user-id}/media_publish
endpoint to publish the container.Step 1 of 2: Create Container
Let's say you have an image at...
https://www.example.com/images/bronz-fonz.jpg
... that you want to publish with the hashtag "#BronzFonz" as its caption. Send a request to the POST /{ig-user-id}/media
endpoint:
POST https://graph.facebook.com/v21.0
/17841400008460056/media
?image_url=https://www.example.com/images/bronz-fonz.jpg
&caption=#BronzFonz
This returns a container ID for the image.
{ "id": "17889455560051444" // IG Container ID }
Step 2 of 2: Publish Container
Use the POST /{ig-user-id}/media_publish
endpoint to publish the container ID returned in the previous step.
POST https://graph.facebook.com/v21.0
/17841400008460056/media_publish
?creation_id=17889455560051444
{ "id": "17920238422030506" // IG Media ID }
You may publish up to 10 images, videos, or a mix of the two in a single post (a carousel post). Publishing carousels is a three step process:
POST /{ig-user-id}/media
endpoint to create individual item containers for each image and video that will appear in the carousel.POST /{ig-user-id}/media
endpoint again to create a single carousel container for the items.POST /{ig-user-id}/media_publish
endpoint to publish the carousel container.Carousel posts count as a single post against the account's rate limit.
Limitations
Step 1 of 3: Create item container
Use the POST /{ig-user-id}/media
endpoint to create an item container for the image or video that will appear in a carousel. Carousels may have up to 10 total images, videos, or a mix of the two.
POST /{ig-user-id}/media
The following parameters are required. Refer to the POST /{ig-user-id}/media
endpoint reference for additional supported parameters.
is_carousel_item
— Set to true
. Indicates image or video will appear in a carousel.image_url
— (images only) The path to the image. We will cURL your image using the passed in URL so it must be on a public server.media_type
— (videos only) Set to VIDEO
. Indicates media is a video.video_url
— (videos only) Path to the video. We will cURL your video using the passed in URL so it must be on a public server.If the operation is successful, the API will return an item container ID which can be used when creating the carousel container.
Repeat this process for each image or video that should appear in the carousel.
curl -i -X POST \
"https://graph.facebook.com/v21.0
/90010177253934/media?image_url=https%3A%2F%2Fsol...&is_carousel_item=true&access_token=EAAOc..."
{ "id": "17899506308402767" }
Step 2 of 3: Create carousel container
Use the POST /{ig-user-id}/media
endpoint to create a carousel container.
POST /{ig-user-id}/media
The following parameters are required. Refer to the POST /{ig-user-id}/media
endpoint reference for additional supported parameters.
media_type
— Set to CAROUSEL
. Indicates container is for a carousel.children
— An array of up to 10 container IDs of each image and video that should appear in the published carousel. Carousels can have up to 10 total images, videos, or a mix of the two.
curl -i -X POST \
"https://graph.facebook.com/v21.0
/90010177253934/media?caption=Fruit%20candies&media_type=CAROUSEL&children=17899506308402767%2C18193870522147812%2C17853844403701904&access_token=EAAOc..."
{ "id": "18000748627392977" }
Step 3 of 3: Publish carousel container
Use the POST /{ig-user-id}/media_publish
endpoint to publish a carousel container (a carousel post). Accounts are limited to 50 published posts within a 24-hour period. Publishing a carousel counts as a single post.
POST /{ig-user-id}/media_publish
The following parameters are required.
creation_id
— The carousel container ID.If the operation is successful the API will return a carousel album IG Media ID.
curl -i -X POST \
"https://graph.facebook.com/v21.0
/90010177253934/media_publish?creation_id=18000748627392977&access_token=EAAOc..."
{ "id": "90010778390276" }
Reels are short-form videos that are eligible to appear in the Reels tab of the Instagram app if they meet certain specifications and are selected by our algorithm. To publish a reel, follow the steps for publishing a single media post and include the media_type=REELS
parameter along with the path to the video using the video_url
parameter.
Reels are not a new media type, even though you set media_type=REELS
when you publish a reel. If you publish a reel and then request its media_type
field, the value returned is VIDEO
. To determine if a published video has been designated as a reel, request its media_product_type
field instead.
You can use the code sample on GitHub (insta_reels_publishing_api_sample) to learn how to publish Reels to Instagram.
To make it more convenient for developers, Meta has published the full set of Graph API calls for Instagram Reels on the Postman API Platform. For more information, see Postman Collections for Facebook Reels and Instagram Reels.
For more information about Reels, see Reels Developer Documentation.
Only business accounts can publish stories with the Content Publising API at this time.
Stories are videos and images that are posted as IG stories on Instagram. To publish a story, follow the same steps for publishing a single media post and include the media_type=STORIES
parameter along with the path to the image/video using the image_url
or video_url
parameter.
Note: Stories are not a new media type even though you are setting media_type=STORIES
when publishing a story. If you publish a story and then request its media_type
field, the value will be returned as IMAGE/VIDEO
. To determine if a published image/video has been designated as a story, request its media_product_type
field instead.
The Resumable upload protocol is a brand new flow for Instagram content publishing that supports video uploads for Reels, Video Stories, and Video Carousel Items media_types
.
This new protocol supports creating Instagram media from both local videos and public hosted url videos. The protocol lets you resume a local file upload operation after a network interruption or other transmission failure, saving time and bandwidth in the event of network failures. It retains the same media specifications.
POST https://graph.facebook.com/{api-version}/{ig-user-id}/media
— Initialize video creation containers by set upload_type=resumable.POST https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}
— Upload video from a local video file or hosted URL more reliably by using the resumable upload protocol. POST https://graph.facebook.com/{api-version}/{ig-user-id}/media_publish
— Publish uploaded media using their media containers.GET /{ig-container-id}?fields=status_code
— Check media container publishing eligibility and status.user_tags=[{username:’ig_user_name’}]
is encoded to user_tags=%5B%7Busername:ig_user_name%7D%5D
where [
is encoded to %5B
and {
is encoded to %7B
. For more conversions, please refer to the HTML URL Encoding standard.curl -X POST "https://graph.facebook.com/{api-version}/{ig-user-id}/media" \ -d "media_type=REELS" \ -d "upload_type=resumable" \ -d "caption={caption}"\ -d "collaborators={collaborators-username}" -d "cover_url={cover-url}" \ -d "audio_name={audio-name}" \ -d "user_tags={user-tags}" \ -d "location_id={location-id}" \ -d "thumb_offset={thumb-offset}" \ -H "Authorization: OAuth {access-token}"
curl -X POST "https://graph.facebook.com/{api-version}/{ig-user-id}/media" \ -d "media_type=STORIES" \ -d "upload_type=resumable" \ -H "Authorization: OAuth {access-token}"
curl -X POST "https://graph.facebook.com/{api-version}/{ig-user-id}/media" \ -d "media_type=VIDEO" \ -d "is_carousel_item=true" \ -d "upload_type=resumable" \ -H "Authorization: OAuth {access-token}"
{ "id": "{ig-container-id}", "uri": "https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}" }
Most Graph API calls use the graph.facebook.com
host however, calls to upload videos for Reels use rupload.facebook.com
.
The following file sources are supported for uploaded video files:
With the ig-container-id
returned from a resumable upload session call, upload the video.
rupload.facebook.com
.media_type
shares the same flow to upload the video.ig-container-id
is the ID returned from resumable upload session calls. access-token
is the same one used in previous steps.offset
is set to the first byte being upload, generally 0
.file_size
is set to the size of your file in bytes.Your_file_local_path
is set to the file path of your local file, for example, if uploading a file from, the Downloads folder on macOS, the path is @Downloads/example.mov.curl -X POST "https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}" \ -H "Authorization: OAuth {access-token}" \ -H "offset: 0" \ -H "file_size: Your_file_size_in_bytes" \ --data-binary "@my_video_file.mp4"
curl -X POST "https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}" \ -H "Authorization: OAuth {access-token}" \ -H "file_url: https://example_hosted_video.com"
// Success Response Message { "success":true, "message":"Upload successful." } // Failure Response Message { "debug_info":{ "retriable":false, "type":"ProcessingFailedError", "message":"{\"success\":false,\"error\":{\"message\":\"unauthorized user request\"}}" } }
You can reuse step 1 and 2 to create multiple ig-container-ids
with the is_carousel_item
parameter set to true
. Then create a Carousel Container to include all the carousel items, the carousel items can be mixed with Image and Videos.
curl -X POST "https://graph.facebook.com/{api-version}/{ig-user-id}/media" \ -d "media_type=CAROUSEL" \ -d "caption={caption}"\ -d "collaborators={collaborator-usernames}" \ -d "location_id={location-id}" \ -d "product_tags={product-tags}" \ -d "children=[{ig-container-id},{ig-container-id}...]" \ -H "Authorization: OAuth {access-token}"
For Reels and Video Stories, the {ig-container-id}
created in step 1 is used to publish the Video, and for Carousel Container, the {ig-container-id}
created in step 3 is used to publish the Carousel Container.
curl -X POST "https://graph.facebook.com/{api-version}/{ig-user-id}/media_publish" \ -d "creation_id={ig-container-id}" \ -H "Authorization: OAuth {access-token}"
graph.facebook.com
provides a GET
endpoint to read the status of the upload, the video_status
field contains details about the local upload process.
uploading_phase
tells whether the file has been uploaded successfully, and how many bytes transferred. processing_phase
contains the details about the status of video processing after the video file is uploaded.// GET status from graph.facebook.com curl -X GET "https://graph.facebook.com/v19.0/{ig-container-id}?fields=id,status,status_code,video_status" \ -H "Authorization: OAuth {access-token}"
graph.facebook.com
endpoint// A successfully created ig container { "id": "{ig-container-id}", "status": "Published: Media has been successfully published.", "status_code": "PUBLISHED", "video_status": { "uploading_phase": { "status": "complete", "bytes_transferred": 37006904 }, "processing_phase": { "status": "complete" } } } // An interrupted ig container creation, from here you can resume your upload in step 2 with offset=50002. { "id": "{ig-container-id}", "status": "Published: Media has been successfully published.", "status_code": "PUBLISHED", "video_status": { "uploading_phase": { "status": "in_progress", "bytes_transferred": 50002 }, "processing_phase": { "status": "not_started" } } }
You can add public Instagram users in an image, carousel and reel as a collaborators and they will receive an invite to be a collaborator for that particular media. To tag users in an image, follow the Single Media Posts steps above, but when creating the media container, include the collaborators parameter and an array of strings indicating the Instagram usernames of users whom you want to invite as a collaborator on the media.
POST graph.facebook.com/17841400008460056/media ?image_url=https://www.example.com/images/bronzed-fonzes.jpg &caption=#BronzedFonzes! &collaborators= [‘username1’,’username2’]
You can use the Pages Search API , be sure to include the `location` field in your query, to search for Pages whose names match a search string. Then, parse the results to identify any Pages that have been created for a physical location. If you include a Page's ID when publishing an image or video, it will be tagged with the location associated with that Page.
To be eligible for tagging, a Page must have latitude and longitude location data.
Verify that the Page you want to use has latitude and longitude data in the response. Attempting to create a container using a Page that has no location data will fail with coded exception INSTAGRAM_PLATFORM_API__INVALID_LOCATION_ID
.
Once you have the Page ID, assign it to the location_id
parameter when publishing single media or carousel item containers.
You can publish both single media posts and carousel posts tagged with Instagram Shopping products. Refer to the Product Tagging guide to learn how.
You can tag public Instagram users in an image and they will receive a notification that they have been tagged.
To tag users in an image, follow the Single Media Posts steps above, but when creating the media container, include the user_tags
parameter and an array of objects indicating the Instagram users in the image as well as their x/y coordinates within the image itself.
Note: User tags are not supported on video media in carousels.
POST graph.facebook.com/17841400008460056/media ?image_url=https://www.example.com/images/bronzed-fonzes.jpg &caption=#BronzedFonzes! &user_tags= [ { username:'kevinhart4real', x: 0.5, y: 0.8 }, { username:'therock', x: 0.3, y: 0.2 } ]
This returns a container ID which you then publish using the IG User Media Publish endpoint.
user_tags
value must be an array of objects formatted with JSON.username
, x
, and y
) for each user.x
and y
values must be float
numbers that originate from the top-left of the image, with a range of 0.0
–1.0
.If you are able to create a container for a video but the POST /{ig-user-id}/media_publish
endpoint does not return the published media ID, you can get the container's publishing status by querying the GET /{ig-container-id}?fields=status_code
endpoint. This endpoint will return one of the following:
EXPIRED
— The container was not published within 24 hours and has expired.ERROR
— The container failed to complete the publishing process.FINISHED
— The container and its media object are ready to be published.IN_PROGRESS
— The container is still in the publishing process.PUBLISHED
— The container's media object has been published.We recommend querying a container's status once per minute, for no more than 5 minutes.
See the Error Codes reference.