# SMS character limits and segment counting

Every SMS is carried in fixed-size units called segments. Each segment is one billing unit, so message length directly affects cost. How many characters fit in a segment depends on the encoding Bird picks for your body, and a single character outside the default alphabet can cut the capacity in half.

## How encoding is chosen

Bird inspects every character in your message body before sending:

- If every character belongs to the GSM-7 alphabet (the standard 7-bit character set defined by GSM 03.38), the message uses **GSM-7** encoding.
- If any single character falls outside GSM-7, the entire message switches to **UCS-2** (16-bit Unicode encoding).

There is no per-character mixing. One emoji, one CJK character, or one curly quote converts the whole body to UCS-2.

## Segment limits

| Encoding | Single segment | Per segment (multipart) |
| -------- | -------------- | ----------------------- |
| GSM-7    | 160 characters | 153 characters          |
| UCS-2    | 70 characters  | 67 characters           |

When a message is longer than one segment, it is split into multiple segments. Each segment in a multipart message reserves a few bytes for a reassembly header (the User Data Header), which is why the per-segment capacity drops from 160 to 153 for GSM-7, and from 70 to 67 for UCS-2.

A 161-character GSM-7 message takes 2 segments (ceil(161 / 153) = 2), not one full segment plus a tiny second one. The split divides the encoded body evenly across segments.

## Maximum message length

Bird accepts up to **12 segments** per message. That translates to:

- **GSM-7**: 1,836 characters (12 x 153)
- **UCS-2**: 804 characters (12 x 67)

A body that exceeds 12 segments is rejected with a `422` error. Bird never truncates a message silently.

## The GSM-7 character set

GSM-7 covers the characters most Latin-script messages need:

- Letters A-Z, a-z
- Digits 0-9
- Common punctuation: `@`, `£`, `$`, `!`, `"`, `#`, `%`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `-`, `.`, `/`, `:`, `;`, `<`, `=`, `>`, `?`, space, newline
- Some accented characters from Western European languages (the accent in "cafe" is GSM-7, for instance)

### Extension-table characters

A handful of characters are part of GSM-7 but live on an extension table. Each one costs **2 septets** instead of 1, so they count double against the segment limit:

`€`, `[`, `]`, `{`, `}`, `\`, `~`, `^`, `|`

This matters at the boundary. If you write 159 regular characters followed by one euro sign, the encoded size is 161 septets (159 + 2), which pushes the message into 2 segments, even though it looks like 160 characters.

## Characters that trigger UCS-2

Any character outside GSM 03.38 forces the entire message to UCS-2. The most common triggers:

- **Emoji**: each emoji is encoded as a surrogate pair (4 bytes). A single segment fits 35 emoji; the 36th pushes the message to 2 segments.
- **CJK characters** (Chinese, Japanese, Korean)
- **Arabic, Thai, Hindi**, and other scripts outside the GSM-7 alphabet
- **Curly ("smart") quotes**: `"` `"` `'` `'` (the straight versions `"` and `'` are GSM-7)

Common accented Latin characters (like e with an accent in "cafe", or u with an umlaut) are part of the GSM-7 set and do not trigger UCS-2.

## Reading segment counts from the API

Every SMS response includes a `segments` object that reports what Bird calculated:

```json
{
  "segments": {
    "count": 1,
    "encoding": "GSM_7BIT",
    "characters": 64
  }
}
```

- `count`: the number of billable segments
- `encoding`: `GSM_7BIT` or `UCS2`
- `characters`: the number of characters (Unicode code points) in the body

The `count` is the number you are billed for. Check it in the response or in the [SMS log](/docs/guides/sms/sms-log) to verify your messages land where you expect.

## Keeping messages to one segment

A few habits that prevent accidental multi-segment sends:

- Replace curly quotes with straight quotes. Word processors and some phones auto-replace `"` with `"` `"`, which forces UCS-2 and halves your capacity.
- Skip emoji in transactional or authentication messages where segment count matters.
- Watch extension-table characters (`€`, `{`, `}`, `[`, `]`, `\`, `~`, `^`, `|`). Each one eats two character slots.
- If you write in a non-Latin script (CJK, Arabic, Thai), plan for the UCS-2 limits from the start: 70 characters single-segment, 67 per segment when split.
- Use URL shorteners for links. A URL can consume 50+ characters of a 160-character budget.