Threads API video requirements: codecs, 5 minutes, 1 GB, 23-60 fps
Threads API video limits as of October 2026: MP4 or MOV, H264 or HEVC, 23-60 fps, 5 minutes, 1 GB. A preflight that checks each one against a Sume probe.

A video you publish through the Threads API must be MP4 or MOV, H264 or HEVC, 23 to 60 fps, at most 5 minutes and at most 1 GB, with AAC audio. The page also asks for no edit lists, the moov atom at the front, a closed GOP and 4:2:0 chroma. Sume's video inspect can check most of these in one unbilled call; the last few it cannot see, and we say which.
Requirements on the page
| Item | Requirement |
|---|---|
| Container | MOV or MP4; no edit lists; moov atom at the front |
| Video codec | HEVC or H264; progressive scan; closed GOP; 4:2:0 chroma |
| Audio | AAC; 48 kHz maximum; mono or stereo |
| Frame rate | 23 to 60 FPS |
| Resolution | Max 1920 px horizontally; aspect ratio between 0.01:1 and 10:1; 9:16 recommended |
| Bitrate | VBR; 100 Mbps video maximum, 128 kbps audio |
| Duration | Longer than 0 and up to 300 seconds |
| File size | 1 GB maximum |
What a Sume probe can verify
POST /v1/video-inspect returns a probe with container, video_codec, fps, width, height, duration_seconds, audio_codec, audio_channels, audio_sample_rate, pix_fmt and size_bytes. That covers codec, frame rate, size, duration, audio and pixel format. It does not report edit lists, moov position or GOP structure.
def threads_problems(p):
out = []
if p.get("video_codec") not in ("h264", "hevc"):
out.append("codec must be h264 or hevc")
if not 23 <= (p.get("fps") or 0) <= 60:
out.append("fps outside 23-60")
if (p.get("duration_seconds") or 0) > 300:
out.append("longer than 300 s")
if (p.get("size_bytes") or 0) > 1024**3:
out.append("over 1 GB")
if (p.get("width") or 0) > 1920:
out.append("wider than 1920")
if p.get("has_audio") and p.get("audio_codec") != "aac":
out.append("audio must be aac")
return out
print(threads_problems({"video_codec": "h264", "fps": 30,
"duration_seconds": 42, "size_bytes": 5_000_000, "width": 1080}))
Fixing a failure
For length, video trim cuts a range for $0.02 per job. For frame rate or size, its exact mode accepts output with fps of 24, 25, 30 or 60 and a width and height from 256 to 2160, and re-encodes with libx264 in yuv420p, with kept audio remuxed as AAC. Sume has no field for GOP, moov placement or bitrate, and rejects such fields with ffmpeg_fields_rejected.
Limits
The codec strings in the sketch (h264, hevc) are our assumption of what the probe returns; print a real probe and adjust before you rely on it. The sketch also skips the container check. If Threads rejects a file that passes, the cause is likely one of the structural items we cannot probe, so confirm by publishing a test post. Carousel rules differ: see Threads carousel limits.
Sources
Related posts
More in Media tools
- TikTok trending video transcripts via API: what summary_mode returns
Can you get a transcript with Sume's trending video search? summary_mode transcript returns metadata plus an unsupported warning. What to do for the words.
- Trim an AI clip first, or use source_in on the timeline?
For a shot that is too long, set source_in and duration on the Timeline 1.0 slot. Use video_trim ($0.02 per job) only when another step needs a new MP4 file.
- Put a product shot above a UGC creator clip: compose stack
Timeline compose stacks one Sume-hosted still over one video into a single MP4. Set ratio for the still's share. The public rate is $0.02 per job.
- Check a video filter program for free before you encode it
POST /v1/video-filter/check runs the same schema and allowlist as the encode and returns diagnostics without creating a job. Encoding is $0.02 a job.
Written by Sume