Uploading Media

Guide to Uploading Media

There are a few important concepts to understand when using the POST media/upload endpoint. Uploading media with OAuth can be a bit tricky, so we’ve outlined some things to keep in mind as well as a working sample of how to use this endpoint here.

Keep in mind

  • Because the method uses multipart POST, OAuth is handled differently. POST or query string parameters are not used when calculating an OAuth signature basestring or signature. Only the oauth_* parameters are used.
  • You may attach up to 4 photos, 1 animated GIF or 1 video in a Tweet.
  • The image passed should be the raw binary of the image or binary base64 encoded, no need to otherwise encode or escape the contents as long as the Content-Type is set appropriately (when in doubt: application/octet-stream).
  • When posting base64 encoded images, be sure to set the “Content-Transfer-Encoding: base64” on the image part of the message.
  • Multi-part message boundaries must be on their own line and terminated by a CRLF.
  • For working examples of how to POST using this endpoint, we recommend testing with twurl. Also take a look at the Twitter Libraries available.
  • Use the media_id_string provided in the API response from Javascript and other languages that cannot accurately represent a long integer.

Video specifications and recommendations

Video files must meet all of the following criteria:

  • Duration should be between 0.5 seconds and 30 seconds (sync) / 140 seconds (async)
  • File size should not exceed 15 mb (sync) / 512 mb (async)
  • Dimensions should be between 32x32 and 1280x1024
  • Aspect ratio should be between 1:3 and 3:1
  • Frame rate should be 40fps or less
  • Must not have open GOP
  • Must use progressive scan
  • Must have 1:1 pixel aspect ratio
  • Only YUV 4:2:0 pixel format is supported.
  • Audio should be mono or stereo, not 5.1 or greater
  • Audio must be AAC with Low Complexity profile. High-Efficiency AAC is not supported.

Note that the duration, filesize, fps and other constraints may vary based on the media_category parameter.

The media platform is optimized to handle the specifications of video captured on mobile devices. For developers creating their own video (i.e. not uploading video captured directly from a mobile device), please refer to the table below. Each row represents an upload recommendation, but is not a requirement. All uploads are processed for optimization across multiple platforms.

Orientation Width Height Video Bitrate Audio Bitrate
Landscape 1280 720 2048K 128K
Landscape 640 360 768K 64K
Landscape 320 180 256K 64K
Portrait 640 640 1024K 96K
Portrait 480 480 768K 64K
Portrait 240 240 256K 64K

Image specifications and recommendations

Image files must meet all of the following criteria:

  • Supported image media types: JPG, PNG, GIF, WEBP
  • Image size <= 5 MB, animated GIF size <= 15 MB

The filesize limit above is enforced by the media upload endpoint. In addition, there is a separate product entity specific filesize limit which is applied when calling the Tweet creation (or similar) endpoints with media_id. For example, it is possible to upload a 5 MB image, but the Tweet creation requires images to be <= 3 MB. The filesize limit and other constraints may vary depending on the media_category parameter.

Animated GIF recommendations

A GIF may fail during Tweet creation even if it is within the filesize limit. Adhere to the following constraints to improve success rates.

  • Resolution should be <= 1280x1080 (width x height)
  • Number of frames <= 350
  • Number of pixels (width * height * num_frames) <= 300 million
  • Filesize <= 15Mb

In order to get better support for larger GIFs, use the chunked upload endpoint with the media_category parameter. This allows the server to process the GIF file asynchronously, which is a requirement for processing larger files. Pass media_category=tweet_gif to enable async upload behavior for Tweets with an animated GIF.

Example of image media/upload

As of Twurl v0.9.0 (see our command-line twurl tool) support for calling Twitter’s REST API with a multipart message for the POST media/upload endpoint now exists. Use this example as a great way to debug your own code. Note that many of the Twitter Libraries include methods that will handle this POST correctly for you.

Using the -t option will show you the full trace of the request and response that was POSTed to the Twitter API.

twurl -H upload.twitter.com -X POST "/1.1/media/upload.json" --file "/path/to/media.jpg" --file-field "media"

  "media_id": 553656900508606464,
  "media_id_string": "553656900508606464",
  "size": 998865,
  "image": {
    "w": 2234,
    "h": 1873,
    "image_type": "image/jpeg"

Example of chunked video media/upload

Using the chunked POST media/upload endpoints requires an adjusted workflow from single image uploads. For video or chunked uploads, you must:

  • Initialize the upload using the INIT command
  • Upload each chunk of bytes using the APPEND command
  • Complete the upload using the FINALIZE command

See the large video upload sample for an example written in Python.

Below is a working example using the command-line twurl utility. To see full headers of the requests and responses when using twurl, use the -t option to enable trace mode.


twurl -H upload.twitter.com "/1.1/media/upload.json" -d "command=INIT&media_type=video/mp4&total_bytes=4430752"

  "media_id": 601413451156586496,
  "media_id_string": "601413451156586496",
  "expires_after_secs": 3599


twurl -H upload.twitter.com "/1.1/media/upload.json" -d "command=APPEND&media_id=601413451156586496&segment_index=0" --file /path/to/video.mp4 --file-field "media"

HTTP 2XX will be returned with an empty response body on successful upload.


twurl -H upload.twitter.com "/1.1/media/upload.json" -d "command=FINALIZE&media_id=601413451156586496"

  "media_id": 601413451156586496,
  "media_id_string": "601413451156586496",
  "size": 4430752,
  "expires_after_secs": 3600,
  "video": {
    "video_type": "video/mp4"