Character limits & segments
SMS over GSM has a hard 160-character limit per segment for ASCII content. Longer messages are split into multiple segments, each billed as a separate SMS. Lisoloo computes the segment count at submit time and bills accordingly.
Segment table
Section titled “Segment table”| Length (characters) | Type | SMS count |
|---|---|---|
1–160 | Standard SMS | 1 |
161–320 | Long SMS (2-segment) | 2 |
321–480 | Long SMS (3-segment) | 3 |
481–640 | Long SMS (4-segment) | 4 |
| … | concatenated | …ceil(len / 153) after the first segment |
up to 1600 | Maximum | 10 |
For multi-segment messages the per-segment capacity drops from 160 to 153 characters — the extra 7 characters per segment are consumed by the User Data Header (UDH) that the carrier uses to reassemble the message on the handset.
A message longer than 1 600 characters is rejected with
1110 INVALID_FIELD_FORMAT at submit time.
Cost calculation
Section titled “Cost calculation”total_cost = total_recipients × segments_per_message × unit_price
unit_price is your merchant-level price per SMS segment in
currency, returned by GET /balance. A 200-character message to 50
recipients at $0.02 per segment costs 50 × 2 × 0.02 = $2.00.
Unicode and emoji
Section titled “Unicode and emoji”Messages containing characters outside the GSM 03.38 alphabet (any emoji, accented characters in some scripts, CJK, Arabic, …) are sent as UCS-2 (16-bit per character). UCS-2 segments cap at 70 characters single-segment, 67 characters per segment when concatenated. A single 🎉 anywhere in the body flips the entire message to UCS-2.
| Encoding | Single | Concatenated |
|---|---|---|
| GSM 7-bit | 160 | 153 |
| UCS-2 (any non-GSM char) | 70 | 67 |
If you don’t know your character set ahead of time, assume UCS-2 for cost estimation.
What the response tells you
Section titled “What the response tells you”POST /send returns the computed segment count for the batch:
{ "data": { "message_id": "...", "total_recipients": 50, "total_messages": 100, "total_cost": 2.00, "currency": "USD", "status": "pending" }}total_recipientsislen(to).total_messagesistotal_recipients × segments_per_message.total_costistotal_messages × unit_price, deducted from your balance at submit time.
For scheduled or recurring sends the totals reflect the entire schedule, not per-occurrence.
Pre-computing on your side
Section titled “Pre-computing on your side”If you want to estimate cost before calling POST /send, count
segments client-side:
def segments(message: str) -> int: is_gsm = all(c in GSM_03_38 for c in message) n = len(message) if is_gsm: return 1 if n <= 160 else (n + 152) // 153 return 1 if n <= 70 else (n + 66) // 67The full GSM 03.38 character table is at 3GPP TS 23.038.
See also
Section titled “See also”- Sending types — segment count multiplies across
scheduled_datesandrecurring_schedule - Check balance — query
unit_priceandavailable_sms - Rate limits — segments don’t count against rate-limit; requests do