# Instagram

Formats, media and text limits, options, inbox and analytics on Instagram.

Publish `feed`, `carousel`, `reel` and `story` to Instagram, read every post's numbers, and answer comments and messages. Set a target's `format`, or leave it out and Rizamo picks one from the files.

## Formats [#formats]

| Format | Files | Text |
| --- | --- | --- |
| `feed` | 1 to 10 images or videos | 2,200 |
| `carousel` | 2 to 10 images or videos | 2,200 |
| `reel` | 1 video | 2,200 |
| `story` | 1 image or video | none |

## Media [#media]

Rizamo takes JPEG, PNG, WebP, MP4 and MOV files up to 4 GB. What Instagram takes:

- **Images:** JPEG, up to 8 MB, up to 1,440 px wide, 9:16 to 1.91:1 on `feed` and `carousel`.
- **Video:** H.264 or HEVC with AAC audio, 23 to 60 frames a second, up to 1,920 px wide.

| Format | Length | Size |
| --- | --- | --- |
| `reel` | 3 s to 15 min | up to 300 MB |
| `feed` | 3 s to 15 min | up to 300 MB |
| `story` | 3 s to 1 min | up to 100 MB |
| `carousel` | 3 s to 1 min | up to 100 MB |

## What Rizamo does to files [#what-rizamo-does-to-files]

- **Images:** another type becomes JPEG; a larger file is compressed under 8 MB; a wider one is made 1,440 px wide; `feed` and `carousel` images outside 9:16 to 1.91:1 are fitted to it over a blurred copy of themselves, or cropped to it with `options.instagram.fit`.
- **Video:** one Instagram does not take as it is (its codec, frame rate, width or size) is converted to H.264 and AAC within those limits; one whose header is not at the front only has it moved there, for streaming. Its length cannot change: a video too short or too long for the format is refused when it is attached.
- Your file itself never changes: the copy is made when the post goes out, and each target's `changes` says what was done.

## Text [#text]

- Up to 2,200, counted in characters: an emoji counts 1. Rizamo counts the same way, so `POST /v1/posts/validate` refuses what Instagram would.
- A first comment takes up to 2,200 characters.
- Up to 30 hashtags a post. Rizamo does not check it yet: Instagram refuses a post with more.
- Stories take no text: a story target's own `text` is refused (`400`), and one that shares the post's text goes without it, which `validate` warns about.

## Options [#options]

Under `options.instagram` on a target. Each says which formats take it.

| Option | Type | What it does |
| --- | --- | --- |
| `shareToFeed` | boolean | Reels: also show in the profile grid. Default true. |
| `coverUrl` | string | Reels, and a single video sent as a feed post (Instagram makes it a reel): an image as the cover, at a public link Instagram downloads when the post goes out. Not with `coverOffsetMs`. |
| `coverOffsetMs` | integer | Reels, and a single video sent as a feed post: the frame this many milliseconds in becomes the cover. Instagram's default is 0, the first frame. Not with `coverUrl`. |
| `collaborators` | array of string | Feed posts, carousels and reels: up to 3 usernames invited as collaborators. Not sent on stories. |
| `locationId` | string | Feed posts, carousels and reels: a Facebook Page id used as the location. Not sent on stories. |
| `fit` | `fill`, `crop` | Feed images taller than 9:16 or wider than 1.91:1, which Instagram refuses: fill keeps all of the image over a blurred copy of itself (default), crop cuts it to the nearest shape. |
| `music` | object | Music from Instagram's library, for reels only. Accounts connected through Facebook Login only. |
| `isAiGenerated` | boolean | Labels the post as made with AI (Instagram's "AI info"): feed posts, carousels (the label covers the whole carousel), reels and stories. |
| `userTags` | array of object | People tagged on the post, up to 20 on each file, public accounts only. Images need `x` and `y` for each tag; videos and reels take the username alone; on stories `x` and `y` are optional. On a carousel, `mediaIndex` picks the file. |
| `trialReel` | `manual`, `performance` | Reels: publish it as a trial reel, shown to people who do not follow the account first. manual: someone shares it with followers in the Instagram app. performance: Instagram shares it with followers if it does well. |

## First comment [#first-comment]

`firstComment` goes out right after the post, as a comment by the account, up to 2,200 characters. Stories take none. One it would not take is refused when the post is made (`400`), with the reason. If it fails once the post is live, the post stays published.

## Music [#music]

Music from Instagram's library, for reels only. Accounts connected through Facebook Login only. Find a track with `GET /v1/accounts/{id}/music` (`search_music` in MCP).

## After publishing [#after-publishing]

- **Edits:** Instagram does not change a live post's text: an update to a live post is `not_supported`.
- **Deleting:** deleting a post takes it off Instagram when the account's `capabilities` include `delete_posts`. Each target's `removal` says what happened. Only accounts connected through Facebook Login can have it: it needs `instagram_manage_contents`, which waits for Meta's review of Rizamo's access.

## Inbox [#inbox]

Comments on the account's posts come into the inbox as they are written, through Meta's webhooks, and are answered as the account.

- Replies to comments: up to 2,000 characters.
- Messages: direct messages come in and are answered in the same thread. A reply goes out within 24 hours of the person's last message.
- Mentions are not read yet.

| Action | People's comments | The account's own |
| --- | --- | --- |
| Hide | yes | no |
| Delete | yes | yes |
| Like | no | no |

## Comment automations [#comment-automations]

A comment with a keyword gets a private message (`POST /v1/comment-automations`, `create_comment_automation` in MCP), on one post or every post of the account. Each account sends up to 1,000 in 24 hours and 10 a minute; more wait for room, within the 7 days Meta takes a private reply to a comment. A follow gate (`followGate`) sends it only to people who follow the account, and asks the others to follow first.

## Daily caps [#daily-caps]

Up to 100 posts an account in 24 hours, counting posts published. A post over a cap waits for room ([Limits](/limits#publishing)).

## Analytics [#analytics]

Days run on Pacific time (`America/Los_Angeles`). On connecting, Rizamo reads back the posts of the last 12 months (up to 500) and 365 days of the account's numbers. [How Rizamo reads numbers](/analytics).

### Posts [#posts]

| Metric | Instagram's name | Formats | Note |
| --- | --- | --- | --- |
| `reach` | `reach` | all |  |
| `likes` | `likes` | feed, carousel, reel |  |
| `comments` | `comments` | feed, carousel, reel |  |
| `shares` | `shares` | all |  |
| `saves` | `saved` | feed, carousel, reel |  |
| `engagements` | `total_interactions` | all |  |
| `views` | `views` | all |  |
| `replies` | `replies` | story |  |
| `navigation` | `navigation` | story |  |
| `follows` | `follows` | feed, carousel, story | Where Meta gives it |
| `profile_visits` | `profile_visits` | feed, carousel, story | Where Meta gives it |
| `reposts` | `reposts` | all | Where Meta gives it |
| `avg_watch_time` | `ig_reels_avg_watch_time` | reel |  |
| `watch_time` | `ig_reels_video_view_total_time` | reel |  |
| `taps_forward` | `navigation` by `tap_forward` | story | Where Meta gives it |
| `taps_back` | `navigation` by `tap_back` | story | Where Meta gives it |
| `exits` | `navigation` by `tap_exit` | story | Where Meta gives it |
| `swipes_forward` | `navigation` by `swipe_forward` | story | Where Meta gives it |
| `views` | `plays` |  | Not given since 2025-04-21 |
| `views` | `ig_reels_aggregated_all_plays_count` |  | Not given since 2025-04-21 |
| `views` | `video_views` |  | Not given since 2025-04-21 |
| `impressions` | `impressions` |  | Not given since 2025-04-21 |

Its posts' details, what is not a count (a post's `details`, the latest read only: [Details](/analytics#details)):

| Detail | Instagram's name | Formats | Note |
| --- | --- | --- | --- |
| `skip_rate` | `reels_skip_rate` | reel |  |

### Account [#account]

| Metric | Instagram's name | Note |
| --- | --- | --- |
| `reach` | `reach` |  |
| `reach_followers` | `reach` by `follow_type` (`FOLLOWER`) | Where Meta gives it |
| `reach_non_followers` | `reach` by `follow_type` (`NON_FOLLOWER`) | Where Meta gives it |
| `views` | `views` |  |
| `views_followers` | `views` by `follow_type` or `follower_type` (`FOLLOWER`) | Where Meta gives it |
| `views_non_followers` | `views` by `follow_type` or `follower_type` (`NON_FOLLOWER`) | Where Meta gives it |
| `views_paid` | `views` by `media_product_type` (`AD`) | Where Meta gives it |
| `views_feed` | `views` by `media_product_type` (`POST`) | Where Meta gives it |
| `views_carousel` | `views` by `media_product_type` (`CAROUSEL_CONTAINER`) | Where Meta gives it |
| `views_reel` | `views` by `media_product_type` (`REEL`) | Where Meta gives it |
| `views_story` | `views` by `media_product_type` (`STORY`) | Where Meta gives it |
| `engagements` | `total_interactions` |  |
| `accounts_engaged` | `accounts_engaged` |  |
| `likes` | `likes` |  |
| `comments` | `comments` |  |
| `shares` | `shares` |  |
| `saves` | `saves` |  |
| `replies` | `replies` |  |
| `reposts` | `reposts` |  |
| `profile_actions` | `profile_links_taps` |  |
| `follows` | `follows_and_unfollows` by `FOLLOWER` | Meta gives them to accounts with 100 followers or more |
| `unfollows` | `follows_and_unfollows` by `NON_FOLLOWER` | Meta gives them to accounts with 100 followers or more |

Its audience: who follows the account and who engaged this month, by age, gender, country and city, for accounts with 100 followers or more.

No `clicks` on its posts and no `impressions` (since 2025-04-21).
