Skip to content

Media

Upload images, GIFs, and videos, then attach them to tweets.

media.create(source, opts?)

Upload media to Twitter. Returns a media_id you can pass to tweets.create().

ParamTypeDescription
sourcestring | Buffer | Uint8Array | ArrayBuffer | BlobA file path, Buffer, typed array, or Blob containing the media
opts.alt_textstringAlt text for accessibility (applied automatically after upload)
opts.mediaTypestringExplicit MIME type (e.g. "image/png"). Auto-detected when omitted
opts.type"tweet" | "dm"Upload context — defaults to "tweet". Use "dm" for direct messages

Returns: { media_id, ... } — use media_id with tweets.create().

Auto-detected types: JPEG, PNG, GIF, WebP, MP4, WebM. If detection fails, pass opts.mediaType explicitly.

Size limits

TypeMax size
Image5 MB
GIF15 MB
Video512 MB

Examples

js
import { readFileSync } from "fs";

// Upload from a file path
const img = await client.media.create("./photo.jpg");
const tweet = await client.tweets.create("Check this out!", {
  mediaIds: [img.media_id],
});

// Upload a Buffer with alt text
const buf = readFileSync("./chart.png");
const chart = await client.media.create(buf, {
  alt_text: "A bar chart showing monthly revenue growth",
});
await client.tweets.create("Q4 results 📊", {
  mediaIds: [chart.media_id],
});

// Upload a video
const video = await client.media.create("./clip.mp4");
await client.tweets.create("Watch this!", {
  mediaIds: [video.media_id],
});

// Upload a Blob (e.g. from fetch)
const response = await fetch("https://example.com/image.png");
const blob = await response.blob();
const uploaded = await client.media.create(blob);

// Upload for a DM
const dm = await client.media.create("./sticker.gif", { type: "dm" });

// Explicit MIME type
const raw = await client.media.create(someBuffer, {
  mediaType: "image/webp",
});

Upload multiple media

js
const [a, b, c] = await Promise.all([
  client.media.create("./pic1.jpg", { alt_text: "First photo" }),
  client.media.create("./pic2.jpg", { alt_text: "Second photo" }),
  client.media.create("./pic3.jpg", { alt_text: "Third photo" }),
]);

await client.tweets.create("Photo dump 🧵", {
  mediaIds: [a.media_id, b.media_id, c.media_id],
});

TIP

Always add alt_text! It makes your media accessible to users who rely on screen readers — and it only takes one extra option.

media.createMetadata(mediaId, altText, opts?)

Set alt text and metadata for an already-uploaded media item. Uses the v1.1 media/metadata/create endpoint.

TIP

media.create() will do this for you when passing an alt_text

ParamTypeDescription
mediaIdstringThe media ID returned from upload
altTextstringAlt text description for the media
optsobjectAdditional metadata fields to merge
js
await client.media.createMetadata(
  "1234567890",
  "A photo of a sunset over the ocean",
);

media.createSubtitles(mediaId, subtitles)

Attach subtitles / captions to a video. Uses the v1.1 media/subtitles/create endpoint.

ParamTypeDescription
mediaIdstringThe video media ID
subtitlesobject | arrayA subtitle object or array of subtitle objects

Each subtitle object:

FieldTypeDescription
media_idstringMedia ID of the subtitle file
language_codestringLanguage code (e.g. "en")
display_namestringDisplay name (e.g. "English")
js
// Single subtitle track
await client.media.createSubtitles("1234567890", {
  media_id: "9876543210",
  language_code: "en",
  display_name: "English",
});

// Multiple subtitle tracks
await client.media.createSubtitles("1234567890", [
  { media_id: "9876543210", language_code: "en", display_name: "English" },
  { media_id: "1111111111", language_code: "es", display_name: "Español" },
]);

not affiliated with X Corp.