Instagram Reels API: 1920 px width cap and 25 Mbps video bitrate

Meta's Reel spec caps width at 1920 px and bitrate at 25 Mbps VBR, with 23-60 FPS and 300 MB. Probe width, fps and size with Sume; bitrate is an average.

5 min readSume
All posts

Meta's IG User Media reference lists these video limits for a Reel: maximum 1920 horizontal pixels, VBR video bitrate of 25 Mbps maximum, 23 to 60 FPS, HEVC or H264 with 4:2:0 chroma and a closed GOP, 3 seconds to 15 minutes, and 300 MB (read 2026-10-02). Sume's video inspect probe shows width, fps, codec, pixel format, duration and size, but no bitrate field, so you can only estimate average bitrate from size and length.

Which video limits can a Sume probe check?

Most of them. Closed GOP is the exception, along with the peak bitrate that VBR implies.

Reel video items on Meta's IG User Media page against the Sume probe (read 2026-10-02)
Meta itemLimitSume probe field
Width1920 px maximumwidth
Frame rate23 to 60fps
CodecHEVC or H264video_codec
Chroma4:2:0pix_fmt
Duration3 s to 15 minduration_seconds
File size300 MBsize_bytes
Bitrate25 Mbps maximum (VBR)Estimate only
Closed GOPRequiredNot in the probe

How do I estimate bitrate from the probe?

Divide size_bytes times 8 by duration_seconds. The result is the average for the whole file including audio, so it can sit under 25 Mbps while a short peak does not. Treat it as a screen for obvious overshoots, such as a 4K master.

import hashlib, os, time, requests
BASE = "https://api.sume.com"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}

def probe(video_url):
    key = "probe-" + hashlib.sha256(video_url.encode()).hexdigest()[:24]
    r = requests.post(f"{BASE}/v1/video-inspect", headers={**H, "Idempotency-Key": key},
                      json={"video_url": video_url, "frames": False}, timeout=60)
    r.raise_for_status()
    rid = r.json()["data"]["video_inspect_id"]
    while True:
        d = requests.get(f"{BASE}/v1/video-inspect/{rid}", headers=H, timeout=30).json()["data"]
        if d["resource_status"] == "ready":
            return d["probe"]
        if d["resource_status"] in ("failed", "canceled"):
            raise RuntimeError(d["error"])
        time.sleep(2)

p = probe("https://media.sume.com/artifacts/artf_demo/talk.mp4")
avg_mbps = p["size_bytes"] * 8 / p["duration_seconds"] / 1e6
checks = {
    "width <= 1920": p["width"] <= 1920,
    "fps 23-60": 23 <= p["fps"] <= 60,
    "3 s <= duration <= 15 min": 3 <= p["duration_seconds"] <= 900,
    "size <= 300 MB": p["size_bytes"] <= 300 * 1000 * 1000,
    "avg bitrate < 25 Mbps": avg_mbps < 25,
}
print(f"avg {avg_mbps:.1f} Mbps"); print(checks)

How do I bring a too-large clip into range?

Video trim with precision: exact takes an output object with width, height (256 to 2160) and fps (24, 25, 30 or 60) and re-encodes with libx264 and yuv420p. A 1080x1920 conform at 30 fps sits inside Meta's width and frame-rate limits. Trim's output is capped at 900 seconds, the same as Meta's 15 minutes, and its source at 1800 seconds.

The 300 MB limit is a file-size cap, and trim has no bitrate field, so a long 1080p clip can still be too big; shorten it instead. The page does not say whether its MB is decimal or binary, so leave headroom under 300.

What should I do?

Run the five checks above on every file, conform with trim when width or fps fail, and test one real publish before a large batch. Closed GOP and peak bitrate are the two items only Meta's side can confirm.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume