Media & Video
Image, GIF and video limits for X, and the longVideo flag for videos over 140 seconds on Premium accounts.
When you finish this page your images, GIFs and videos are within X's limits and a Premium account can publish a video longer than 140 seconds with platformSpecificData.longVideo. You need a connected X account (accountId) and media on a public HTTPS URL, or an upload through the media endpoint.
Media requirements
A post carries up to 4 images, or 1 GIF, or 1 video. Files above the size limits are rejected.
Images
| Property | Requirement |
|---|---|
| Max images | 4 per post |
| Formats | JPEG, PNG, WebP, GIF |
| Max file size | 5 MB (images), 15 MB (GIFs) |
| Min dimensions | 4 x 4 px |
| Max dimensions | 8192 x 8192 px |
| Recommended | 1200 x 675 px (16:9) |
| Type | Ratio | Dimensions |
|---|---|---|
| Landscape | 16:9 | 1200 x 675 px |
| Square | 1:1 | 1200 x 1200 px |
| Portrait | 4:5 | 1080 x 1350 px |
GIFs
| Property | Requirement |
|---|---|
| Max per post | 1 (takes all 4 image slots) |
| Max file size | 15 MB |
| Max dimensions | 1280 x 1080 px |
| Behavior | Auto-plays in the timeline |
Videos
| Property | Requirement |
|---|---|
| Max videos | 1 per post |
| Formats | MP4, MOV |
| Max file size | 512 MB |
| Max duration | 140 seconds standard; longer where X allows it, see Long video uploads |
| Min duration | 0.5 seconds |
| Min dimensions | 32 x 32 px |
| Max dimensions | 1920 x 1200 px |
| Frame rate | 40 fps max |
| Bitrate | 25 Mbps max |
Recommended encoding: 1280 x 720 px (720p), 16:9 or 1:1, 30 fps, H.264 video, AAC audio at 128 kbps.
Long video uploads
platformSpecificData.longVideo: true uploads the video with X's amplify_video media category instead of the standard tweet_video. Zernio applies it only when the connected X account has a paid X subscription; on other accounts the flag is accepted and ignored. The maximum duration is set by X per account, not by Zernio, which enforces only the 512 MB file size. Some accounts also need X's long-video API allowlisting, without which X rejects an amplify_video upload.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: published } = await zernio.posts.createPost({
body: {
content: 'Full keynote recording',
mediaItems: [{ type: 'video', url: 'https://cdn.example.com/keynote.mp4' }],
platforms: [{
platform: 'twitter',
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
platformSpecificData: { longVideo: true }
}],
publishNow: true
}
});
console.log(published.post.platforms[0].platformPostUrl);Response (201):
{
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"status": "published",
"platforms": [
{
"platform": "twitter",
"status": "published",
"platformPostUrl": "https://twitter.com/acmecorp/status/1852634789012345678"
}
]
}
}Media URLs
A media URL must be public HTTPS, return the file bytes with the correct Content-Type and not redirect to an HTML page; Google Drive, Dropbox, OneDrive and iCloud sharing links return a web page and fail. The media uploads guide has the rules and the upload flow.
If it fails
A 207 with post.status: "failed" and errorMessage: "Media fetch failed, retrying... (failed after 3 attempts)" means Zernio could not download the file from the URL:
{
"message": "Post created but publishing failed",
"error": "All platforms failed",
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"status": "failed",
"platforms": [
{
"platform": "twitter",
"status": "failed",
"errorMessage": "Media fetch failed, retrying... (failed after 3 attempts)"
}
]
}
}Open the URL in an incognito window: a web page instead of the raw file means the host is not serving the bytes. Upload the file through the media endpoint and create the post again.
Related
- Posts & Editing: attaching media to the base request.
- Media uploads: presigned uploads up to 5 GB.
- Fields, Geo & Polls:
geoRestrictionandsensitiveMediaapply to attached media. - Limits & Errors: every field and error.