Expertise technical

Calculate the exact number of SMS segments before sending: formula and code (PHP/JS/Python)

Calculate number of SMS segments before sending: technical guide with code examples for developers in Morocco.

Calculate the exact number of SMS segments before sending: formula and code (PHP/JS/Python)
Table of Contents
  1. One of the most common pitfalls when integrating an [SMS API in Morocco](/fr/api-sms-maroc/) is unexpected overcharging related to encoding. You send a campaign of 10,000 messages in Darija, and your provider charges you 30,000 credits. For what ? Because SMS is not billed "per message", but "per segment".
  2. The formula for calculating segments
  3. Automatically detect GSM-7 vs UCS-2 in code
  4. Snippet PHP (Ready to use)
  5. Snippet Node.js / JavaScript

One of the most common pitfalls when integrating an [SMS API in Morocco](/fr/api-sms-maroc/) is unexpected overcharging related to encoding. You send a campaign of 10,000 messages in Darija, and your provider charges you 30,000 credits. For what ? Because SMS is not billed "per message", but "per segment".

If you are building an in-house CRM or a business application, you must definitely show your users the number of segments they are about to consume before they click “Send”.

Here is the technical specification (GSM 03.38) and code to implement a robust segment counter in your applications.

The formula for calculating segments

An SMS is limited by the telecom network to a weight of 140 octets (bytes). The character capacity depends on how these bytes are used (the encoding):

1. GSM-7 encoding (Standard Alphabet)

Used for classic Latin characters (a-z, A-Z, 0-9) and some basic punctuation marks.

  • Each character takes 7 bits.
  • Maximum size for 1 segment: 160 characters.
  • Size if concatenated (> 1 segment): 153 characters per segment (7 characters are reserved for the User Data Header - UDH, which allows the phone to put the pieces together).

2. UCS-2 (Unicode) encoding

Required if your message contains a single Arabic character, an emoji (🚀), or a complex accent (œ).

  • Each character takes 16 bits.
  • Maximum size for 1 segment: 70 characters.
  • Size if concatenated (> 1 segment): 67 characters per segment (3 characters reserved for UDH).

Automatically detect GSM-7 vs UCS-2 in code

The calculation algorithm takes place in 3 steps:

  1. Analyze each character of the text.
  2. If all characters belong to the GSM-7 alphabet, use the limit of 160/153.
  3. If a single character does not belong there, force the UCS-2 alphabet and use the limit of 70/67.

Note: Some "extended" GSM-7 characters (like €, [, ], ~) count double. A good function must take them into account.

Snippet PHP (Ready to use)

Here is a lightweight PHP implementation, perfect for Laravel backends:

php
function calculateSmsSegments($text) {
    // Alphabet GSM-7 standard + Extension
    $gsm7Chars = "@£\$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà";
    $gsm7Extended = "^{}\\[~]|€";
    
    $isGSM = true;
    $length = 0;
    
    // Détection de l'encodage et calcul de la longueur
    $chars = preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY);
    foreach ($chars as $char) {
        if (mb_strpos($gsm7Extended, $char) !== false) {
            $length += 2; // Compte double
        } elseif (mb_strpos($gsm7Chars, $char) !== false) {
            $length += 1;
        } else {
            // Caractère hors GSM-7 trouvé (ex: Arabe, Emoji)
            $isGSM = false;
            $length = mb_strlen($text, 'UTF-8');
            break;
        }
    }
    
    if ($isGSM) {
        if ($length <= 160) return 1;
        return ceil($length / 153);
    } else {
        if ($length <= 70) return 1;
        return ceil($length / 67);
    }
}

// Tests
echo calculateSmsSegments("Test simple GSM7"); // Retourne 1
echo calculateSmsSegments("Test en arabe مرحبا"); // Retourne 1 (passe en UCS2, mais <70)
echo calculateSmsSegments(str_repeat("مرحبا بكم في خدمة الرسائل القصيرة", 3)); // Retourne 2 ou 3 selon la longueur exacte

Snippet Node.js / JavaScript

For your React/Vue frontend (to display the live counter while typing):

javascript
function getSmsSegments(text) {
    const gsm7Regex = /^[@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"\#¤%&'()*+,\-.\/0-9:;<=>?¡A-ZÄÖÑܧ¿a-zäöñüà\^\{\}\\[~\]|€]*$/;
    
    // Détecter si le texte est entièrement en GSM-7
    const isGsm7 = gsm7Regex.test(text);
    
    // Calcul de la longueur (les caractères étendus comme € comptent pour 2)
    let length = text.length;
    if (isGsm7) {
        const extendedRegex = /[\^\{\}\\[~\]|€]/g;
        const matches = text.match(extendedRegex);
        if (matches) {
            length += matches.length;
        }
    }
    
    if (isGsm7) {
        if (length <= 160) return 1;
        return Math.ceil(length / 153);
    } else {
        // Mode UCS-2 (Unicode) - Attention avec JavaScript et les emojis (Surrogate pairs)
        // Array.from(text).length donne le compte exact d'emojis complexes
        const unicodeLength = Array.from(text).length;
        if (unicodeLength <= 70) return 1;
        return Math.ceil(unicodeLength / 67);
    }
}

console.log(`Segments: \${getSmsSegments("Vos soldes sont ouverts 🚀")}`); // Segments: 1 (UCS-2)

Never send your campaigns blindly. Implementing this logic in your application will save you and your Moroccan customers from out-of-control SMS API bills.

Why choose EnvoiSMS for your business?

Carrier Delivery

Local routes to IAM, Orange and Inwi, with automatic failover between routes and delivery status sent by webhook.

Cost Optimization

WhatsApp Business API from 0.65 MAD per message with optimal ROI.

Sovereign Data (CNDP)

Full compliance with Moroccan personal data protection regulations (CNDP).

What is the routing latency on the IAM, Inwi and Orange networks?
On our local routes to Maroc Telecom (IAM), Orange and inwi, the average delivery latency is between 2 and 4 seconds for transactional flows.
How does the platform manage the format of Moroccan numbers?
EnvoiSMS automatically normalizes the numbers entered (06..., 07..., 00212...) to the E.164 standard (+212) to avoid any delivery failure.

Suggested Articles

SMS Formatting in Morocco: Line Breaks, GSM-7 vs UCS-2 Encoding and Cost Optimization
technical

SMS Formatting in Morocco: Line Breaks, GSM-7 vs UCS-2 Encoding and Cost Optimization

WhatsApp Business Formatting in Morocco: Enriched Text, Emojis and Interactive Buttons
technical

WhatsApp Business Formatting in Morocco: Enriched Text, Emojis and Interactive Buttons

One-Tap Autofill & 1-Click WhatsApp OTP Authentication in Morocco
technical

One-Tap Autofill & 1-Click WhatsApp OTP Authentication in Morocco