Overview
Baileys supports sending various media types efficiently. Media can be provided as a Buffer, Stream, or URL, and Baileys handles encryption and upload automatically.
All media messages accept a WAMediaUpload type, which can be:
type WAMediaUpload =
| Buffer
| { stream : Readable }
| { url : URL | string }
Using stream or url is recommended to save memory, especially for large files. Baileys will encrypt the media as a stream without loading the entire file into memory.
Image Messages
Send images with optional captions:
Buffer
URL
Remote URL
Stream
import { readFileSync } from 'fs'
await sock . sendMessage (
jid ,
{
image: readFileSync ( './image.jpg' ),
caption: 'Hello World!'
}
)
Image with Mentions
await sock . sendMessage (
jid ,
{
image: { url: './image.jpg' },
caption: 'Look at this @12345678901!' ,
mentions: [ '[email protected] ' ]
}
)
Video Messages
Send video files with captions:
await sock . sendMessage (
jid ,
{
video: { url: './video.mp4' },
caption: 'Check out this video!'
}
)
Video Notes (PTV)
Send as a video note (circular video):
await sock . sendMessage (
jid ,
{
video: { url: './video.mp4' },
ptv: true // Send as video note
}
)
ptv stands for “picture-taking video” - WhatsApp’s internal name for video notes.
GIF Messages
WhatsApp doesn’t support actual .gif files. GIFs are sent as MP4 videos with the gifPlayback flag.
import { readFileSync } from 'fs'
await sock . sendMessage (
jid ,
{
video: readFileSync ( './animation.mp4' ),
caption: 'Animated content' ,
gifPlayback: true
}
)
Audio Messages
Send audio files or voice notes:
Regular Audio
await sock . sendMessage (
jid ,
{
audio: { url: './audio.mp3' },
mimetype: 'audio/mp4'
}
)
Voice Notes (PTT)
await sock . sendMessage (
jid ,
{
audio: { url: './voice.ogg' },
mimetype: 'audio/ogg; codecs=opus' ,
ptt: true // Send as voice note
}
)
ptt stands for “push to talk” - WhatsApp’s internal name for voice notes.
Audio Requirements
For audio to work across all devices, convert to OGG format with ffmpeg:
ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
Required flags:
codec: libopus - OGG file format
ac: 1 - Single audio channel
avoid_negative_ts make_zero - Timestamp handling
Audio with Duration
await sock . sendMessage (
jid ,
{
audio: { url: './audio.ogg' },
mimetype: 'audio/ogg; codecs=opus' ,
ptt: true ,
seconds: 60 // Optional duration in seconds
}
)
Document Messages
Send any file as a document:
await sock . sendMessage (
jid ,
{
document: { url: './file.pdf' },
mimetype: 'application/pdf' ,
fileName: 'document.pdf' ,
caption: 'Here is the document'
}
)
Common MIME Types
const mimeTypes = {
pdf: 'application/pdf' ,
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ,
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ,
zip: 'application/zip' ,
txt: 'text/plain'
}
Sticker Messages
Send stickers (WebP format):
await sock . sendMessage (
jid ,
{
sticker: { url: './sticker.webp' }
}
)
Animated Stickers
await sock . sendMessage (
jid ,
{
sticker: { url: './animated-sticker.webp' },
isAnimated: true
}
)
View Once Messages
Send media that can only be viewed once:
await sock . sendMessage (
jid ,
{
image: { url: './secret.jpg' },
viewOnce: true ,
caption: 'This can only be viewed once'
}
)
viewOnce works with images, videos, and audio messages.
Thumbnails
Baileys can automatically generate thumbnails for media messages.
Automatic Thumbnail Generation
Install image processing libraries:
# For images and stickers
yarn add sharp
# or
yarn add jimp
# For video thumbnails (requires ffmpeg installed on system)
# No additional packages needed
Manual Thumbnail
await sock . sendMessage (
jid ,
{
image: { url: './large-image.jpg' },
jpegThumbnail: thumbnailBuffer , // Buffer or base64 string
caption: 'Large image with custom thumbnail'
}
)
Media with Context
Combine media with other message features:
await sock . sendMessage (
jid ,
{
image: { url: './photo.jpg' },
caption: 'Check this out @12345678901!' ,
mentions: [ '[email protected] ' ]
},
{
quoted: originalMessage ,
ephemeralExpiration: 86400 // 24 hours
}
)
Understanding how media is uploaded:
Encryption : Media is encrypted using AES-256-CBC
Upload : Encrypted media is uploaded to WhatsApp servers
Message : A message containing the media key and URL is sent
Decryption : Recipient decrypts media using the media key
// This all happens automatically
const msg = await sock . sendMessage ( jid , {
image: { url: './image.jpg' }
})
// The message contains:
// - directPath: WhatsApp CDN path
// - mediaKey: Encryption key
// - fileEncSha256: Encrypted file hash
// - fileSha256: Original file hash
Configure media upload behavior in socket config:
const sock = makeWASocket ({
// Timeout for media uploads (default: 30 seconds)
mediaUploadTimeoutMs: 60000 ,
// Cache media to avoid re-uploading
mediaCache: new NodeCache ({
stdTTL: 3600 // 1 hour cache
})
})
Best Practices
Use Streams : For large files, use streams to avoid memory issues
Set MIME Types : Always specify correct MIME types for documents
Optimize Images : Compress images before sending
Generate Thumbnails : Install sharp/jimp for automatic thumbnails
Handle Errors : Wrap uploads in try-catch blocks
Rate Limiting : Don’t send too many media messages rapidly
From the Baileys source code:
type AnyMediaMessageContent =
| { image : WAMediaUpload ; caption ?: string ; jpegThumbnail ?: string }
| { video : WAMediaUpload ; caption ?: string ; gifPlayback ?: boolean ; ptv ?: boolean }
| { audio : WAMediaUpload ; ptt ?: boolean ; seconds ?: number }
| { sticker : WAMediaUpload ; isAnimated ?: boolean }
| { document : WAMediaUpload ; mimetype : string ; fileName ?: string ; caption ?: string }
Troubleshooting
Upload Failures
try {
await sock . sendMessage ( jid , { image: { url: './image.jpg' } })
} catch ( error ) {
if ( error . message . includes ( 'upload failed' )) {
// Retry with exponential backoff
}
}
Large Files
For files larger than 100MB, consider:
Breaking into smaller chunks
Using a more reliable network connection
Increasing mediaUploadTimeoutMs
Next Steps
Downloading Media Learn how to download media from received messages
Message Options Configure ephemeral and other message options