Codificador y decodificador de entidades HTML

Escapa texto para que sea seguro dentro de HTML, o decodifica entidades con nombre y numéricas de vuelta a los caracteres que representan.

Texto
Codificado

La salida aparecerá aquí

Qué hace esta herramienta

HTML no tiene forma de distinguir entre un signo de menor que usted quería como texto y uno que abre una etiqueta. El lenguaje resuelve esto con entidades: secuencias de escape cortas que representan un carácter sin que se lea como marcado. Esta herramienta convierte en ambos sentidos — texto plano a su forma escapada, y HTML escapado de vuelta a los caracteres que representa.

Ambos sentidos se ejecutan por completo en su navegador. Aquí eso importa más que en la mayoría de las herramientas, porque el texto que la gente pega en un decodificador de entidades suele ser una página raspada, el correo de un cliente o una columna de base de datos que alguien intenta entender.

Los cinco caracteres que importan

Existen miles de entidades, pero solo hacen falta unas pocas para que el texto sea seguro. La codificación aquí sustituye exactamente cinco caracteres y deja legible todo lo demás:

  • El ampersand pasa a ser & — este primero, o cada sustitución posterior se volvería a leer como una entidad.
  • El signo de menor que pasa a ser < — el carácter que puede iniciar una etiqueta.
  • El signo de mayor que pasa a ser > — menos peligroso por sí solo, se escapa por simetría y para sobrevivir a analizadores descuidados.
  • La comilla doble pasa a ser " — necesaria dentro de valores de atributo escritos con comillas dobles.
  • El apóstrofo pasa a ser ' — necesario dentro de valores de atributo escritos con comillas simples.

Ese último se escribe numéricamente a propósito. Existe un nombre, ', pero viene de XML y HTML 4 nunca lo definió, así que los analizadores antiguos lo pasan como texto literal y el escapado falla en silencio. La forma numérica siempre ha funcionado en todas partes, y por eso las bibliotecas de escapado serias la emiten.

Con nombre, decimal y hexadecimal

Cualquier carácter puede escribirse de tres maneras, y la decodificación las acepta todas. La raya es un buen ejemplo:

named     —      la forma legible, pero solo para caracteres con nombre
decimal   —      el punto de código en base 10
hex       —     el mismo punto de código en base 16, la notación de las tablas Unicode

Al decodificar, esta herramienta reconoce los 255 nombres del conjunto de HTML 4 — las letras latinas, el alfabeto griego, las flechas, los símbolos matemáticos y la puntuación tipográfica, que entre todos cubren prácticamente todo lo que aparece en texto real. HTML 5 define unos 2200 más, casi todos símbolos matemáticos poco frecuentes; llevar esa tabla añadiría decenas de kilobytes a cada carga de página a cambio de nombres que la mayoría de los documentos nunca usa. Un nombre fuera del conjunto se informa en vez de descartarse, así que el coste es un aviso, nunca una respuesta equivocada.

La codificación va en sentido contrario y se mantiene deliberadamente sencilla: nombres para los cinco caracteres anteriores, números decimales para todo lo demás. Nada se convierte en … ni en ’ cuando el carácter en sí es perfectamente válido en un documento UTF-8.

Escapar no es una regla sino cuatro

Es tentador tratar el escapado de entidades como la respuesta a la inyección, y dentro del contenido de un elemento realmente lo es. Pero HTML son en realidad cuatro lenguajes anidados unos en otros, y cada uno tiene sus propias reglas. El escapado de entidades es correcto en los dos primeros de estos lugares e inútil en el resto:

  • Contenido de elemento — texto entre etiquetas. El escapado de entidades es exactamente lo indicado.
  • Valores de atributo entrecomillados. El escapado de entidades es correcto, siempre que el atributo esté realmente entrecomillado; sin comillas, un espacio en el valor termina el atributo y el escapado no le aporta nada.
  • Dentro de un bloque script. Se aplica el escapado de cadenas de JavaScript, no las entidades — el navegador no decodifica entidades ahí, así que una comilla escapada llega como los caracteres literales ".
  • Atributos de URL como href y src. El escapado de entidades no detiene una URL javascript:, porque el peligro está en el esquema, no en ningún carácter que una entidad fuera a sustituir.

La regla práctica: escape en el punto donde el texto se inserta en un documento, con las reglas del contexto exacto en el que aterriza, y no una sola vez, pronto, con la esperanza de que valga en todas partes más adelante.

Por qué a veces se ve &

Este es, con diferencia, el motivo más común para recurrir a un decodificador de entidades. El texto se escapó y luego se volvió a escapar, normalmente una vez por el código de la aplicación y otra por un motor de plantillas o framework que ya escapa su salida:

original     Fish & Chips
escaped      Fish & Chips
escaped x2   Fish & Chips

La segunda línea se muestra en la página como el original. La tercera se muestra como la segunda, es decir, el visitante ve la entidad en lugar del carácter. La decodificación quita exactamente una capa, así que ejecutarla una vez le dice en qué caso está. Si la salida todavía contiene entidades, había más de una capa. La solución casi nunca es quitar entidades al mostrar: es encontrar y eliminar el paso de escapado duplicado, porque el mismo fallo está corrompiendo en silencio los datos almacenados.

No-ASCII, y la opción para ello

Una página servida como UTF-8 no necesita entidades para letras acentuadas, hebreo, árabe, chino ni emoji. Esos caracteres son válidos tal cual, y dejarlos legibles mantiene el código fuente legible y el archivo más pequeño. Eso es lo predeterminado aquí.

La opción existe porque algunos destinos siguen exigiendo ASCII: plantillas de correo antiguas, sistemas que estropean los bytes por encima de 127, o una columna de base de datos cuya codificación nadie quiere cambiar. Al activarla, cada carácter así se escribe como referencia decimal: é pasa a ser é, א pasa a ser א.

Los emoji merecen una nota. Un emoji se escribe como una única referencia para todo su punto de código, por ejemplo 🙂, nunca como dos mitades. Si ha usado la herramienta de escapado JSON, esto es lo contrario de lo que ocurre allí, donde el formato exige expresamente dividir un emoji en dos escapes \u. El mismo carácter, dos respuestas correctas, porque los dos formatos definen el escapado sobre unidades distintas.

Cuando una referencia no se puede decodificar

La decodificación aquí nunca falla y nunca borra nada. Una referencia que no se puede resolver se deja exactamente como se encontró y se lista encima de la salida con su línea y su columna. Se informan tres cosas:

  • Un nombre desconocido, como &nbps; — casi siempre una errata de  . Este es el aviso sobre el que conviene actuar: significa que falta un espacio en su contenido y nadie se dio cuenta.
  • Un número que no es un carácter, como � o un valor por encima del rango Unicode. No hay nada a lo que decodificarlo, así que se queda como texto.
  • Un número entre 128 y 159. Véase más abajo.

Un ampersand suelto no se informa en absoluto. En HTML, R&D y Q&A son texto corriente, y tratar cada ampersand perdido como un error sepultaría los avisos que importan bajo el ruido de la prosa.

El rango de 128 a 159 es una auténtica rareza. Esos números designan caracteres de control invisibles que nadie pretende escribir jamás; aparecen porque el documento se redactó en Windows-1252, donde esos mismos números son comillas curvas, rayas y el símbolo del euro. Los navegadores los leen calladamente como Windows-1252 por esa misma razón, y esta herramienta hace lo mismo para que el resultado coincida con lo que la página mostraría de verdad — pero lo dice en los avisos, porque una sustitución silenciosa que usted no pidió es peor que una ruidosa.

Preguntas frecuentes

¿Basta con escapar estos cinco caracteres para frenar el XSS?
En el contenido de un elemento y en valores de atributo entrecomillados, sí: para eso sirve exactamente. No basta dentro de un bloque script o style, en un atributo sin comillas, ni en un atributo de URL como href, cada uno de los cuales necesita sus propias reglas. Escapar es una propiedad del lugar donde aterriza el texto, no del texto.
¿Por qué el apóstrofo se codifica como ' y no como '?
Porque ' es una entidad XML que HTML 4 nunca definió. Los analizadores anteriores a HTML 5 la dejan como texto literal, así que un apóstrofo que usted creía escapado no lo está. La forma numérica funciona en todos los analizadores, y por eso es la opción segura.
Mi página muestra & en lugar de un ampersand. ¿Qué pasó?
El texto se escapó dos veces. Decodifíquelo aquí: una pasada convierte & en &, lo que confirma la capa de más. Arregle el proceso y no el texto: normalmente su código escapa una salida que el motor de plantillas ya estaba escapando.
¿Necesito codificar hebreo, árabe o emoji?
No en una página moderna servida como UTF-8; son válidos tal cual. Active la opción de no-ASCII solo cuando algo más adelante exija ASCII, como una plantilla de correo antigua. Cada emoji se escribe entonces como una única referencia numérica.
¿Por qué avisa sobre “ si lo decodificó bien?
Porque 147 designa un carácter de control invisible, no la comilla que usted ve. Los documentos que lo usan se escribieron en Windows-1252, donde 147 es una comilla curva; los navegadores lo leen así y esta herramienta también. El aviso le indica que hubo una sustitución, para que corrija la codificación de origen si está en su mano.
¿Se envía mi texto a algún sitio?
No. La codificación y la decodificación se ejecutan por completo en su navegador; nada de lo que pegue sale de su dispositivo.