# How to Send Text, Media, Location, Contact, and Poll Messages with Baileys

> Learn to send text, media, location, contact, and poll messages with Baileys. Effortlessly handle message encoding, encryption, and delivery with sock.sendMessage.

- Repository: [WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys)
- Tags: how-to-guide
- Published: 2026-08-01

---

**Use `sock.sendMessage(jid, content, options?)` with a content object matching the `AnyMessageContent` interface—Baileys automatically handles protocol encoding, encryption, and delivery for text, images, video, audio, documents, location, contacts, and polls.**

Baileys provides a unified API to send various message types through WhatsApp Web without manually constructing protobuf payloads. The library's `sendMessage` method in [`src/Socket/messages-send.ts`](https://github.com/WhiskeySockets/Baileys/blob/main/src/Socket/messages-send.ts) orchestrates message generation via `generateWAMessage()` ([src/Utils/messages.ts#L666-L672]), content normalization in `generateWAMessageContent()` ([src/Utils/messages.ts#L395-L795]), and encrypted delivery through `relayMessage()` ([src/Socket/messages-send.ts#L16-L31]). This guide covers the canonical content shapes for each message type with runnable TypeScript examples.

## Sending Text Messages with Baileys

The simplest message type requires only a `text` property. Baileys detects this path at `if (hasNonNullishProperty(message, 'text'))` ([src/Utils/messages.ts#L996-L1005]).

```typescript
await sock.sendMessage('1234567890@s.whatsapp.net', { 
  text: 'Hello from Baileys!' 
})

```

### Link Preview Options

Baileys automatically fetches link previews for URLs in your text. Control this behavior:

```typescript
await sock.sendMessage(jid, { 
  text: 'Check out https://github.com/WhiskeySockets/Baileys' 
  // linkPreview: false // disable if needed
})

```

The link preview logic is implemented in [`src/Utils/link-preview.ts`](https://github.com/WhiskeySockets/Baileys/blob/main/src/Utils/link-preview.ts).

## Sending Media Messages (Image, Video, Audio, Document, Sticker)

Media messages use the `AnyMediaMessageContent` union type ([src/Types/Message.ts#L74-L104]). Baileys branches on media type at lines L1026-L1065 in `generateWAMessageContent()`.

| Media Type | Required Field | Key Optional Fields |
|------------|---------------|---------------------|
| **Image** | `image: WAMediaUpload` | `caption`, `jpegThumbnail`, `width`, `height` |
| **Video** | `video: WAMediaUpload` | `caption`, `gifPlayback`, `ptv` (picture-in-video), `width`, `height` |
| **Audio** | `audio: WAMediaUpload` | `ptt` (push-to-talk), `seconds` |
| **Document** | `document: WAMediaUpload`, `mimetype` | `fileName`, `caption` |
| **Sticker** | `sticker: WAMediaUpload` | `isAnimated`, `width`, `height` |

### Image Example

```typescript
await sock.sendMessage(jid, {
  image: { url: './photo.jpg' },  // WAMediaUpload: URL, Buffer, or Stream
  caption: 'Check this out!'
})

```

### Document with Custom Filename

```typescript
await sock.sendMessage(jid, {
  document: { buffer: pdfBuffer },
  mimetype: 'application/pdf',
  fileName: 'report-2024.pdf',
  caption: 'Monthly report'
})

```

### Voice Note (Push-to-Talk)

```typescript
await sock.sendMessage(jid, {
  audio: { url: './voice.ogg' },
  ptt: true,  // displays as waveform, not playable audio
  seconds: 15
})

```

`WAMediaUpload` accepts URLs, Buffers, or Streams—Baileys handles upload to WhatsApp's CDN internally.

## Sending Location Messages with Baileys

Location messages use the `WALocationMessage` interface, processed at `else if (hasNonNullishProperty(message, 'location'))` ([src/Utils/messages.ts#L1038-L1040]).

```typescript
await sock.sendMessage(jid, {
  location: {
    degreesLatitude: 37.7749,
    degreesLongitude: -122.4194,
    name: 'San Francisco',
    address: 'Golden Gate Bridge'
  }
})

```

The `name` and `address` fields are optional but recommended—they appear in the WhatsApp location card header.

## Sending Contact Cards (vCard)

Contact messages wrap vCard data in the `contacts` structure, handled at lines L1042-L1052 ([src/Utils/messages.ts]).

```typescript
await sock.sendMessage(jid, {
  contacts: {
    displayName: 'Business Contacts',  // optional section header
    contacts: [
      {
        displayName: 'John Doe',
        vcard: `BEGIN:VCARD
VERSION:3.0
FN:John Doe
ORG:Acme Inc.
TEL;type=CELL;type=VOICE;waid=1234567890:1234567890
EMAIL:john@example.com
END:VCARD`
      }
    ]
  }
})

```

Multiple contacts can be included in the `contacts.contacts` array. The `waid` parameter in the vCard TEL field should match the WhatsApp ID for proper linking.

## Creating and Sending Polls

Polls use `PollMessageOptions` ([src/Types/Message.ts#L136-L144]), processed at `else if (hasNonNullishProperty(message, 'poll'))` ([src/Utils/messages.ts#L1077-L1085]).

```typescript
await sock.sendMessage(jid, {
  poll: {
    name: 'Pick a fruit',
    selectableCount: 1,           // 0 = unlimited choices, 1+ = limit
    values: ['🍎 Apple', '🍊 Orange', '🍌 Banana'],
    messageSecret: crypto.randomBytes(32)  // optional: encrypts selections
  }
})

```

Baileys validates `selectableCount` against the values array size at lines L1079-L1084. Set `selectableCount: 0` for unlimited selections, or `>1` for multiple-choice limits.

## Complete Working Example

This script demonstrates all five message types sequentially. Replace authentication with your preferred Baileys auth method.

```typescript
import makeWASocket, { useMultiFileAuthState } from '@whiskeysockets/baileys'
import { Boom } from '@hapi/boom'
import { readFileSync } from 'fs'
import crypto from 'crypto'

async function main() {
  const { state, saveCreds } = await useMultiFileAuthState('./baileys-auth')
  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: true
  })

  sock.ev.on('creds.update', saveCreds)
  sock.ev.on('connection.update', ({ connection }) => {
    if (connection === 'open') console.log('Connected!')
  })

  const jid = '1234567890@s.whatsapp.net'

  // 1️⃣ Text message
  await sock.sendMessage(jid, { text: 'Hello from Baileys!' })

  // 2️⃣ Image with caption
  await sock.sendMessage(jid, {
    image: { url: './assets/demo.jpg' },
    caption: 'Photo demonstration'
  })

  // 3️⃣ Location pin
  await sock.sendMessage(jid, {
    location: {
      degreesLatitude: 40.7128,
      degreesLongitude: -74.0060,
      name: 'New York City',
      address: 'Manhattan, NY 10001'
    }
  })

  // 4️⃣ Contact card
  await sock.sendMessage(jid, {
    contacts: {
      contacts: [{
        displayName: 'Support Team',
        vcard: readFileSync('./assets/contact.vcf', 'utf-8')
      }]
    }
  })

  // 5️⃣ Interactive poll
  await sock.sendMessage(jid, {
    poll: {
      name: 'Preferred stack?',
      selectableCount: 1,
      values: ['MERN', 'PERN', 'LAMP', 'Django/DRF'],
      messageSecret: crypto.randomBytes(32)
    }
  })
}

main().catch(err => {
  if (err instanceof Boom) {
    console.error('WhatsApp error:', err.output.statusCode, err.message)
  } else {
    console.error(err)
  }
})

```

## Key Implementation Details from Source Code

Understanding Baileys' internal flow helps debug issues:

- **Message generation**: `generateWAMessage()` → `generateWAMessageContent()` builds protocol buffers
- **Type detection**: Uses `hasNonNullishProperty()` checks to branch on content keys (`text`, `image`, `video`, etc.)
- **Encryption**: `relayMessage()` in [`src/Socket/messages-send.ts`](https://github.com/WhiskeySockets/Baileys/blob/main/src/Socket/messages-send.ts) handles multi-device encryption and delivery
- **Type safety**: All content shapes are defined in [`src/Types/Message.ts`](https://github.com/WhiskeySockets/Baileys/blob/main/src/Types/Message.ts)—reference this for exact interfaces

## Summary

- **Text**: `{ text: string }` with optional `linkPreview` control
- **Media**: Use `image`, `video`, `audio`, `document`, or `sticker` keys with `WAMediaUpload` values
- **Location**: `{ location: { degreesLatitude, degreesLongitude, name?, address? } }`
- **Contact**: `{ contacts: { contacts: [{ displayName, vcard }] } }` with valid vCard 3.0 strings
- **Poll**: `{ poll: { name, selectableCount?, values, messageSecret? } }` for interactive voting

All message types route through `sock.sendMessage()`—Baileys abstracts protocol details, encryption, and device synchronization.

## Frequently Asked Questions

### What is the maximum size for media files in Baileys?

Baileys does not enforce size limits—WhatsApp's servers do. Typical limits are 16 MB for documents, 64 MB for most media in regular chats. The library streams large files automatically via `WAMediaUpload` stream support.

### How do I send a message to a group instead of an individual?

Use the group's JID format: `1234567890@g.us` instead of `1234567890@s.whatsapp.net`. The `sendMessage` API remains identical; only the JID changes.

### Can I combine multiple content types in one message?

No—WhatsApp's protocol enforces single-message-type payloads. To send text with media, use the `caption` field on media messages rather than a separate text property.

### Why does my poll not show secret ballot results?

Include `messageSecret: crypto.randomBytes(32)` in your `poll` object. Without this, poll selections are visible to the message sender. The secret enables end-to-end encryption of votes per `PollMessageOptions` in [`src/Types/Message.ts`](https://github.com/WhiskeySockets/Baileys/blob/main/src/Types/Message.ts).