Content Publishing

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.

Requirements

Access Tokens

All requests must include the app user's User access token.

Permissions

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.

Public Server

We cURL media used in publishing attempts so the media must be hosted on a publicly accessible server at the time of the attempt.

Page Publishing Authorization

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.

Limitations

  • JPEG is the only image format supported. Extended JPEG formats such as MPO and JPS are not supported.
  • Shopping tags are not supported.
  • Branded content tags are not supported.
  • Filters are not supported.
  • Publishing to Instagram TV is not supported.

For additional limitations, refer to each endpoint's reference.

Rate Limit

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.

Endpoints

The API consists of the following endpoints. Refer to each endpoint's reference document for usage requirements.

Single Media Posts

Publishing single image, video, story or reel is a two-step process:

  1. Use the POST /{ig-user-id}/media endpoint to create a container from an image or video hosted on your public server.
  2. Use the 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:

Sample Request

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.

Sample Response

{
  "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.

Sample Request

POST https://graph.facebook.com/v21.0/17841400008460056/media_publish
  ?creation_id=17889455560051444

Sample Response

{
  "id": "17920238422030506" // IG Media ID
}

Carousel Posts

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:

  1. Use the POST /{ig-user-id}/media endpoint to create individual item containers for each image and video that will appear in the carousel.
  2. Use the POST /{ig-user-id}/media endpoint again to create a single carousel container for the items.
  3. Use the 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

  • Carousels cannot be boosted.
  • Carousels are limited to 10 images, videos, or a mix of the two.
  • Carousel images are all cropped based on the first image in the carousel, with the default being a 1:1 aspect ratio.

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

Parameters

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.

Sample Request

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..."

Sample Response

{
  "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

Parameters

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.

Sample Request

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..."

Sample Response

{
  "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

Parameters

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.

Sample Request

curl -i -X POST \

"https://graph.facebook.com/v21.0/90010177253934/media_publish?creation_id=18000748627392977&access_token=EAAOc..."

Sample Response

{
  "id": "90010778390276"
}

Reels Posts

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.

Story Posts

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.

Resumable Upload Protocol

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.

Endpoints

  • 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.

HTML URL encoding hints

  • Some of the parameters are supported in list/dict format.
  • Some characters need to be encoded into a format that can be transmitted over the Internet. For example: 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.

Step 1: Initialize an Upload Session for Reels, Video Stories or Carousel Items

Reels Sample Request

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}"

Video Stories Sample Request

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}"

Carousel Video Item Sample Request

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}"

Sample Response

{
   "id": "{ig-container-id}",
   "uri": "https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}"
}

Step 2: Upload the Video using Resumable Upload Protocol

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:

  • A file located on your computer
  • A file hosted on a public facing server, such as a CDN

Sample request upload a local video file

With the ig-container-id returned from a resumable upload session call, upload the video.

  • Be sure the host is rupload.facebook.com.
  • All 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"

Sample request upload a public hosted video

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"

Sample Response

// 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\"}}"
  }
}

Step 3: (Carousel Only) Create Carousel Containers

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}"

Step 4: Publish the Media

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}"

Step 5: Get Media Status

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.

  • The uploading_phase tells whether the file has been uploaded successfully, and how many bytes transferred.
  • The 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}"

Sample Response from the 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"
    }
  }
}

Collaborator Tags

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.

Sample Requeset

POST graph.facebook.com/17841400008460056/media
?image_url=https://www.example.com/images/bronzed-fonzes.jpg
&caption=#BronzedFonzes!
&collaborators= [‘username1’,’username2’]

Notes

  • The collaborators value must be an array of strings.
  • You can only tag users with public Instagram accounts.
  • No more than 3 collaborators can be added to a media.
  • Collaborators cannot be added to Story media.

Location Tags

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.

Limitations

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.

Product Tags

You can publish both single media posts and carousel posts tagged with Instagram Shopping products. Refer to the Product Tagging guide to learn how.

User Tags

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.

Sample Request

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.

Notes

  • The user_tags value must be an array of objects formatted with JSON.
  • You can only tag users with public Instagram accounts.
  • The object must contain all three properties (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.01.0.

Troubleshooting

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.

Errors

See the Error Codes reference.