← All posts

Why one accent can triple your SMS bill

A 160-character text is one message. Add a lowercase ç and it becomes three. How SMS segments actually work, and what we do to keep the count honest.

Every SMS price you have ever seen, ours included, is quoted per segment rather than per message. Ours is three cents Canadian. Most people find out what a segment is by reading an invoice, which is the worst possible moment to learn it.

The rules behind it are old, slightly absurd, and completely deterministic. Once you know them, you can predict every charge before you press send.

Where 160 comes from

SMS was designed to ride in the spare capacity of the signalling channel phones already used to talk to towers, and the space going spare was 140 bytes. To fit more text into that, the standard uses a 7-bit alphabet called GSM-7 instead of the 8-bit characters you would expect. 140 bytes at 7 bits each works out to exactly 160 characters. That is the whole derivation. There is no tidier reason for the number.

Go one character over and the message has to be split, and each part then carries a small header telling the receiving phone how to staple the pieces back together. That header takes up seven characters' worth of space in every part. So a message that spills past 160 is not billed in chunks of 160. It is billed in chunks of 153.

  • 160 characters or fewer is one segment
  • 161 to 306 is two
  • 307 to 459 is three, and it carries on in steps of 153

Which means a 161-character message costs exactly double a 160-character one. At any real volume, cutting a single word is worth money.

Nine characters that quietly count twice

GSM-7 ran out of room for symbols people actually type, so nine of them were exiled to an extension table and travel as two characters each:

  • The euro sign €
  • Square brackets [ and ]
  • Curly braces { and }
  • The tilde ~, the pipe |, the caret ^ and the backslash \

A 160-character message with one euro sign in it is two segments. Nothing about it looks long. It just is.

The 70-character cliff

The bigger drop happens when your text contains a character GSM-7 does not have at all. There is no partial fallback and no per-character penalty. One offending character re-encodes the entire message to UCS-2, where every character takes 16 bits, and the limit falls from 160 to 70. Split parts get 67.

Emoji are the obvious culprit. Take a real appointment reminder:

Reminder: your appointment with Dr. Patel is tomorrow at 2:00pm. Reply STOP to opt out.

That is 87 characters and one segment. Add a thumbs up on the end and it becomes 90 characters and two segments, because 90 is more than 70. The emoji did not cost you two characters. It cost you a whole second message.

The part that catches Canadian senders

The less obvious culprit, and the one that matters if you send anything in French, is accented letters. GSM-7 includes some and omits others, and the selection follows no pattern you can reason your way to. We ran every accented character we could think of through our own segment counter. These are free:

  • é è à ì ò ù
  • ä ö ü ñ å ø æ ß
  • É Ä Ö Ü Ñ Å Ø Æ Ç

And these drop the whole message to 70 characters:

  • ç ê î ô û ë ï
  • â Â Ê Î Ô Û Ë Ï
  • È À Ì Ò Ù

Read those two lists next to each other. É is in the alphabet and È is not. Ç is in the alphabet and ç is not. Every circumflex is out, which takes « être », « prêt », « hôpital », « coût » and « s'il vous plaît » with it. So is À, which is how a good many French sentences begin.

To put a number on it: 160 letter A's followed by one lowercase ç is 161 characters, and it bills as three segments. Not two. Three, because 161 characters at 67 per part rounds up to three.

What we do about it

Carriers are not entirely heartless here. Ours applies something called smart encoding, which swaps a few hundred Unicode look-alikes for their plain equivalents before the message is split. Curly quotes become straight ones, the long dash becomes a hyphen, the single ellipsis character becomes three periods, and non-breaking spaces become ordinary ones. So this:

text
Written:  Don’t forget your ID … pickup closes at 6pm.
Billed:   Don't forget your ID ... pickup closes at 6pm.

That matters more than it sounds. Text pasted out of a word processor is riddled with curly quotes, and without the swap every one of them would drop the message to 70 characters. We had one 1,312-character message that a naive counter estimated at 20 segments. It went out as 9.

The important half is that we count it the same way. Our segment counter applies exactly the replacements the carrier does, so the number in the dashboard preview is the number on the bill. That sounds obvious. It is not: an estimator that skipped smart encoding would have quoted that message at more than double what it actually cost.

The ceiling

Carriers refuse to split a message past 10 parts. We check before sending, so an over-long body comes back as an error and nothing is charged. There is no scenario where you pay for a message that was never going to arrive.

Practical rules

  • Write in plain ASCII where the message allows it, and let smart encoding tidy up the typography you cannot avoid
  • Skip emoji in transactional messages. One of them can double the cost of every send built on that template
  • If you send in French, watch for ç, circumflexes and a leading À. A rewrite that avoids them can halve a template's cost
  • Count the characters in your templates, not in your test message. The 160 boundary bites at scale, not in testing
  • The dashboard shows the segment count as you type, using the same function that bills you

None of this is HonkIO being clever. It is an encoding decision from the 1980s that the whole industry still bills against. The only real choice a provider has is whether to explain it to you or let you find it on the invoice.

The pricing page has the short version in the FAQ, and the dashboard preview will give you the count for any body you paste into it. If a number ever looks wrong, tell us and we will go through it with you.