Contador de bytes UTF-8 | Detecta el desfase entre VARCHAR y String.length en una pantalla
Pega un texto y verás simultáneamente los bytes UTF-8, los puntos de código Unicode (caracteres reales), las unidades de código UTF-16 (lo que devuelve string.length en JavaScript) y el número de líneas. El desglose por 4 categorías (ASCII, Latín extendido, BMP CJK, emoji y suplementarios) revela qué caracteres están inflando tu presupuesto de almacenamiento.
💡 Sobre esta herramienta
Si alguna vez has visto ERROR 1406: Data too long for column al insertar un nombre con tilde, has notado que un JWT con emoji ocupa casi el doble, o has descubierto en consola que '😀'.length === 2, has tropezado con la diferencia entre puntos de código Unicode, bytes UTF-8 y unidades UTF-16.
UTF-8 es una codificación de longitud variable definida en RFC 3629: ASCII cabe en 1 byte, los caracteres latinos extendidos (á, ñ, ü), griegos y cirílicos en 2, el bloque BMP CJK en 3, y todo lo que está por encima de U+FFFF — emoji, ideogramas suplementarios, símbolos matemáticos — en 4 bytes. Las cadenas de JavaScript, en cambio, viven internamente como UTF-16, así que cualquier carácter fuera del BMP aparece como par sustituto (surrogate pair) y suma 2 al length. El resultado: las bases de datos miden en bytes, los APIs de JS razonan en unidades UTF-16 y los humanos contamos grafemas. Los tres marcadores discrepan en cuanto entra un emoji o un carácter exótico.
Esta herramienta muestra las cuatro métricas en paralelo y reparte cada carácter en uno de los cuatro cubos de bytes para que puedas responder preguntas concretas: "¿Por qué un nombre con ñ ocupa más que la versión inglesa?", "¿Cuántos emoji caben en una clave Redis de 4 KB?", "¿Mi display_name cabe en este NVARCHAR(50)?".
🧐 Preguntas Frecuentes
Q. VARCHAR(255) ¿son 255 caracteres o 255 bytes?
A. En MySQL 5.0.3+ son 255 caracteres, pero el límite de tamaño de fila se calcula en bytes (65 535 por fila). Con utf8mb4, VARCHAR(N) puede ocupar hasta N × 4 bytes en los cálculos de fila e índice, por eso una sola columna VARCHAR(16383) ya llena la fila. Mira el campo "Bytes UTF-8" de esta herramienta para dimensionar columnas con datos reales.
Q. ¿Por qué '😀'.length devuelve 2 en JavaScript?
A. String.prototype.length devuelve unidades de código UTF-16. U+1F600 está fuera del BMP, así que se codifica con el par sustituto 😀. Para contar caracteres reales usa [...cadena].length, Array.from(cadena).length o el campo "Caracteres" de esta herramienta, que itera puntos de código con for..of.
Q. ¿Qué diferencia hay entre utf8 y utf8mb4 en MySQL?
A. El charset legacy utf8 almacena como máximo 3 bytes por carácter y convierte silenciosamente cualquier carácter de 4 bytes (emoji, varios ideogramas suplementarios, símbolos matemáticos) en ?. utf8mb4 es el UTF-8 completo según RFC 3629. Para esquemas nuevos siempre elige utf8mb4: si el desglose "4 bytes" tiene algún valor, el charset antiguo lo destruiría.
Q. Caracteres vs unidades UTF-16: ¿cuándo importa?
A. Importa en cualquier API que confíe en string.length: claves key de React, truncado naïve con substring, validadores de longitud de contraseña, los límites de caracteres en Twitter antes de 2017. Los grafemas (👨👩👧👦 = un solo carácter percibido) también difieren de los puntos de código; usa Intl.Segmenter cuando necesites un conteo orientado al usuario final.
Q. ¿Cómo se cuentan los saltos de línea?
A. LF (\n), CRLF (\r\n) y CR (\r) se tratan como un único separador de línea. Una entrada vacía da 0 líneas; cualquier entrada no vacía da al menos 1. Eso sí, CRLF sigue ocupando 2 bytes y 2 unidades UTF-16 aunque cuente como un solo separador.
📚 Datos Curiosos
- Los acentos castellanos cuestan el doble: La palabra
añoocupa 4 bytes en UTF-8 (a+ñde 2 bytes +o) frente a 3 bytes deano. El uso correcto del español impone una sobrecarga de aproximadamente +10 % respecto al inglés plano. Si trabajas en SEO o redes sociales con límites en bytes, pega tu texto y compara: la diferencia es pequeña por carácter pero significativa en cabeceras HTTP o cadenas de consulta. - Latinoamérica y emoji: El 60 % de los mensajes de WhatsApp en América Latina contienen al menos un emoji según el reporte anual de Meta de 2024. Cada emoji estándar añade 4 bytes UTF-8 + 2 unidades UTF-16; un mensaje de "Hola 😊👍🎉" ocupa 17 bytes mientras que "Hola" solo ocupa 4. Para sistemas con cuotas estrictas en bytes (SMS gateway, push notifications con APNS) esto se nota rápidamente.
- Ñ y la migración del charset: Muchas bases de datos heredadas en empresas hispanohablantes nacieron con
latin1(1 byte por carácter, incluida la ñ). Al migrar autf8mb4lañempezó a ocupar 2 bytes, lo que rompió queries que asumíanLENGTH(column) = CHAR_LENGTH(column). UsarCHAR_LENGTH()en lugar deLENGTH()para validaciones de longitud es el patrón correcto, y esta herramienta deja ver de un vistazo cuál de las dos magnitudes te interesa.