BroadNet
The JournalEngineering
Engineering

SMS message encoding and segmentation: GSM-7, Unicode (UCS-2) and multipart messages.

An SMS carries 140 bytes: 160 GSM-7 characters, or just 70 in Unicode (UCS-2). How encoding, the UDH and segmentation set your SMS character limit and cost.

10 min read
Engineering · Issue 19
10 min read

he SMS character limit depends entirely on encoding. Every SMS carries a fixed 140-byte payload, so a message using the GSM-7 default alphabet fits 160 characters, while one containing any non-GSM-7 character — an emoji, an Arabic letter, a curly quote — switches to 16-bit UCS-2 and fits only 70. Longer text splits into separately billed segments.

Want the numbers for a specific message? Paste it into the SMS segment calculator to see the encoding, segment count and character budget, or check exactly which characters force Unicode with the GSM-7 / Unicode checker.

Everything derives from 140 bytes

An SMS message body — the field 3GPP calls the TP-User-Data — is capped at 140 octets, or 1,120 bits. That single constraint drives every character count you will ever see quoted. How many characters fit is simply 1,120 divided by the number of bits each character consumes, so the only real question is which encoding your text triggers. Two encodings matter in practice: GSM-7 and UCS-2.

GSM-7 vs UCS-2: two ways to pack the same 140 bytes

GSM-7: the 7-bit default alphabet

GSM-7 is the default SMS alphabet defined in 3GPP TS 23.038. It encodes each character in 7 bits, so 1,120 bits hold 160 characters — the classic single-SMS limit. Its table covers the Latin letters, digits, common punctuation and a handful of symbols. Crucially, a small set of characters sits in a basic character set extension and each costs two septets, because it is encoded as an escape byte followed by the character. Those characters are ^ { } \ [ ] ~ | and the euro sign €. A message padded with euro signs therefore fits only 80 characters in a single SMS, not 160.

You can see exactly which characters in your text are in-alphabet, extension, or out-of-alphabet with the GSM-7 / Unicode checker before you send.

UCS-2: 16-bit Unicode

When the text contains even one character that GSM-7 cannot represent, the whole message is re-encoded in UCS-2, a 16-bit fixed-width Unicode encoding. At 16 bits per character, 1,120 bits hold just 70 characters. There is no partial upgrade and no mixing: a single out-of-alphabet character halves your budget from 160 to 70. This is not a bug — an SMS declares one encoding for its entire body, so the sender must pick the one that can represent every character present.

The character limits, side by side

EncodingBits per characterSingle SMSPer segment (multipart)
GSM-7 (default alphabet)7160153
UCS-2 (16-bit Unicode)167067

The per-segment figures are lower than the single-message limits because a concatenated message spends part of its 140 bytes on a header, covered next. Note that the extension characters above still cost two GSM-7 positions inside a segment too, so a segment full of square brackets or euro signs holds far fewer than 153 visible characters.

How multipart (concatenated) SMS works

Text longer than a single message is not truncated — the sending SMSC splits it into segments, each a self-contained SMS, and the receiving handset stitches them back together before display. Coordination is handled by a User Data Header (UDH) placed at the front of each segment's payload, defined in 3GPP TS 23.040. For standard concatenation the UDH is 6 bytes, and it carries a reference number shared by every part, the total part count, and this part's sequence number so the handset can reassemble them in order.

snippet
UDH for a concatenated SMS = 6 bytes
05 00 03 RR TT SS
| | | | | |
| | | | | +- sequence number of this part (1..TT)
| | | | +---- total number of parts (TT)
| | | +------- reference number (identical on every part)
| | +---------- length of this information element = 3
| +------------- IEI = 00 (concatenated SMS, 8-bit reference)
+---------------- UDH length = 05 (5 more bytes follow)

Those 6 bytes come out of the same 140-byte payload, leaving 134 bytes for text. That is why a multipart message holds 153 GSM-7 characters per segment (the header is septet-aligned, consuming seven of the 160 positions) and 67 UCS-2 characters per segment (134 bytes ÷ 2). Some platforms use a 7-byte UDH with a 16-bit reference number, which drops those figures to 152 and 66. The SMS segment calculator shows the exact split for any message length.

Why one emoji or one Arabic character changes everything

This is where senders get surprised. Because a single non-GSM-7 character forces the entire message to UCS-2, a 150-character English notification that fits comfortably in one segment can silently drop to a 70-character budget — and split into three segments — the moment someone pastes in an emoji or a smart curly quote from a word processor. The visible character count did not change; the encoding did.

For Arabic-market senders this is not an edge case, it is the default. Arabic script is not in the GSM-7 alphabet, so every Arabic SMS is UCS-2 from the first character: 70 characters in a single message, 67 per segment thereafter. A bilingual Arabic-and-English message, or a branded Arabic OTP, crosses into multiple segments quickly. Teams sending across the GCC, KSA, UAE and Egypt should budget every Arabic template in UCS-2 units from the start, not GSM-7 ones.

Common characters that silently force a whole message to UCS-2:

  • Emoji of any kind, including a single trailing 😀 in a marketing message.
  • Arabic, Hebrew, Cyrillic, Greek, Chinese and other non-Latin scripts.
  • Curly quotation marks and apostrophes (’ ‘ “ ”) pasted from word processors.
  • En- and em-dashes (– —), the ellipsis (…), and the non-breaking space.
  • Many accented Latin letters that are not present in the GSM-7 table.

What segmentation costs you

Every segment is rated and billed as a separate message. A 160-character GSM-7 alert is one billable SMS; add one character and it becomes two segments — up to 306 characters of capacity — billed as two. An Arabic OTP of just 75 characters is already two UCS-2 segments, and therefore two messages, even though it looks short. At OTP and campaign scale, encoding discipline is a direct line item, not a cosmetic detail.

  1. Keep transactional templates inside one segment — 160 GSM-7 or 70 UCS-2 — wherever the language allows.
  2. Strip accidental Unicode: normalise curly quotes, dashes and non-breaking spaces to their GSM-7 equivalents before sending.
  3. Validate encoding and segment count at build time, not after the invoice, using a checker in your send pipeline.
  4. Budget Arabic and other non-Latin templates in UCS-2 units (70 / 67) from the outset.
  5. Trim variable content — URLs, long merchant names — that can push a message over a segment boundary at runtime.
BroadNet's SMS API reports the resolved encoding and segment count on every message before it is sent and in each delivery receipt, so you can see and control segmentation in production rather than discovering it on the bill. Full request and response details are in the developer docs.

Frequently asked questions

How many characters is one SMS?

One SMS carries a 140-byte payload. Using the GSM-7 default alphabet that is 160 characters; if the text contains any character outside GSM-7 — an emoji, an accented or Arabic letter, a curly quote — the message switches to UCS-2 encoding and holds 70 characters. Longer text is split into concatenated segments of 153 (GSM-7) or 67 (UCS-2) characters each.

Why is my SMS counted as only 70 characters?

Because something in the text is not in the GSM-7 alphabet, so the whole message was re-encoded as 16-bit UCS-2, which fits only 70 characters. The usual culprits are emoji, non-Latin scripts, and curly quotes, dashes or non-breaking spaces pasted from a word processor. Replace or remove that character and the message returns to the 160-character GSM-7 budget.

What is UCS-2 encoding in SMS?

UCS-2 is the 16-bit fixed-width Unicode encoding SMS uses when text cannot be represented in the 7-bit GSM-7 alphabet. Two bytes per character means the 140-byte payload holds 70 characters in a single message, or 67 per segment in a multipart message. Any Arabic, emoji or other non-GSM-7 character in the body forces the entire SMS to UCS-2.

Why did my message split into two?

The text exceeded the single-message limit for its encoding — 160 characters in GSM-7 or 70 in UCS-2 — so it was sent as a concatenated (multipart) message. Each segment carries a 6-byte User Data Header for reassembly, dropping capacity to 153 (GSM-7) or 67 (UCS-2) characters per part, and each segment is billed as a separate message.

References

Was this useful?

How we write and review content

Written by

BroadNet Editorial Team

The Editorial Team publishes the BroadNet blog. Articles are written with BroadNet's regulatory affairs, product, engineering, industry research and operator solutions teams, and reviewed under our editorial standards.

The Journal, by email

One essay a month. Nothing else.

Subscribe and we'll send the next piece — engineering, regulation, or industry — the day it ships. No drip campaigns, no product pitches, no third-party sharing. Unsubscribe in one click.

We send one email a month. Unsubscribe anytime. See our privacy policy.

What you'll get
  • Long-form, not link bait
    Six to eleven minutes of focused writing on a single topic.
  • Written by operators
    Engineers, regulatory leads, and product writing in-house.
  • Region-aware
    MENA-grounded view on regulators, operators, and channel mix.
  • Once a month
    No drip campaign. One essay when there is one to share.
Stop reading. Start shipping.

Most of what we write we learned in production.

If this piece made you nod, we should probably talk. Bring the use case, the volumes, the markets — we'll come back with routing, pricing, and a reference customer you can call.

$ curl -X POST https://api.broadnet.me/sms/sendSms