Una entidad HTML es una forma de escribir un carácter para que el navegador lo muestre como texto en lugar de interpretarlo como marcado. Si escribes un < literal en tu contenido, el navegador empieza a leer una etiqueta; si en su lugar escribes <, renderiza un < literal en la página. Ese intercambio es la idea central de la codificación de entidades HTML.
Cinco caracteres tienen un significado especial en HTML y son los que más a menudo escaparás: <, >, &, " y '. Los escapas por dos motivos. El primero es la visualización: quieres mostrar código o marcado como texto. El segundo, y más importante, es la seguridad: escapar entradas no confiables es la base para frenar el cross-site scripting (XSS).
Hay tres maneras intercambiables de escribir cualquier entidad (con nombre <, decimal < y hexadecimal <), y todas se resuelven al mismo carácter. La pregunta más espinosa es cuándo escapar y con qué, porque la respuesta correcta depende de dónde aterrice el valor: texto HTML, un atributo, un script o una URL. Esta guía recorre las notaciones, el conjunto reservado, una matriz de decisión por contexto y los tropiezos que más afectan a la gente.
¿Qué es una entidad HTML? (anatomía)
Una entidad HTML, también llamada referencia de carácter, es un código corto que sustituye a un solo carácter. Toda entidad empieza con un ampersand & y termina con un punto y coma ;. Lo que va en medio determina qué carácter obtienes.
Hay tres formas:
&name;— una referencia con nombre, como<o©.&#decimal;— una referencia numérica decimal, como<.&#xhex;— una referencia numérica hexadecimal, como<.
El navegador lee la referencia, busca el carácter al que apunta y renderiza ese único carácter. Nada cambia en el resultado visible: < y un < literal se muestran idénticos. La única diferencia es que la entidad se trata como texto, nunca como el inicio de una etiqueta.
Las tres notaciones: con nombre, decimal, hexadecimal
Las tres notaciones referencian el mismo punto de código Unicode; solo difieren en la grafía. Una entidad con nombre es la forma legible, pero existe únicamente para los caracteres que tienen un nombre definido. Una entidad decimal escribe el punto de código en base 10. Una entidad hexadecimal escribe el mismo punto de código en base 16, lo que se corresponde uno a uno con la notación U+XXXX que ves en el estándar Unicode.
| Carácter | Con nombre | Decimal | Hex |
|---|---|---|---|
< | < | < | < |
& | & | & | & |
© | © | © | © |
é | é | é | é |
Como el hex refleja directamente U+XXXX (é es U+00E9, de ahí é), muchos desarrolladores recurren a él cuando documentan o razonan sobre un punto de código concreto. Para el marcado del día a día, las entidades con nombre se leen mejor.
Los cinco caracteres reservados que debes escapar
Estos son los caracteres especiales de HTML que cambian cómo el navegador analiza un documento. Si alguno aparece en contenido que debería mostrarse en lugar de ejecutarse, escápalo.
| Carácter | Con nombre | Decimal | Hex | Qué se rompe si no lo escapas |
|---|---|---|---|---|
< | < | < | < | Inicia una etiqueta — el navegador lee el texto siguiente como marcado |
> | > | > | > | Cierra una etiqueta antes de tiempo |
& | & | & | & | Inicia una entidad — el resto puede malinterpretarse como una referencia |
" | " | " | " | Termina antes de tiempo el valor de un atributo entre comillas dobles |
' | ' | ' | ' | Termina antes de tiempo el valor de un atributo entre comillas simples |
La entidad del ampersand de HTML es la raíz de todo el sistema. El carácter & inicia todas las entidades, así que hay que escaparlo primero: si escapas los corchetes angulares antes que el ampersand, vuelves a escapar el & de las entidades que acabas de producir. Más sobre ese tropiezo a continuación.
¿Cuándo necesitas escapar realmente? (según el contexto)
Aquí es donde viven la mayoría de los errores y de las vulnerabilidades. La regla es escapar en el momento de la salida, ajustando el escape al contexto donde aterriza el valor. Un valor que es seguro en un lugar es peligroso en otro, así que la codificación que apliques tiene que coincidir con el destino.
Contenido de un elemento HTML
Cuando colocas un valor entre etiquetas (dentro de un <p>, un <div>, un <td>), escapa <, > y &. Escapar las comillas aquí es inofensivo pero innecesario. Si quieres mostrar el texto <strong> como caracteres literales en lugar de poner en negrita la siguiente palabra, codifícalo a <strong> y el navegador imprime la etiqueta en lugar de aplicarla.
Valores de atributos HTML
Dentro de un atributo, las comillas se vuelven críticas. Si un valor está en title="…" y contiene un " sin escapar, termina el atributo antes de tiempo y permite a un atacante añadir atributos nuevos: un vector de XSS clásico. Escapa " (e idealmente ') en el contexto de atributos. Un valor como He said "hi" debe convertirse en He said "hi" para mantenerse contenido.
Dentro de <script> o JavaScript en línea
Las entidades HTML no ayudan aquí. Una cadena incrustada en un bloque <script> o en un manejador de eventos en línea necesita escapado de cadenas de JavaScript o JSON, no referencias de carácter. Escribir " dentro de un literal de cadena de JS produce los seis caracteres literales, no una comilla. Para este contexto, usa la herramienta Escape JSON y lee la guía completa de escapado de cadenas JSON para conocer las reglas de \uXXXX que realmente aplican dentro de un script.
Dentro de una URL
Una URL tiene su propio esquema de escapado: la codificación porcentual. Las entidades HTML no harán que un valor sea seguro para una URL. La cadena a&b c corresponde en una consulta como a%26b%20c, no como a&b c: el espacio sigue rompiendo la URL y el & sigue separando parámetros. Usa el Codificador / Decodificador URL para esto, y la guía de codificación y decodificación de URL para conocer las reglas completas sobre caracteres reservados frente a no reservados.
La matriz de decisión
| Contexto | Escapa con | Ejemplo | Elección errónea que falla |
|---|---|---|---|
| Contenido de elemento HTML | Entidades HTML (< > &) | <strong> → <strong> | Dejar < sin escapar inyecta una etiqueta |
| Valor de atributo HTML | Entidades HTML (" ' críticas) | "hi" → "hi" | Un " sin escapar se escapa del atributo |
<script> / JS en línea | Escapado de cadenas JS / JSON | " → \" | Las entidades HTML son inertes en JS |
| URL / cadena de consulta | Codificación porcentual | espacio → %20 | & y las entidades siguen rompiendo la URL |
Con nombre vs numéricas: ¿cuál deberías usar?
Las entidades con nombre son legibles y la opción por defecto correcta para los caracteres reservados comunes y los símbolos conocidos: <, &, ©, —. Sin embargo, solo existen para los caracteres que tienen un nombre definido. Las entidades numéricas, decimales o hexadecimales, pueden codificar cualquier punto de código, incluidos los que no tienen nombre, lo que las convierte en el recurso universal de reserva. Cuando no puedas garantizar que el sistema consumidor admita una entidad con nombre concreta, la numérica es la opción segura.
Por qué el apóstrofo es ' y no '
La entidad con nombre ' se introdujo solo en HTML5 y XML. Está indefinida en HTML4, así que un puñado de analizadores antiguos y clientes de correo la renderizan como el texto literal ' en lugar de un apóstrofo. La referencia numérica ' (y su gemela decimal ') apunta exactamente al mismo carácter, U+0027, y la entiende todo analizador conforme jamás escrito. Las bibliotecas de escapado bien probadas, como he, emiten ' para la comilla simple precisamente por esta razón, y un buen codificador sigue esa convención para que la salida sea segura de colocar en cualquier contexto HTML, XML o de atributo.
Conjunto de caracteres vs entidades: cuándo codificar lo no ASCII
Un conjunto de caracteres, como UTF-8, decide cómo se almacenan los caracteres en forma de bytes. Una entidad es una forma de deletrear un carácter usando solo ASCII básico (&, #, ;, letras, dígitos). Son capas distintas, y confundirlas lleva a codificación innecesaria.
En una página UTF-8 (es decir, casi cualquier página moderna que declara <meta charset="utf-8">), las letras acentuadas, las rayas y los emojis son caracteres crudos válidos. Deja é, — y 😀 tal como están. Codificar todo en entidades solo importa cuando el texto debe sobrevivir a un conjunto de caracteres heredado de un solo byte o a un sistema que estropea el UTF-8 crudo; existe un modo de “codificar todo lo no ASCII” para esos casos. Si no tienes claro cómo se relacionan bytes, puntos de código y caracteres, la guía de codificación UTF-8, UTF-16 y Unicode expone el modelo.
Tropiezos comunes con las entidades HTML
Escapar el & al final causa doble escapado
El orden importa. Si reemplazas < y > antes que &, las entidades que acabas de crear (<, >) también ven su & inicial escapado, así que < acaba como &lt; y se renderiza como el texto literal <. Escapa siempre & primero, luego el resto. Esta única regla previene el error de codificación más común que existe.
Doble codificación de texto ya escapado
Pasar de nuevo por un codificador un texto que ya está escapado lo recodifica. & se convierte en &amp;, y el visitante ve & en la página en lugar de &. Escapa exactamente una vez, en el momento de la salida. Si un valor atraviesa varias capas, asegúrate de que solo una de ellas lo escape.
Mojibake al decodificar
Ir en la dirección contraria tiene su propia trampa. Decodifica con el conjunto de caracteres equivocado, o decodifica dos veces, y obtienes una salida ilegible: el clásico mojibake. Si una página muestra un &lt; literal donde esperabas <, pégalo en el Decodificador de entidades HTML para ver exactamente a qué se resuelven las entidades; maneja referencias con nombre, decimales, hex e incluso referencias heredadas sin terminar como © sin punto y coma final.
Confiar en el escapado como cura completa contra XSS
El escapado es la primera línea de defensa, no la única. Como HTML tiene varios contextos con reglas distintas, escapar para el equivocado deja un agujero: comillas en atributos, escapado de JS en scripts, codificación porcentual en URL. Combina un escapado correcto y consciente del contexto con una Content Security Policy y el auto-escapado de tu framework. Piensa en la codificación de entidades como los cimientos, con CSP y los valores por defecto del framework superpuestos encima.
Cómo codificar y decodificar entidades en la práctica
Cuando construyes HTML a mano, lo escapas tú mismo. Aquí tienes una escapeHtml() correcta que maneja el orden con & primero, además de la mejor práctica para código de aplicación real.
// Los cinco caracteres reservados y sus entidades seguras:
// < → < > → > & → & " → " ' → '
function escapeHtml(str) {
return str
.replace(/&/g, '&') // & FIRST, so later entities are not double-escaped
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, '''); // numeric form — safe in HTML4, HTML5 and XML
}
const userInput = `<a href="x">Tom & Jerry's</a>`;
const safe = escapeHtml(userInput);
// → <a href="x">Tom & Jerry's</a>
// Better in app code: let the platform escape for you.
// el.textContent = userInput; // the browser escapes; no manual replace
// React / Vue / Angular escape interpolated text by default
// Server templates (Jinja, ERB, Blade) auto-escape unless you opt out
La función artesanal es útil para entender qué ocurre y para conversiones puntuales, pero en producción prefiere el camino integrado. Asignar element.textContent deja que el navegador escape por ti, y los frameworks modernos escapan los valores interpolados de forma automática. Reserva el escapado manual para los casos que la plataforma no cubre.
Para trabajo improvisado, el Codificador de entidades HTML escapa el conjunto reservado (con nombre, decimal o hex), y el Decodificador de entidades HTML lo revierte. Los dos son inversos exactos para los caracteres reservados, así que puedes hacer un ciclo de ida y vuelta del texto por ambos sin pérdida.
Preguntas frecuentes
¿Qué es una entidad HTML?
Una entidad HTML es un código corto, que empieza con & y termina con ;, que representa un solo carácter. El navegador renderiza el carácter al que apunta la entidad en lugar de tratarlo como marcado. Por ejemplo, < muestra un < literal y & muestra un & literal.
¿Qué caracteres necesito escapar en HTML?
Los cinco caracteres especiales reservados de HTML: <, >, &, " y '. En el contenido de un elemento necesitas sobre todo <, > y &; en los valores de atributos las comillas " y ' también se vuelven críticas. Escapa primero el ampersand & para que las demás entidades no sufran doble escapado.
¿Debería usar entidades con nombre o numéricas (decimal/hex)?
Usa entidades con nombre (<, ©) por legibilidad con los caracteres comunes, ya que son fáciles de reconocer. Usa entidades numéricas (decimal < o hex <) cuando necesites codificar un carácter sin nombre definido, o cuando no puedas garantizar que el consumidor admita una entidad con nombre dada. Ambas formas referencian el mismo punto de código.
¿Protegen las entidades HTML contra XSS?
Son los cimientos, cuando se aplican correctamente. Escapar los cinco caracteres reservados antes de colocar entradas no confiables en el contenido de un elemento o atributo HTML detiene la inyección de etiquetas y scripts. Pero el escapado depende del contexto: los bloques de script necesitan escapado de JavaScript y las URL necesitan codificación porcentual. Combina un escapado correcto y consciente del contexto con CSP y el auto-escapado del framework.
¿Por qué mi página muestra &lt; en lugar de <?
Eso es doble escapado. El texto se codificó dos veces, o el & se escapó después de los corchetes angulares, así que el & de < se convirtió en &. El visitante ve entonces < como texto literal. Escapa exactamente una vez y siempre escapa & primero. La herramienta decodificadora puede confirmar a qué se resuelven las entidades.
¿Necesito escapar caracteres como é, — o emojis?
Normalmente no. En una página que declara <meta charset="utf-8">, las letras acentuadas, las rayas y los emojis son caracteres crudos válidos y no necesitan codificación: déjalos tal cual. Solo codifica lo no ASCII cuando el texto deba pasar por un conjunto de caracteres heredado de un solo byte o por un sistema que corrompe el UTF-8 crudo.