<!-- https://cutedyno.com/docs/platforms/instagram -->

# Instagram

Reels, carousels, and the account type requirement that blocks most first attempts.

Instagram accepts images and video. It does not accept text-only posts — there is nowhere for them to go.

## Account requirements

Instagram's API only works with **Professional** accounts: Business or Creator. A personal account cannot be published to by any tool, including this one, and the connect flow will fail rather than silently connect something unusable.

Two shapes work:

- **Instagram Business, linked to a Facebook Page** — connected through Facebook, using the Page's token.
- **Instagram Professional, standalone** — connected directly through Instagram login.

Both publish identically. Put the requirement next to your Connect button; it is the most common reason a connection fails.

## Video becomes a Reel

```typescript
await cutedyno.posts.create({
  content: 'Behind the counter this morning. ☕️',
  media: [{ type: 'video', url: videoUrl }],
  accountIds: [instagramAccountId],
  platforms: {
    instagram: {
      thumbnail_url: coverUrl,
      collaborators: ['acmeroasters'],
    },
  },
});
```

There is no separate reel content type: Instagram publishes API video as Reels, so every video post is one.

Instagram processes video on its own side before it can be published. CuteDyno creates a media container, waits for Instagram to finish — up to five minutes for video, two for images — and then publishes. A minute or two in `processing` for a large video is normal.

## Carousels

Two to ten images in the `media` array become a carousel:

```typescript
await cutedyno.posts.create({
  content: 'Five shots from the roastery.',
  media: images.map((url) => ({ type: 'image', url })),
  accountIds: [instagramAccountId],
});
```

Above ten, Instagram accepts only the first ten. Split into several posts rather than relying on that.

## Options

| Option | Effect |
| --- | --- |
| `location_id` | Instagram location ID to tag. |
| `thumbnail_url` | Cover image for a Reel. Must be publicly reachable. |
| `collaborators` | Up to three usernames invited as collaborators. |

Collaborators are invitations, not facts: the post publishes immediately and the collaborator appears once they accept.

## Media rules

Instagram is the fussiest platform about media, and enforces all of it on their side:

- Feed images between 4:5 and 1.91:1. Squarer or wider is cropped or rejected.
- Reels are vertical, 9:16. Other ratios get letterboxed.
- Minimum 3 seconds of video.
- JPEG and PNG for images; MP4 with H.264 and AAC for video.

A rejection arrives as `results[].error` with Instagram's own wording, which is more specific than a generic pre-check would be.

## Failures worth handling

| Message | Meaning |
| --- | --- |
| media container failed processing | Instagram rejected the file. Usually codec, aspect ratio, or duration. |
| media container expired before publishing | Processing took longer than Instagram's own container lifetime. Retry. |
| media container processing timed out | Instagram never finished. Retry; if it repeats, the file is the problem. |
| Authentication failed. Please reconnect your account. | The token was revoked. Run the [connect flow](/docs/guides/connecting-accounts) again. |

## Analytics

Views, reach, saves, shares, likes, and comments per post, plus average watch time on Reels. Audience demographics by age, gender, and country are available at the account level.

## Comments

Fully supported. Instagram comments arrive as `comment.received` webhooks, appear in [`GET /v1/comments`](/docs/api/list-comments), and can be replied to, hidden, or deleted.
