Contar caracteres frente a un límite que ha puesto otro
Publicado el 10/8/2026 · 13 min de lectura · Herramientas de texto e idioma
Daniel Okonkwo — Desarrollador front-end y redactor de Tecnología en Allin
Rendimiento web · Formatos de archivo
Verificado con 4 fuentes
«Carácter» no designa una sola cosa, y quien escribió el límite decidió cuál sin decírtelo. El contador de frecuencia de esta página recorre la cadena con un iterador de puntos de código, así que cuenta puntos de código Unicode. Pégale el emoji de la familia y devuelve cinco filas que suman siete: cuatro filas para las cuatro personas y una fila para algo que no se ve en absoluto, el unidor de ancho cero, con un recuento de 3. Esa misma cadena es 1 grupo de grafemas, 7 puntos de código, 11 unidades UTF-16 y 25 bytes UTF-8. Esos cuatro números son lo que cuatro sistemas distintos llaman su longitud, así que un campo que dice 500 caracteres admite 500 si cuenta grafemas, 71 si cuenta puntos de código, 45 si usa el .length de JavaScript o el .length() de Java, y 20 si la columna de detrás son 500 bytes. La herramienta no imprime total; la columna la sumas tú, y sus valores por defecto omiten los espacios y unifican mayúsculas, por eso «Merci beaucoup !» da 11 filas que suman 14 y no 16 caracteres. El SMS es más estricto. El protocolo transporta 140 octetos, que son 160 caracteres del alfabeto GSM de 7 bits o 70 en UCS-2, y bajan a 153 y 67 en cuanto los mensajes se concatenan. Un solo carácter fuera de la tabla de 7 bits vuelca el mensaje entero: basta una comilla tipográfica, basta cualquier emoji, y bastan las á í ó ú españolas o las ã õ portuguesas, porque la tabla por defecto sencillamente no las contiene. Las metadescripciones no se cuentan: los fragmentos se cortan por anchura representada, no por número de caracteres.
Un emoji vale 1 carácter, o 7, o 11, o 25, según quién cuente. Cuál quieren decir tu formulario, tu base de datos y tu pasarela de SMS, y una prueba de un solo pegado para saber a cuál te enfrentas.
Cuatro números para un solo emoji
Toma el emoji de la familia formado por un hombre, una mujer, una niña y un niño. Es una sola cosa en pantalla, una sola pulsación de Retroceso lo borra y el cursor lo salta en un solo paso. Por debajo son cuatro emojis de personas separados por tres copias de un carácter de control invisible, U+200D, el unidor de ancho cero. Medida de cuatro maneras, esa cadena es 1 grupo de grafemas, 7 puntos de código, 11 unidades UTF-16 y 25 bytes UTF-8. Ninguno de esos números está mal; responden a cuatro preguntas distintas.
El grupo de grafemas es el carácter tal como lo percibe el usuario, y Unicode define las fronteras entre ellos en un anexo técnico, el UAX n.º 29, precisamente porque «lo que un lector considera un carácter» no es lo bastante evidente como para dejarlo a cada programa. El punto de código es la entrada numerada del catálogo Unicode. La unidad UTF-16 es una casilla de dieciséis bits, y todo lo que pase de U+FFFF necesita dos: ese es el número que devuelven JavaScript, Java y C# cuando pides la longitud de una cadena. El byte UTF-8 es lo que viaja de verdad por la red y ocupa una columna de base de datos.
Qué cuenta esta herramienta, exactamente
El contador de frecuencia recorre la entrada con un bucle for-of, que en JavaScript avanza por puntos de código y no por unidades de dieciséis bits. Cuenta, pues, puntos de código, y se le puede ver hacerlo. Pega el emoji de la familia con los ajustes por defecto y la salida son cinco filas: una fila de aspecto vacío con el recuento 3 y luego cuatro filas con 1 cada una. La fila vacía es el unidor de ancho cero. Suma la columna y obtienes 7, el número de puntos de código, no el 1 que responderías si te preguntaran cuántos caracteres has pegado.
Dos valores por defecto cambian la cuenta antes de que la veas. «Omitir espacios» está activo, así que los espacios nunca aparecen en la tabla: «Merci beaucoup !» tiene 16 caracteres pero produce 11 filas que suman 14, porque los dos espacios se caen. «Ignorar mayúsculas» también está activo y funde pares, que es lo que casi siempre quieres y de vez en cuando produce algo raro. La İ mayúscula turca pasa a minúscula como una i más un punto combinante aparte, de modo que la tabla gana una fila cuya clave mide dos puntos de código. La herramienta nunca prometió que la clave de fila fuera un solo carácter; es lo que dio la conversión a minúscula.
Y no imprime total. La salida es una tabla de dos columnas, carácter y recuento, ordenada por recuento y luego alfabéticamente, y el número que probablemente buscabas es la suma de la segunda columna. Si quieres los cuatro recuentos uno al lado del otro sin hacer cuentas, el contador de bytes UTF-8 del sitio imprime grafemas, puntos de código, bytes UTF-8, unidades UTF-16, palabras y líneas de una vez: existe precisamente porque esos números discrepan, y su propio comentario lo dice.
La prueba de un solo pegado que revela con qué contador te enfrentas
Pega un emoji de familia en el campo que lleva el contador y lee el contador. Si dice 1, cuenta grupos de grafemas. Si dice 7, cuenta puntos de código. Si dice 11, usa la longitud de cadena nativa del lenguaje, es decir unidades UTF-16: JavaScript, Java o C#. Si dice 25, está contando bytes UTF-8 y el límite es en realidad un límite de bytes. Cuatro respuestas posibles, cuatro sistemas distintos detrás del campo, y la prueba cabe en un pegado.
La prueba tiene una segunda mitad, y pesa más: el contador que ves en el navegador no es necesariamente el que decide. Un contador de front-end es casi siempre el .length de JavaScript, mientras que el rechazo al enviar viene de un servidor, de una definición de columna o de una API aguas abajo con su propio criterio. Si el campo te deja teclear 500 y el guardado falla en 480, los dos extremos cuentan distinto y gana el más corto. Escribe el texto, guárdalo, recarga la página y mira qué ha vuelto: un truncamiento se ve más fácilmente de lo que se predice.
SMS: 160 caracteres, o 70, y lo decide una comilla
El servicio de mensajes cortos transporta hasta 140 octetos de datos de usuario. Empaquétalos con el alfabeto GSM de 7 bits por defecto y caben 160 caracteres; codifícalos en UCS-2, dos bytes por unidad, y caben 70. Cuando un mensaje es demasiado largo se parte, y cada trozo cede sitio a una pequeña cabecera que dice qué trozo es: quedan 153 caracteres de 7 bits o 67 unidades UCS-2 por segmento. Nada de esto es negociable, y todas las tarifas de SMS masivo están construidas sobre ello.
Lo interesante es qué hay en esa tabla de 7 bits, porque un solo carácter ausente vuelca todo el mensaje a UCS-2 y reduce la capacidad a menos de la mitad. La tabla sí contiene un juego generoso de acentos — è é ù ì ò à ä ö ü ñ å æ ø ß, más Ä Ö Ü Ñ É Å Æ Ø Ç — junto con ¡ ¿ § y unos cuantos símbolos monetarios. No contiene á, í, ó ni ú, y tampoco ã ni õ. Así que un mensaje en español con «está» o «aquí», o uno en portugués con «não», es un mensaje de 70 caracteres y no de 160, y nada en pantalla se lo dice al remitente.
La especificación lo previó y define tablas nacionales: el español tiene una tabla de desplazamiento simple, el portugués tiene una simple y una de bloqueo. Un carácter de desplazamiento simple cuesta dos de tus casillas de 7 bits en lugar de una, y ambos extremos tienen que implementar el mecanismo. En la práctica la mayoría de las pasarelas no lo intenta y salta a UCS-2. Ese mismo mecanismo de escape explica que un pequeño conjunto de símbolos corrientes ya cueste dos casillas cada uno en un mensaje normal: el acento circunflejo suelto, las llaves, los corchetes, la barra invertida, la virgulilla, la barra vertical y el signo del euro viven en la tabla de extensión, no en la principal. Y la comilla tipográfica que tu procesador de textos insertó cuando escribiste una recta no está en ninguna de las dos.
La metadescripción se mide en píxeles, no en caracteres
Toda lista de comprobación SEO da un rango de caracteres para la metadescripción. La documentación de Google no da ninguno: dice que no hay límite de longitud, que el fragmento se genera a partir de la página y a veces de la descripción, y que los fragmentos se recortan para caber en el resultado. Caber es cuestión de anchura representada: una descripción llena de letras anchas se corta antes que otra del mismo número de caracteres hecha de letras estrechas, y el resultado móvil tiene menos sitio que el de escritorio.
La consecuencia práctica no es abandonar un presupuesto de caracteres, sino dejar de tratarlo como una regla. Pon lo que tiene que sobrevivir en la primera mitad de la frase y luego comprueba el resultado real en vez del recuento. Y ten presente que Google reescribe con frecuencia la descripción entera cuando juzga que el contenido de la página responde mejor a la consulta: una descripción truncada que tú nunca escribiste es un problema distinto de una que sí escribiste.
Dos grafías de la misma palabra, dos longitudes
Queda una última trampa que no tiene nada que ver con los emojis. La letra é puede ser un punto de código, U+00E9, o dos: una e simple seguida de un acento agudo combinante. Se ven idénticas, significan lo mismo y no miden lo mismo: 1 punto de código y 2 bytes frente a 2 puntos de código y 3 bytes. Casi todos los teclados producen la primera; algunos sistemas, algunos escáneres y mucho texto copiado y pegado producen la segunda. Pasa la forma descompuesta por el contador de frecuencia y sale en dos filas, una de ellas un acento desnudo posado sobre nada.
Si una comprobación de longitud falla con un texto que parece de la longitud correcta, esto es lo primero que hay que probar. Normalizar a la forma compuesta antes de contar lo arregla, y es una sola llamada en todos los lenguajes que traen una biblioteca Unicode. Hazlo antes de contar, antes de almacenar y antes de comparar dos cadenas por igualdad: la misma palabra en dos formas de normalización no es igual en ninguna comparación de bytes.
| Unidad de recuento | El emoji de la familia cuenta como | Dónde te la encuentras | Cuántos caben bajo «500 caracteres» |
|---|---|---|---|
| Grupos de grafemas (UAX n.º 29) | 1 | El String.count de Swift; una pulsación de Retroceso; la primera fila del contador de bytes UTF-8 | 500 |
| Puntos de código Unicode | 7: cuatro personas más tres unidores | El len() de Python 3; las runas de Go; el contador de frecuencia de esta página | 71 |
| Unidades de código UTF-16 | 11 | El .length de JavaScript, el .length() de Java, el .Length de C#: casi todos los contadores de formulario en el navegador | 45 |
| Bytes UTF-8 | 25 | El len() de Go; una columna o una cabecera medidas en bytes | 20 |
| Unidades UCS-2 en un segmento de SMS | 11 | Un segmento único de 70 unidades, o 67 en cuanto se concatenan los mensajes | 6 por segmento: el séptimo abre otro mensaje |
Preguntas frecuentes
- ¿Por qué la tabla de frecuencia tiene una fila en blanco?
- Porque un carácter que no se ve sigue siendo un carácter, y el contador lo informa con honestidad. En el emoji de la familia esa fila es U+200D, el unidor de ancho cero, que aparece tres veces: es lo que pega a las cuatro personas en una sola imagen. Los selectores de variación se comportan igual: el pequeño U+FE0F que convierte un símbolo monocromo en un emoji de color es invisible y se cuenta. Una fila en blanco con un número al lado es la herramienta diciéndote que tu texto contiene algo que no ves, que es justo lo que conviene saber antes de pegarlo en un campo con límite.
- ¿De verdad un solo emoji parte mi SMS por la mitad?
- Más que por la mitad. Un mensaje se codifica en un solo alfabeto de punta a punta, así que un único carácter fuera de la tabla GSM de 7 bits fuerza todo el mensaje a UCS-2 y la capacidad cae de 160 caracteres a 70. Con los emojis es peor: todo lo que pase de U+FFFF ocupa dos unidades UCS-2, de modo que una cara sonriente simple cuesta dos de tus 70 y el emoji de la familia cuesta once. Seis de esos emojis y una palabra no caben en un solo segmento. Si tu factura de SMS masivo subió sin que el texto creciera, busca una comilla tipográfica o un acento que la tabla no lleva antes de mirar a ningún otro sitio.
- Mi formulario dice 500 caracteres. ¿Qué 500 son?
- Pruébalo en vez de adivinar. Pega un emoji de familia y lee el contador: 1 significa grupos de grafemas, 7 puntos de código, 11 unidades UTF-16, 25 bytes UTF-8. En ASCII puro los cuatro coinciden, y por eso la diferencia solo aflora cuando un usuario real pega un nombre con tilde o un emoji en el campo. Si el formulario es tuyo, cuenta grupos de grafemas para el número visible y valida contra lo que la capa de almacenamiento imponga de verdad, y luego fija el límite visible en el menor de los dos. Si no es tuyo, supón la respuesta más pequeña posible y deja holgura.
- Un VARCHAR(500) de base de datos, ¿son quinientos bytes o quinientos caracteres?
- En las bases relacionales corrientes la longitud declarada es en caracteres, no en bytes, pero los límites que la rodean sí están en bytes, y ahí es donde te pillan. Una fila tiene un tamaño máximo en bytes, un índice tiene un tamaño de clave máximo en bytes, y una codificación de cuatro bytes por carácter multiplica ambos. Resultado: la columna acepta tus 500 caracteres y el índice se niega a crearse. Los límites en bytes son más frecuentes fuera de la base: valores de cabeceras HTTP, cargas de colas de mensajes, claves de almacenamiento de objetos y muchísimas API de terceros están especificadas en bytes. Cuando la documentación dice bytes, cuenta bytes.
- ¿Cuántos caracteres debe tener una metadescripción?
- No hay ningún número documentado, y el que te hayan dado se midió sobre resultados de búsqueda, no se publicó como regla. La orientación de Google es que las descripciones no tienen límite de longitud, que los fragmentos se toman de la página tanto como de la descripción, y que se recortan para caber, y caber es cuestión de anchura representada en una maquetación que difiere entre móvil y escritorio. El hábito útil es cargar el principio: pon el argumento, la cifra o el elemento diferenciador en la primera oración y trata todo lo posterior como prescindible. Después mira el resultado real en una búsqueda de verdad y ajusta según lo que veas.
Artículos que podrían interesarte
Todas las guías →Herramientas relacionadas
Esto describe lo que hacen hoy estas herramientas de texto, comprobado ejecutando sus propias funciones sobre las entradas exactas que se citan aquí. Cuando una herramienta falla en un caso, queda escrito en vez de suavizado, porque una herramienta impredecible es peor que una cuyos límites conoces. Nada de esto es una regla que ninguna herramienta esté obligada a seguir: la capitalización, el recuento de caracteres y la numeración de líneas son convenciones, y esas convenciones cambian según el idioma, el manual de estilo y el programa que haya al otro lado. Antes de pasar cualquiera de ellas por un texto que no puedas volver a teclear, pásala primero por una copia y compara los dos extremos.
Fuentes
- Unicode Consortium — UAX #29, Unicode Text Segmentation — the grapheme cluster boundary rules that define a user-perceived character, including the treatment of zero-width joiners, variation selectors and emoji modifier sequences
- ETSI / 3GPP — TS 123 038 (3GPP TS 23.038) — the GSM 7-bit default alphabet table in clause 6.2.1, its escape-driven extension table in 6.2.1.1 (which holds the caret, braces, brackets, backslash, tilde, vertical bar and euro sign), and the national language single- and locking-shift tables for Spanish and Portuguese in 6.2.1.2 and Annex A
- ETSI / 3GPP — TS 123 040 (3GPP TS 23.040) — the transfer of short messages: the user data of an SM MT or SM MO carries up to 140 octets, which is what yields 160 seven-bit characters or 70 UCS-2 units per single message
- Google Search Central — Control your snippets in search results — no documented character limit for a description; snippets are generated from the page and from the description and are trimmed to fit the result
¿Has detectado un error en este artículo?