Escape / Unescape Unicode
Convierte texto a escapes \uXXXX o \u{XXXXX} y viceversa. Maneja pares surrogate para emoji.
Unicode Escape / Unescape
Runs entirely in your browser. Your input never leaves your device.
What next?
How it works
Qué es el escape de Unicode
El escape de Unicode convierte caracteres a su representación de secuencia de escape \uXXXX (o \u{XXXXX}) — y viceversa. El carácter é se convierte en é; el emoji 👀 se convierte en \u{1f440} en modo ES6 o el par sustituto 👀 en modo JSON.
Esto no es codificación para compresión o seguridad. Es una representación segura para texto que permite incrustar cualquier carácter Unicode en un contexto que solo acepta ASCII — valores de cadenas JSON, archivos fuente JavaScript, literales de cadena en C, archivos .properties de Java y contextos similares.
Las dos sintaxis de escape
\uXXXX — cuatro dígitos hexadecimales (solo BMP)
La sintaxis de escape Unicode original, definida en la especificación ECMAScript 1 (1997) y requerida por la especificación JSON (RFC 8259 §7). Funciona para puntos de código U+0000 a U+FFFF — el Plano Multilingüe Básico (BMP). Para estos 65.536 caracteres, é y é son exactamente equivalentes en cualquier analizador conforme.
\u{XXXXX} — dígitos hex variables entre llaves (Unicode completo)
Introducida en ES6 (ECMAScript 2015). Soporta el rango Unicode completo U+000000 a U+10FFFF. Esta es la forma correcta de escapar caracteres del plano astral — puntos de código por encima de U+FFFF que incluyen la mayoría de los emoji, escrituras históricas y símbolos matemáticos. \u{1f600} es más limpio e inequívoco; la sintaxis de llaves también permite omitir los ceros iniciales.
JSON no soporta \u{} — los analizadores JSON esperan exactamente cuatro dígitos hex después de \u. Para incrustar un punto de código del plano astral en JSON, debes usar pares sustitutos.
El plano astral y los pares sustitutos
El Plano Multilingüe Básico de Unicode contiene los puntos de código U+0000–U+FFFF. Todo lo que está por encima — llamado planos astrales o caracteres suplementarios — requiere una estrategia diferente en sistemas construidos sobre UTF-16.
Las cadenas JavaScript son internamente UTF-16. Para representar un punto de código por encima de U+FFFF en UTF-16, se usan dos unidades de código de 16 bits llamadas par sustituto: un sustituto alto (U+D800–U+DBFF) seguido de un sustituto bajo (U+DC00–U+DFFF). La fórmula:
codepoint = 0x10000 + (high - 0xD800) × 0x400 + (low - 0xDC00)
El emoji 😀 (U+1F600) se convierte en el par 😀. En JSON, esta es la única forma de representarlo ya que el escape \u de JSON solo acepta cuatro dígitos hex. En JavaScript ES6, puedes usar \u{1F600} directamente.
El problema: como un par sustituto son dos secuencias \u, las operaciones de cadena ingenuas que trabajan carácter por carácter se rompen. "😀".length devuelve 2 en JavaScript, no 1. "😀"[0] devuelve el sustituto alto suelto \uD83D, no el emoji. Dividir por clústeres de grafemas requiere [...str] (spread) o Intl.Segmenter en ES2022+.
Modo JSON vs modo ES6 vs modo "all"
Modo JSON — escapa cada carácter no ASCII usando solo \uXXXX, con pares sustitutos para puntos de código por encima de U+FFFF. La salida siempre es válida dentro de un literal de cadena JSON.
Modo ES6 — usa \u{XXXXX} para caracteres astrales y \uXXXX para caracteres BMP. Produce salida más corta y legible para cadenas con muchos emoji. Solo válido en contextos JavaScript ES6+ — no en JSON, no en entornos ES5 más antiguos.
Modo all — escapa cada carácter, incluidos los ASCII. Útil cuando necesitas una representación puramente ASCII de una cadena sin ningún Unicode crudo — para incrustar en cadenas C, archivos fuente Python o depurar carácter por carácter.
String.fromCodePoint vs String.fromCharCode
Estas dos funciones JavaScript revelan directamente la complejidad del par sustituto:
String.fromCharCode(0x1F600) // "?" — incorrecto, trunca a U+F600
String.fromCodePoint(0x1F600) // "😀" — correcto
String.fromCharCode(0xD83D, 0xDE00) // "😀" — correcto vía par sustituto
String.fromCodePoint(0x1F600) // "😀" — correcto vía punto de código
fromCharCode es anterior a los planos astrales de Unicode y opera en unidades de código UTF-16 crudas. Si le pasas un punto de código por encima de 0xFFFF, lo trunca silenciosamente. fromCodePoint (ES6) maneja el rango completo. Al desescapar \u{1F600}, usa siempre fromCodePoint.
¿Cuándo obliga JSON a escapar?
La especificación JSON (RFC 8259) requiere que los caracteres de control U+0000–U+001F sean escapados. Todos los demás caracteres pueden incluirse en crudo como UTF-8, pero muchos serializadores escapan el rango no ASCII completo por seguridad. Si recibes un payload JSON y ves à donde esperabas à, el JSON fue producido con una configuración de "escapar completamente los no ASCII". Ambas representaciones son idénticas para un analizador JSON conforme.
Literales de plantilla y cuándo no necesitas escape
En los literales de plantilla ES6 y los literales de cadena JavaScript modernos, puedes incrustar Unicode directamente:
const saludo = `¡Hola, España!`; // sin necesidad de escape
const emoji = "😀"; // funciona en JS moderno
const escaped = "\u{1F600}"; // idéntico a lo anterior
Necesitas escape cuando: la cadena se incrustará en JSON programáticamente, el archivo debe ser solo ASCII, estás depurando un carácter y quieres ver su punto de código explícitamente, o estás pasando la cadena por un canal que corrompe el Unicode crudo.
Privacidad
Todo el procesamiento se ejecuta en tu navegador. Tu texto nunca se envía a un servidor.
Herramientas relacionadas
- URL Encode/Decode — codificación porcentual para componentes URI, un esquema de escape diferente.
- HTML Entity Encode/Decode —
&,éy referencias de caracteres HTML similares.
FAQ
¿Por qué mi emoji aparece como dos secuencias \u en modo JSON?
Porque el escape \u de JSON solo acepta exactamente cuatro dígitos hexadecimales, cubriendo puntos de código hasta U+FFFF. Los emoji viven en los planos astrales (por encima de U+FFFF) y deben representarse como pares sustitutos UTF-16 — dos secuencias \u consecutivas. Por ejemplo, 😀 (U+1F600) se convierte en 😀. Usa el modo ES6 para obtener la forma más limpia \u{1F600}, pero nota que los analizadores JSON no aceptan la sintaxis de llaves.
¿Cuál es la diferencia entre \uXXXX y \u{XXXXX}?
\uXXXX es la sintaxis original de cuatro dígitos hex de ECMAScript 1 (1997) y la especificación JSON (RFC 8259). Solo cubre el Plano Multilingüe Básico (U+0000–U+FFFF). \u{XXXXX} es la sintaxis de llaves de ES6 que acepta cualquier número de dígitos hex y cubre el rango Unicode completo hasta U+10FFFF. La forma de llaves es válida en JavaScript ES6+ y muchos lenguajes modernos, pero no en JSON — la especificación JSON nunca fue actualizada para incluirla.
¿Por qué "😀".length devuelve 2 en JavaScript?
Las cadenas JavaScript son internamente UTF-16. Los puntos de código por encima de U+FFFF se almacenan como dos unidades de código de 16 bits (un par sustituto), por lo que String.prototype.length cuenta unidades de código, no caracteres. Usa [...str].length (el spread usa el iterador de cadena, que es consciente de puntos de código) o Array.from(str).length para obtener el conteo de caracteres correcto. Intl.Segmenter da conteos de clústeres de grafemas, que es lo que los usuarios perciben como "número de caracteres".
¿Cuándo necesito realmente escapar Unicode en JavaScript?
Raramente en código moderno. Los archivos fuente ES6+ guardados como UTF-8 pueden contener caracteres Unicode directamente. Necesitas escapes \u cuando: (1) el archivo debe ser solo ASCII para una cadena de herramientas antigua, (2) estás construyendo una cadena JSON programáticamente y necesitas incrustar contenido no ASCII de forma segura, (3) el entorno destino tiene soporte Unicode incompleto, o (4) estás depurando un punto de código específico y quieres hacerlo explícito.
¿Requiere JSON escapar los caracteres no ASCII?
No — RFC 8259 permite que cualquier carácter Unicode codificado como UTF-8 aparezca sin escapar en una cadena JSON, excepto los caracteres de control (U+0000–U+001F). Muchos serializadores JSON escapan el rango no ASCII completo igualmente, por seguridad en transportes solo ASCII o para evitar riesgos de inyección HTML. Ambas representaciones son idénticas para un analizador conforme.
¿Qué es String.fromCodePoint y por qué debería preferirlo sobre String.fromCharCode?
String.fromCharCode (ES1) opera en unidades de código UTF-16 crudas y trunca silenciosamente los valores por encima de 0xFFFF. String.fromCodePoint (ES6) maneja el rango Unicode completo — pasa 0x1F600 y obtienes 😀, no basura. Usa siempre fromCodePoint al convertir un número de punto de código a un carácter, especialmente si el punto de código puede estar en el plano astral.
¿Qué hace el modo "all" que los modos JSON y ES6 no hacen?
El modo all escapa cada carácter — incluidas las letras y dígitos ASCII ordinarios — no solo los no ASCII o no imprimibles. El resultado es una cadena puramente ASCII donde cada carácter se representa como \uXXXX. Útil para incrustar en literales de cadena C que deben ser solo ASCII, ciertos formatos de archivos .properties (la herramienta native2ascii de Java produce esto), o para depurar secuencias de caracteres donde quieres ver cada punto de código explícitamente.
¿Puede dividir una cadena en un emoji romperla?
Sí. Dado que muchos emoji son pares sustitutos (dos unidades de código UTF-16), las operaciones que trabajan a nivel de unidad de código — str[i], str.substring(), str.split('') — pueden cortar entre las dos mitades de un par, produciendo sustitutos sueltos y salida corrupta. Alternativas seguras: el operador spread [...str] itera por punto de código, e Intl.Segmenter itera por clúster de grafemas (teniendo en cuenta los modificadores de emoji y las secuencias ZWJ).