Skip to main content
Best Emojis

Emoji para desarrolladores

Casi todos los bugs con emoji vienen de un mismo desajuste: tu código cuenta algo distinto de lo que ve el lector. Un emoji de familia es una sola imagen, siete code points, 11 caracteres de JavaScript y 25 bytes. Pasamos las regex, los segmentadores y las comprobaciones de longitud habituales por los 3,963 emoji de la lista oficial de Unicode, y aquí publicamos lo que realmente detectan, para que elijas el método adecuado antes de que un informe de error te diga cuál elegiste.

3,963
emoji de Unicode 18.0, todos probados
2,770
tienen más de un code point
271
se los salta un filtro Extended_Pictographic
35
bytes en el emoji más largo

Un emoji, una longitud distinta en cada lenguaje

Cada celda es lo que devuelve esa expresión para el emoji que encabeza la columna. Se reparten en cuatro grupos: unidades UTF-16, code points, bytes UTF-8 y grafemas (lo que cuenta una persona). La columna de grafemas la calcula Intl.Segmenter en este servidor, así que un runtime con datos de Unicode más antiguos puede devolver más para los emoji más recientes.

ExpresiónCuenta😀❤️👍🏽🇯🇵👩‍💻👨‍👩‍👧‍👦🧑🏻‍❤️‍💋‍🧑🏼
JavaScripts.lengthunidades UTF-16224451115
JavaScript[...s].lengthcode points12223710
JavaScriptIntl.Segmentergrafemas1111111
Pythonlen(s)code points12223710
Pythonlen(s.encode('utf-8'))bytes UTF-84688112535
Javas.length()unidades UTF-16224451115
Javas.codePointCount(0, s.length())code points12223710
C#s.Lengthunidades UTF-16224451115
C# (.NET 5+)new StringInfo(s).LengthInTextElementsgrafemas1111111
Golen(s)bytes UTF-84688112535
Goutf8.RuneCountInString(s)code points12223710
Rusts.len()bytes UTF-84688112535
Rusts.chars().count()code points12223710
Swifts.countgrafemas1111111
Swifts.unicodeScalars.countcode points12223710
Rubys.lengthcode points12223710
Rubys.grapheme_clusters.lengthgrafemas1111111
PHPstrlen($s)bytes UTF-84688112535
PHPmb_strlen($s)code points12223710
PHPgrapheme_strlen($s)grafemas1111111
MySQLCHAR_LENGTH(s)code points12223710
MySQLLENGTH(s)bytes UTF-84688112535
SQL ServerLEN(s) on nvarcharunidades UTF-16224451115

Lo que un corte ingenuo le hace a un emoji

Aquí está s.slice(0, n) aplicado a la familia 👨‍👩‍👧‍👦 para cada n. La mayoría de los cortes no fallan de forma visible. Devuelven otra familia, más pequeña, y así es como este tipo de bug llega a producción sin que nadie lo note.

Corte en nLo que quedaCode points restantes
s.slice(0, 1)�medio par sustituto (se ve como �)0
s.slice(0, 2)👨1
s.slice(0, 3)👨‍2
s.slice(0, 4)👨‍�medio par sustituto (se ve como �)2
s.slice(0, 5)👨‍👩3
s.slice(0, 6)👨‍👩‍4
s.slice(0, 7)👨‍👩‍�medio par sustituto (se ve como �)4
s.slice(0, 8)👨‍👩‍👧5
s.slice(0, 9)👨‍👩‍👧‍6
s.slice(0, 10)👨‍👩‍👧‍�medio par sustituto (se ve como �)6
s.slice(0, 11)👨‍👩‍👧‍👦7

La bandera que cambia de país

Las letras de indicador regional se emparejan desde el principio de la cadena. Quita un code point del principio de 🇺🇸🇯🇵 y las letras restantes se emparejan de otra forma: 🇸🇯🇵. Sin errores, solo otro país.

🇺🇸🇯🇵 US + JP → 🇸🇯 SJ (Svalbard & Jan Mayen) + 🇵

Qué detecta cada regex de emoji

Probado el 2026-10-20 contra los 3,963 emoji fully-qualified, en Node 25.2.1, que incluye datos de Unicode 17.0. Un patrón solo cuenta como coincidencia cuando abarca el emoji completo.

PatrónCoincidenciasLo que se le escapa
/^\p{RGI_Emoji}$/v3,944 / 3,963Todos los emoji más nuevos que los datos de Unicode del motor: Emoji 18.0 (19)
Intl.Segmenter3,963 / 3,963Nada en este runtime
/\p{Extended_Pictographic}/u3,692 / 3,963259 banderas y 12 keycaps, que no contienen ningún code point pictográfico
/^\p{Extended_Pictographic}$/u1,193 / 3,963Todo lo que tenga más de un code point: tonos de piel, banderas, keycaps, secuencias ZWJ y emoji con selector de estilo

Y el que hay que evitar: \p{Emoji} también coincide con # * 0 1 2 3 4 5 6 7 8 9 © ®. Úsalo para eliminar emoji y borrarás todos los dígitos del texto.

Eliminar emoji: lo que deja cada método

Las dos líneas de abajo partían del mismo texto. Los restos son invisibles en la mayoría de las fuentes, y precisamente por eso dan problemas más tarde: en búsquedas, en deduplicación y en límites de longitud.

Great 👍🏽 job ❤️ 👩‍💻 🇯🇵 #️⃣1

MétodoResultadoCode points sobrantes
Eliminar \p{Extended_Pictographic}Great 🏽 job ️ ‍ 🇯🇵 #️⃣1U+1F3FD U+FE0F U+200D U+1F1EF U+1F1F5 U+FE0F U+20E3
Eliminar \p{RGI_Emoji}Great job 1ninguno

Cuánto espacio ocupan los emoji en una base de datos

Bytes UTF-8 por emoji en los 3,963. 30% caben en cuatro bytes o menos; el más largo necesita 35. Si una columna está limitada en bytes y no en caracteres, dimensiónala según esta tabla, no según el aspecto del texto.

Bytes UTF-8Emoji que cabenProporción
≤ 41,19330%
≤ 82,34659%
≤ 112,42461%
≤ 173,42486%
≤ 283,86898%
≤ 353,963100%

🧑🏻‍❤️‍💋‍🧑🏼 U+1F9D1 U+1F3FB U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F9D1 U+1F3FC

Elige la cuenta que corresponde al límite que aplicas

No existe una única longitud correcta, solo la que corresponde a la regla que estás aplicando. Una columna de base de datos limitada en bytes necesita bytes UTF-8. Un campo de texto que promete 50 caracteres a una persona necesita grafemas, o a quien escriba tres banderas le dirás que ha usado 12. SQL Server es la excepción: nvarchar(n) cuenta unidades UTF-16, así que 😀 ocupa dos caracteres de un nvarchar pero uno de un varchar de MySQL o PostgreSQL, que cuentan code points. Decide cuál de las cuatro quieres decir, ponlo en el nombre de la variable y lo demás viene solo.

Trunca en límites de grafema, no por índice

Cualquier corte por índice puede caer dentro de un emoji. Con UTF-16, el peor caso es medio par sustituto, que la mayoría de los renderizadores muestran como una caja con un signo de interrogación y que algunos codificadores JSON rechazan directamente. Con code points no se rompe nada a la vista, lo cual es peor: la familia pierde un hijo, un tono de piel se suelta y aparece como un cuadrado marrón, o una bandera se convierte en dos letras. La solución es segmentar primero y cortar un número entero de grafemas. Intl.Segmenter está en todos los navegadores principales desde que Firefox 125 lo incorporó en abril de 2024, y en Node desde antes, así que ya no hay excusa para escribir un divisor a mano.

Fragmentos listos para copiar

Pequeños y sin dependencias donde el lenguaje lo permite. Cada uno resuelve un caso de las tablas anteriores.

Contar lo que ve el lector (JavaScript)

const seg = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
const visibleLength = (s) => [...seg.segment(s)].length;

visibleLength('👨‍👩‍👧‍👦 ok'); // 4, while '👨‍👩‍👧‍👦 ok'.length is 14

Truncar sin partir un emoji (JavaScript)

function truncate(s, max, ellipsis = '…') {
  const parts = [...seg.segment(s)].map((x) => x.segment);
  return parts.length <= max ? s : parts.slice(0, max - 1).join('') + ellipsis;
}

Encontrar todos los emoji, banderas y keycaps incluidos (JavaScript)

// ES2024 'v' flag: Chrome 112, Safari 17, Firefox 116, Node 20
const emoji = /\p{RGI_Emoji}/gv;
'Go 🇯🇵 #️⃣1 👍🏽'.match(emoji); // ['🇯🇵', '#️⃣', '👍🏽']

Lo mismo en Python, con el módulo regex

import regex  # pip install regex; the built-in re has no \X

graphemes = regex.findall(r'\X', '👨‍👩‍👧‍👦 ok')
len(graphemes)  # 4, while len('👨‍👩‍👧‍👦 ok') is 10

Columnas que aceptan cualquier emoji

-- MySQL: utf8mb4 on the column AND the connection
CREATE TABLE posts (body VARCHAR(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci);
SET NAMES utf8mb4;

-- PostgreSQL: any UTF8 database already stores every emoji
-- SQL Server: use nvarchar, and remember LEN() counts UTF-16 units

Por qué ninguna regex está terminada

Cada propiedad de emoji de un motor de regex sale de datos de Unicode compilados en ese motor, así que un patrón solo está tan actualizado como el runtime que lo ejecuta. Nuestra propia prueba lo demuestra: \p{RGI_Emoji} detectó 3,944 de 3,963 porque las 19 secuencias más recientes aún no están en las tablas de Unicode 17.0 de Node 25.2.1. El mismo código las detectará tras actualizar el runtime, y un usuario con un navegador antiguo seguirá sin detectarlas. Si una validación debe aceptar emoji nuevos el mismo día que aparecen, compara por estructura (Extended_Pictographic más modificadores, joiners y selectores) o por grafema, y usa la propiedad solo donde un falso negativo no haga daño.

El mismo emoji se puede guardar de tres formas

Unicode recoge 3,963 emoji fully-qualified, más 1,029 formas minimally-qualified y 243 unqualified de las mismas imágenes, sobre todo las versiones sin el selector de estilo U+FE0F. ❤ y ❤️ se ven idénticos en muchas apps pero son cadenas distintas, así que una comprobación de unicidad, un contador de reacciones o un índice de búsqueda los trata como dos cosas. La normalización Unicode no ayuda: NFC y NFKC no tocan los selectores de variación. Si comparas o deduplicas emoji, elige una forma (fully-qualified es la opción segura) y convierte en la entrada usando la lista de cualificación, en lugar de quitar todos los U+FE0F, lo que además rompería keycaps como 1️⃣.

Conversor de emoji a UnicodeTodas las secuencias ZWJ, con sus tamañosContador de caracteres que cuenta bien los emojiGlosario de emoji

Preguntas que hacen los desarrolladores sobre emoji

¿Por qué la longitud de un emoji es 2 en JavaScript?

Las cadenas de JavaScript son UTF-16, y cualquier carácter por encima de U+FFFF ocupa dos unidades de 16 bits, un par sustituto. Casi todos los emoji están por encima de U+FFFF, así que incluso un simple 😀 tiene .length 2. Usa [...str].length para code points o Intl.Segmenter para lo que ve el lector.

¿Cuál es la mejor regex para detectar emoji?

En JavaScript moderno, /\p{RGI_Emoji}/v detecta secuencias de emoji completas, banderas y keycaps incluidos, pero solo hasta la versión de Unicode que conoce el motor. \p{Extended_Pictographic} se salta banderas y keycaps, y \p{Emoji} detecta por error dígitos, # y *.

¿Cómo cuento un emoji como un solo carácter?

Cuenta clústeres de grafemas. En JavaScript usa Intl.Segmenter con granularity grapheme; en Swift, String.count ya lo hace; en Python usa \X del módulo de terceros regex; en PHP, grapheme_strlen de la extensión intl.

¿Cuántos bytes necesito para guardar un emoji?

En UTF-8, entre 3 y 35 bytes. Un emoji de un solo code point por encima de U+FFFF ocupa 4. Los tonos de piel, las banderas y las secuencias unidas suman: en nuestra prueba, 59% de todos los emoji caben en 8 bytes, y el más largo, un beso con dos tonos de piel, ocupa 35.

¿Por qué mi emoji se convierte en ???? en la base de datos?

La columna o la conexión usa un juego de caracteres que no admite caracteres de cuatro bytes, normalmente el utf8 heredado de MySQL. Cambia tanto la tabla como la conexión a utf8mb4. Nuestra página del conversor Unicode explica la sentencia ALTER TABLE exacta.