Quick answer: An SMS is not billed per message — it is billed per segment, and how long a segment is depends on which of two encodings the body qualifies for. GSM-7 (the legacy 7-bit alphabet) carries up to 160 characters per segment; UCS-2 (the Unicode fallback) carries only 70. The decision rule is unforgiving: one character outside the GSM-7 table re-encodes the entire message as UCS-2, so a single emoji or curly quote can more than double the billed segment count of a long message. SMS network operators charge per segment at the same rate for either encoding — the cost lever is segment count, and the encoding decides the segment count. On Devotel Orbit, the SMS compose dialog counts both live as you type and the free SMS segment & cost calculator does the same without a login, so you can see the price before anything sends.
Segment mechanics — how an SMS becomes one or more billable units
The SMS standard (3GPP TS 23.038) defines two wire encodings for the message body, and every handset and SMSC understands both:
- GSM-7 — the 7-bit default alphabet. It holds 128 basic characters (uppercase and lowercase ASCII letters, digits, common punctuation, whitespace, plus a block of national characters — é, è, ß, Ä, Ö, Ü, å, the Greek capitals Δ Φ Γ Λ Ω Π Ψ Σ Θ Ξ, and a few others) and a 10-character extension table reached by an escape sequence:
^, curly brackets, square brackets,~,\,|, the euro sign€, and form feed. Extension characters cost 2 septets each — the escape byte plus the character — so{consumes two of your 160. When the body fits entirely in this alphabet, a standalone SMS carries 160 characters. - UCS-2 — the Unicode fallback, 2 bytes per character, used when anything in the body is not representable in GSM-7. A standalone UCS-2 SMS carries 70 characters, because the raw payload is capped at 140 bytes and each character now takes two of them.
The second wrinkle is concatenation. A message longer than one segment is rebuilt on the handset from multiple SMSes, and each part of a concatenated message spends 7 bytes on a User Data Header (the concatenation metadata) — so the per-segment budget shrinks:
- GSM-7 multipart: 153 characters per segment (not 160)
- UCS-2 multipart: 67 characters per segment (not 70)
This is why a 161-character GSM-7 message bills as two segments, not "160 ÷ 160 rounded up": the second part of a long message packs into 153-char chunks. Plain ASCII text — the kind most transactional and marketing messages in English consist of — stays in GSM-7 naturally, which is what makes the UCS-2 trigger list below worth knowing cold.
What forces the switch to UCS-2
The encoding decision is single-bit and body-wide: scanning left to right, the first character that is not in the GSM-7 basic or extension alphabet moves the entire message to UCS-2. The usual culprits:
- Emoji. Every emoji is outside GSM-7. One 🙂 in a 300-character GSM-7 body re-encodes all 300 characters, and 300 ÷ 67 rounds up to 5 segments where GSM-7 needed 2 (300 ÷ 153).
- CJK and non-Latin scripts. Chinese, Japanese, Korean, Arabic, Cyrillic, Hebrew, Devanagari — none of these is in the default alphabet. Messages written in them are UCS-2 by construction; the GSM-7 optimization is simply not available there.
- Accented characters beyond the GSM-7 block. The default alphabet includes some accented Latin (é, ß, ü) but not others — Ł, Ś, Ż, the œ ligature, and most of the extended Latin block force UCS-2. Polish SMS copy is a classic case: "zażółć" is UCS-2, "juz" would be GSM-7.
- Typographic punctuation from rich editors. Curly quotes ("…"), em/en dashes, ellipsis glyphs, non-breaking spaces, and zero-width characters paste in from word processors and chat tools and flip the encoding silently.
Two details most operators miss until they hit them in a bill:
- Normalisation helps, legitimately. Orbit normalises the body (NFC) before deciding the encoding, so a precomposed
éand its decomposed twin (e+ combining accent) count identically — both resolve to the single GSM-7 codepoint. Invisible zero-width characters are stripped for the same reason. This is a fair adjustment that benefits the sender, not a loophole. - Template variables re-run the detection per recipient.
"Hi {{first_name}}"is clean ASCII — GSM-7, 1 segment. Rendered for a recipient named Şükrüye, the Ş-class characters turn that send UCS-2. The correct segment count for a templated campaign is the worst case across recipients, not the count of the raw template.
The encoding switch cost — one emoji, double the segments
Carriers price per segment, and on Orbit the per-segment rate for SMS is the same for GSM-7 and UCS-2 — encoding itself never changes the unit price. What changes is how many units the body consumes. Run the arithmetic on a typical long promotional body:
| Body | Encoding | Segment math | Billed segments |
|---|---|---|---|
| 140 ASCII chars | GSM-7 | ≤ 160 single | 1 |
| 140 ASCII chars + 1 emoji | UCS-2 | 141 ÷ 67 → ceil | 3 |
| 300 ASCII chars | GSM-7 | 300 ÷ 153 → ceil | 2 |
| 300 ASCII chars + curly apostrophe | UCS-2 | 300 ÷ 67 → ceil | 5 |
At a flat per-segment price of, say, $0.008 per segment, that curly apostrophe took the message from $0.016 (2 segments) to $0.040 (5 segments) — a 2.5× segment-count jump (2 → 5), before carrier surcharges. UCS-2 segments fit about 2.29× fewer characters than GSM-7 segments (160 ÷ 70 ≈ 2.286 for standalone messages; 153 ÷ 67 ≈ 2.284 for multipart ones). For long bodies, that per-segment capacity gap compounds through segment rounding into roughly 2×–3× the billed segment count, which is how the 2.5× example lands. Multiplied across a 100,000-recipient campaign, the difference is $1,600 vs $4,000 at that same $0.008 rate — a $2,400 swing caused by one character in a greeting.
The corollary is just as important: the switch costs you nothing when the body is short either way. A 50-character message with an emoji is one segment in both encodings, so the UCS-2-per-segment price equals the GSM-7 price and the total is unchanged. Brevity is the cheapest emoji policy; the trap is long bodies where UCS-2's shrunken segment size flips the count.
See the price before you send — Orbit's preview surfaces
Orbit treats segment counting as tenant-owned infrastructure: the same counter that bills your API sends drives the preview surfaces, so what you see is what your wallet is charged.
- The SMS compose dialog counts live. As you type, the dialog shows the detected encoding (GSM-7 or UCS-2), the character count, how many segments the body splits into, and the estimated cost at your per-segment rate. When a keystroke flips the body to UCS-2, a transient toast names the exact character that forced it — "🙂 forces Unicode encoding — UCS-2 fits 70 chars/seg (vs 160)" — and tells you whether that actually changed the price or just the encoding. If the segment count is the same either way, the dialog says so rather than inventing a saving.
- A free calculator outside the login. The SMS segment & cost calculator on /tools is public: paste a body, pick a country and recipient count, and it returns the encoding, the segment split, and the total estimated send cost from the published rate card. It runs the same segment logic your billed sends run against, so a "what would this campaign cost" decision can be made before you open the compose dialog.
- The published rate card. Per-country and per-operator SMS rates on the pricing page give you the multiplication factor — the segment count comes from this explainer's math; the price per segment comes from the card. Two numbers, one invoice.
Because template bodies change per recipient, the billing path counts segments on the rendered body, not the raw template — the count the wallet charges is the count of what actually goes on the wire, which is what protects you from the Şükrüye case above.
Best practices — keep GSM-7 or pay for UCS-2 on purpose
- Preview before send, every time. For a one-off send the compose dialog is the preview; for a campaign, run the worst-case recipient through the calculator first. The price decision belongs to you, but the information to make it should not require a test send.
- Use the substitution rules. Most UCS-2 triggers have a GSM-7 equivalent: curly quotes →
', em dash →-, ellipsis →..., œ →oe, and accented-but-non-GSM-7 letters like ó →oif your brand tolerates it. The compose dialog will sanitise the body for you on demand; for API sends, do the same mapping in your template layer and let the live preview confirm the encoding flipped back. - Keep emoji handful and purposeful. One emoji in a short transactional message is free (same 1-segment cost either way). The same emoji in a 300-character promotional message is a deliberate 2.5×-the-segments line item — fine as a brand choice, expensive as an accident.
- Fallback to a rich channel when UCS-2 gets long. If the message genuinely needs rich content — CJK body text, multiple emoji, attachments — SMS is the wrong-shaped channel: RCS carries it natively with SMS fallback, and per-message rich-channel pricing often beats a 5-segment UCS-2 SMS. Keep SMS for the ASCII-shaped bulk it prices best at.
- Audit templates for hidden Unicode. The expensive character is usually pasted, not typed — an em dash from a doc, a curly quote from a CMS. Once a quarter, run your top templates through the calculator and look for UCS-2 results on bodies you expected to be ASCII.
Frequently asked questions
Is UTF-8 ever used for SMS?
No — SMS bodies are GSM-7 or UCS-2 on the wire. UTF-8 shows up inside APIs and databases (including the Orbit API's JSON body), but the SMSC encodes the body as GSM-7 or UCS-2, which is why the segment math above and not UTF-8 byte length decides your price.
Do GSM-7 extension characters change the encoding?
No — characters like {, }, [, ], \, |, ^, ~, and € stay in GSM-7 but cost 2 characters each (an escape byte plus the character). They eat into your 160-char budget without triggering the UCS-2 switch, so a body full of braces can quietly blow past one segment while staying "GSM-7."
Does Orbit charge a different per-segment rate for UCS-2?
No — the per-segment SMS rate is encoding-independent. UCS-2 costs more only because its 70/67-char segment fits fewer characters, so the same body occupies more segments. A short body that fits one segment either way costs exactly the same in both encodings.
When does a message use more than 10 segments?
On Orbit, never — the counter caps at 10 segments (1,530 GSM-7 characters or 670 UCS-2 characters) and flags the body as truncated at that point rather than silently expanding the bill. Messages that long belong on a rich channel anyway; email and RCS are built for it.
Will normalising accents myself ever be wrong?
Removing accents is a brand decision, not an encoding rule — some markets read unaccented copy as careless, and GSM-7 includes é, ß, ü and friends natively. Normalise typography (curly quotes, dashes, ellipses) freely; normalise language characters only where your brand voice accepts the unaccented form.