¿Qué es un Contador SMS?
Un contador SMS es una herramienta que calcula cuántos caracteres contiene tu mensaje, detecta el tipo de codificación (GSM de 7 bits o UCS-2) y determina en cuántos segmentos SMS se dividirá el mensaje. Esto importa porque los operadores móviles cobran por segmento, no por mensaje, y exceder el límite de un solo SMS puede duplicar o triplicar tu costo sin aviso.
A diferencia de un contador de caracteres normal, un contador SMS tiene en cuenta las restricciones técnicas del estándar de Servicio de Mensajes Cortos definido en GSM 03.38. Considera no solo la longitud de tu texto, sino qué caracteres contiene y cómo deben codificarse para su transmisión a través de redes celulares.
Cómo Funciona la Codificación GSM de 7 Bits
La especificación GSM 03.38 define un alfabeto predeterminado de 128 caracteres que se pueden codificar usando 7 bits cada uno. Esto incluye letras latinas mayúsculas y minúsculas, dígitos, puntuación común y algunos símbolos especiales. Debido a que cada carácter usa solo 7 bits en lugar de 8, un solo SMS puede contener hasta 160 caracteres — calculado como (140 bytes × 8 bits) / 7 bits por carácter.
Conjunto de caracteres básico GSM de 7 bits:
| Categoría | Caracteres |
|---|---|
| Letras | A–Z, a–z |
| Dígitos | 0–9 |
| Puntuación | @, !, ", #, $, %, &, ', (, ), *, +, ,, -, ., / |
| Símbolos | :, ;, <, =, >, ?, ¡, ¿, ¤, £, ¥, §, ¨, ©, ®, ´, `, ^, ~, ¯ |
| Especiales | Espacio, nueva línea, retorno de carro |
| Extendidos | ^, {, }, , [, ~, ], , € (requieren byte de escape) |
Los caracteres GSM extendidos de 7 bits — como ^, {, }, [, ], ~, | y € — requieren un código de escape (0x1B) antes del carácter. Este byte de escape consume espacio en el mensaje, por lo que cada carácter extendido cuenta efectivamente como 2 caracteres hacia el límite de 160 caracteres.
Codificación UCS-2: Cuando 7 Bits No es Suficiente
Cuando tu mensaje contiene caracteres fuera del alfabeto GSM de 7 bits — como emojis, comillas curvas, letras acentuadas como é o ü, guiones como —, o cualquier símbolo Unicode — todo el mensaje cambia a codificación UCS-2 (16 bits). En modo UCS-2, cada carácter ocupa 16 bits, reduciendo la capacidad de un solo SMS de 160 a 70 caracteres.
Caracteres que fuerzan la codificación UCS-2:
- Emojis y pictogramas (
😊,🚀,❤️) - Comillas curvas (
"",'') - Guiones largos (
—,–) - Caracteres acentuados no incluidos en el conjunto GSM básico (
ě,ř,č) - Símbolos de moneda más allá de
$,£,¥,€ - Flechas (
→,←,↑,↓) - Símbolos matemáticos (
∑,∫,√,∞) - La mayoría de caracteres CJK (chino, japonés, coreano)
Una vez que un mensaje contiene incluso un solo carácter UCS-2, todo el mensaje usa codificación de 16 bits. No hay modo híbrido — es completamente de 7 bits o completamente de 16 bits.
SMS Multiparte y Límites de Segmento
Cuando tu mensaje excede el límite de un solo SMS (160 caracteres GSM o 70 caracteres UCS-2), el operador lo divide en múltiples segmentos. Cada segmento incluye un Encabezado de Datos de Usuario (UDH) de 6 bytes para reensamblaje, lo que reduce el espacio de payload disponible.
| Codificación | SMS Simple | Multiparte (por segmento) |
|---|---|---|
| GSM 7 bits | 160 caracteres | 153 caracteres |
| UCS-2 | 70 caracteres | 67 caracteres |
Cómo funciona el cálculo:
GSM 7 bits multiparte:
caracteres_por_segmento = (140 - 6) × 8 / 7 = 153
UCS-2 multiparte:
caracteres_por_segmento = (140 - 6) / 2 = 67
Un mensaje de 200 caracteres en codificación GSM de 7 bits se divide en 2 segmentos (153 + 47). Un mensaje de 150 caracteres que contiene emojis se divide en 3 segmentos UCS-2 (67 + 67 + 16). La mayoría de los operadores facturan por segmento, por lo que entender estos límites te ayuda a controlar los costos.
Ejemplos de Código
PHP: Contar Segmentos SMS
function countSmsSegments(string $text): array {
$gsm7 = '@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&\'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà';
$gsm7ext = ['^', '{', '}', '\\', '[', '~', ']', '|', '€'];
$isUcs2 = false;
$extCount = 0;
for ($i = 0; $i < mb_strlen($text); $i++) {
$char = mb_substr($text, $i, 1);
if (in_array($char, $gsm7ext)) {
$extCount++;
} elseif (mb_strpos($gsm7, $char) === false) {
$isUcs2 = true;
break;
}
}
if ($isUcs2) {
$maxPerSegment = 70;
$segments = (int)ceil(mb_strlen($text) / $maxPerSegment);
// Multiparte reduce el límite
if ($segments > 1) {
$maxPerSegment = 67;
$segments = (int)ceil(mb_strlen($text) / $maxPerSegment);
}
return ['encoding' => 'UCS-2', 'segments' => $segments, 'chars_per_segment' => $maxPerSegment];
}
$effectiveLength = mb_strlen($text) + $extCount;
$maxPerSegment = 160;
$segments = (int)ceil($effectiveLength / $maxPerSegment);
if ($segments > 1) {
$maxPerSegment = 153;
$segments = (int)ceil($effectiveLength / $maxPerSegment);
}
return ['encoding' => 'GSM 7-bit', 'segments' => $segments, 'chars_per_segment' => $maxPerSegment];
}
JavaScript: Detectar Codificación SMS
const GSM7_BASIC = new Set(
'@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&\'()*+,-./0123456789:;<=>?¡' +
'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà'.split('')
);
const GSM7_EXT = new Set(['^', '{', '}', '\\', '[', '~', ']', '|', '€']);
function detectSmsEncoding(text) {
let extCount = 0;
for (const char of text) {
if (GSM7_EXT.has(char)) {
extCount++;
} else if (!GSM7_BASIC.has(char)) {
return { encoding: 'UCS-2', extCount: 0 };
}
}
return { encoding: 'GSM 7-bit', extCount };
}
const result = detectSmsEncoding('Hello World! €50');
console.log(result); // { encoding: 'GSM 7-bit', extCount: 1 }
Python: Calcular Partes SMS
def sms_parts(text: str) -> dict:
gsm7_basic = set('@£$¥èéùìòÇØøÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&\'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà')
gsm7_ext = {'^', '{', '}', '\\', '[', '~', ']', '|', '€'}
is_ucs2 = False
ext_count = 0
for char in text:
if char in gsm7_ext:
ext_count += 1
elif char not in gsm7_basic:
is_ucs2 = True
break
if is_ucs2:
limit = 70 if len(text) <= 70 else 67
parts = (len(text) + limit - 1) // limit
return {'encoding': 'UCS-2', 'parts': parts, 'chars_per_part': limit}
effective = len(text) + ext_count
limit = 160 if effective <= 160 else 153
parts = (effective + limit - 1) // limit
return {'encoding': 'GSM 7-bit', 'parts': parts, 'chars_per_part': limit}
print(sms_parts('Hello World')) # 1 parte, GSM 7-bit
print(sms_parts('Hello 😊 World')) # Codificación UCS-2 activada
Por Qué la Codificación SMS es Importante para los Desarrolladores
Si construyes aplicaciones que envían notificaciones SMS — como códigos de autenticación de dos factores, recordatorios de citas o campañas de marketing — entender la codificación SMS te ayuda a controlar tanto la capacidad de entrega como el costo.
Conclusiones clave para desarrolladores:
- Siempre valida la longitud del mensaje antes de enviar para evitar cargos multiparte inesperados
- Elimina o reemplaza caracteres UCS-2 cuando sea posible para mantener los mensajes en GSM de 7 bits
- Prueba con caracteres extendidos como
€y[]— se comprimen de manera diferente que los caracteres GSM básicos - Ten en cuenta la sobrecarga de UDH de 6 bytes al estimar la capacidad multiparte
- Considera usar una herramienta de contador SMS dedicada durante el desarrollo y las pruebas
Herramienta en Línea
La herramienta Contador SMS en Help2Code proporciona recuento de caracteres en tiempo real, detección de codificación y vista previa de segmentos. Pega tu mensaje y ve instantáneamente si usa codificación GSM de 7 bits o UCS-2, cuántos segmentos requiere y exactamente dónde se rompe cada segmento. La vista previa de codificación con código de colores te muestra qué caracteres activan el modo Unicode y cuáles son seguros en 7 bits.
Conclusión
Un contador SMS es una utilidad esencial para cualquiera que envíe mensajes de texto mediante programación o quiera evitar cargos inesperados del operador. Al entender la diferencia entre la codificación GSM de 7 bits y UCS-2, y saber cómo funciona la segmentación multiparte, puedes escribir aplicaciones SMS más rentables y depurar problemas de entrega más rápido. Usa la herramienta Contador SMS para probar tus mensajes antes de enviarlos en producción.