Generador de Data URI
Codifica una imagen, una fuente o un texto como data: URI, o descodifica uno, midiendo Base64 frente a la codificación porcentual. Todo en tu navegador.
data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232563eb'%20stroke-width='2'%3E%3Ccircle%20cx='12'%20cy='12'%20r='9'/%3E%3Cpath%20d='M8%2012.5l2.5%202.5%205-6'/%3E%3C/svg%3E
Aquí la codificación porcentual es más corta: 255 caracteres frente a 272, un ahorro de 17.
Tamaños
- Bytes de origen
- 174
- URI, en Base64
- 272
- URI, con codificación porcentual
- 255
Un archivo dentro de una dirección
Un data URI es un archivo entero escrito como una dirección. En lugar de apuntar a un recurso que el navegador tiene que ir a buscar, lleva los propios bytes, de modo que un icono puede vivir dentro de la hoja de estilos que lo usa y una imagen pequeña dentro del HTML que la muestra. El RFC 2397 definió el esquema en 1998 y lleva dos décadas soportado en todas partes.
La gramática es corta. Después del esquema viene un tipo de medio opcional con parámetros opcionales, luego una marca base64 opcional, luego una coma y luego los datos. Todo lo anterior a la coma es la cabecera y todo lo posterior son los datos: por eso el navegador divide en la primera coma y por eso una coma dentro de los datos es inofensiva.
data:[<mediatype>][;base64],<data> data:,hello text/plain;charset=US-ASCII data:text/plain;charset=utf-8,hello the same bytes, spelled out data:image/png;base64,iVBORw0KGgo= binary, Base64 encoded data:image/svg+xml,%3Csvg%20... markup, percent-encoded
Una cabecera vacía es válida y significa text/plain;charset=US-ASCII, el único valor por omisión que te entrega la especificación. Esta página avisa de que lo ha aplicado en vez de mostrar un tipo de medio que nunca escribiste.
Dos codificaciones, y cuál es más corta
El RFC define dos maneras de escribir los datos, y la elección no es una cuestión de estilo: para un archivo concreto una de ellas es claramente más corta, y cuál lo sea depende por completo de lo que contenga el archivo.
Base64 reescribe cada tres bytes como cuatro caracteres de un alfabeto de 64. El coste es fijo y previsible: exactamente un tercio más, más el relleno. Funciona con cualquier cosa, y por eso es la forma a la que se recurre por defecto.
La codificación porcentual deja tal cual cualquier carácter válido en una URL y gasta tres caracteres en todos los demás. Con datos que son sobre todo ASCII sencillo —un SVG, una hoja de estilos pequeña, un trozo de JSON— la mayoría de los bytes pasan intactos y el resultado sale más corto que en Base64, a menudo entre un veinte y un treinta por ciento. Con un PNG o una fuente, donde casi todos los bytes hay que escaparlos, se acerca al triple del original y resulta mucho peor que Base64.
Cuánto se escapa es en sí mismo una decisión, y esta página ofrece las dos respuestas:
- El conjunto estricto escapa todos los bytes fuera de los caracteres no reservados del RFC 3986: letras, dígitos, guion, punto, guion bajo y tilde. El resultado es seguro en cualquier contexto, a cambio de escapar signos de puntuación que no lo necesitaban.
- El conjunto mínimo conserva todo lo que la gramática del data URI permite realmente, incluidas las barras, los dos puntos, los signos de igual, las comillas y los paréntesis de los que está llena la marcación. Aquí es donde gana la codificación porcentual, y por eso un SVG escrito con comillas simples alrededor de sus atributos se codifica mucho mejor que uno escrito con comillas dobles.
- El destino añade una regla más. Dentro de un atributo HTML un ampersand suelto inicia una referencia de carácter, así que elegir el destino img también lo escapa. Nada más cambia: la comilla doble, los signos de menor y mayor y la barra invertida ya están fuera del conjunto permitido y se escapan en ambos niveles.
- El signo de porcentaje se escapa siempre, en todos los niveles. Introduce una secuencia de escape, así que un porcentaje literal hay que escribirlo como %25 o los dos caracteres siguientes se leen como hexadecimal.
En lugar de dejarte adivinar, la página codifica los datos de las dos maneras e informa de ambas longitudes y de la diferencia. Elige la que gane, o fija la codificación a mano si tienes un motivo.
El 33% es una cifra anterior a la compresión
Casi toda discusión sobre data URIs repite que Base64 añade un tercio al tamaño del archivo. Aritméticamente es cierto y en la práctica induce a error, porque la cifra describe los bytes antes de llegar a la red y todo servidor comprime el texto de salida.
Base64 no añade información; reparte la misma información entre más caracteres, usando solo 64 de los 256 valores que puede tomar un byte. Es exactamente la clase de redundancia que gzip y Brotli existen para eliminar. Con datos ya comprimidos —un PNG, un JPEG, una fuente WOFF2— el compresor no puede tocar el contenido pero sí volver a empaquetar el Base64 hasta algo muy cercano al tamaño original. El famoso tercio desaparece en su mayor parte.
Por eso esta página mide en lugar de afirmar. Comprime tres cosas con la propia implementación de gzip del navegador: los datos tal como se servirían en un archivo aparte, el documento que los lleva en Base64 y el documento que los lleva con codificación porcentual. Esas tres cifras son la versión honesta del argumento del tamaño, y a menudo muestran que el coste real de incrustar no es el tamaño en absoluto.
Los costes reales están en otra parte. Un archivo incrustado no se puede cachear por su cuenta, así que se descarga otra vez con cada copia del documento que lo lleva, y nunca se comparte entre dos páginas. Además bloquea: una hoja de estilos no termina de analizarse hasta que ha leído entero el URI que tiene en medio. HTTP/2 eliminó casi toda la penalización por petición que hacía atractivo incrustar. Para un icono diminuto que aparece en todas las páginas sigue siendo un intercambio razonable; a partir de unas decenas de kilobytes normalmente no, y por eso esta página empieza a avisar en treinta.
El tipo sale de los bytes
Un data URI solo sirve si el tipo de medio es correcto. Equivócate y el navegador se negará a mostrar la imagen, aplicará el analizador equivocado o —para cualquier cosa servida con un tipo que no reconoce— ofrecerá una descarga en su lugar.
Cuando sueltas un archivo, el navegador informa de un tipo propio, pero ese informe se deriva de la extensión del archivo y de nada más. Renombra un JPEG a .png y el navegador lo llamará PNG. Esta página lee en cambio los primeros bytes. Casi todos los formatos binarios empiezan por una firma: PNG empieza con un byte que no puede aparecer en ASCII seguido de las letras PNG, JPEG con tres bytes fijos, PDF con un signo de porcentaje y la palabra PDF, y WOFF y WOFF2 con sus propias etiquetas de cuatro caracteres. Cuando la firma y la extensión no coinciden, gana la firma y se informa de la discrepancia.
La lista es deliberadamente corta: los formatos que la gente incrusta de verdad, no todo lo que un navegador es capaz de husmear. Si nada coincide y los bytes son texto válido, el tipo es texto, distinguiendo SVG de XML por cómo abre la marcación. Si no coincide absolutamente nada, la respuesta es application/octet-stream, y el campo sigue siendo editable, porque una suposición equivocada es peor que una admitida.
Para los datos textuales también importa el juego de caracteres. El valor por omisión de la especificación es US-ASCII, que no es lo que nadie quiere decir hoy, así que un tipo de medio textual se ofrece con charset=utf-8 añadido. Omitirlo no corrompe los bytes, pero sí cambia cómo se vuelven a leer.
Leer uno de vuelta
La otra mitad del trabajo es la que aparece más a menudo: has encontrado un data: URI en una hoja de estilos, en un volcado del DOM o en una página guardada y quieres saber qué es. Pégalo y la página lo desmonta: el tipo de medio, sus parámetros, qué codificación se usó, a cuántos bytes se descodifica frente a cuántos caracteres cuesta y qué son esos bytes con independencia de lo que afirme la cabecera. Una imagen se dibuja, el texto se muestra y cualquier otra cosa recibe sus primeros bytes en hexadecimal.
La descodificación es estricta, porque un URI pegado es entrada no fiable y una respuesta verosímil pero equivocada es peor que un error. Una coma que falta, un tipo de medio mal formado, un signo de porcentaje sin dos dígitos hexadecimales detrás, un carácter fuera del alfabeto Base64: cada caso falla indicando la posición del problema en vez de repararse en silencio.
Se toleran dos cosas, porque las tolera cualquier navegador y porque un URI copiado de una hoja de estilos con saltos de línea sería si no inservible. Los espacios dentro de los datos se eliminan y el relleno Base64 que falta se completa. De ambas cosas se informa, para que sepas que el URI que tienes no es exactamente el URI que funciona en todas partes.
Una cosa que se le parece se rechaza de plano. El alfabeto Base64 seguro para URL, que cambia el más y la barra por el guion y el guion bajo, es el que usan los JSON Web Token, y no es el que admite un data URI. Aceptarlo en silencio significaría descodificar a bytes distintos de los que descodificaría un navegador, así que se rechaza por su nombre, con la posición del carácter infractor.
Dónde se ejecuta
Todo ocurre en tu navegador. El archivo que eliges se lee con la API de archivos local y nunca se sube; la codificación, la medición de la compresión y la descodificación se ejecutan en tu propia máquina, y nada se almacena ni se registra. Aquí importa más que en la mayoría de páginas, porque los archivos que la gente convierte en data URI suelen ser recursos internos y los URIs que se pegan para inspeccionarlos vienen de páginas en producción.
Preguntas frecuentes
- ¿Se sube mi archivo a algún sitio?
- No. El archivo se lee en local con la propia API de archivos del navegador, se codifica en tu máquina y no se envía a ninguna parte. Lo mismo vale para un URI que pegues para descodificar.
- ¿Debería usar Base64 o codificación porcentual?
- La que resulte más corta con tus datos, que es lo que la página mide por ti. Como regla general: codificación porcentual para SVG, CSS, JSON y demás texto; Base64 para imágenes, fuentes y cualquier cosa ya comprimida. La diferencia suele ser de un veinte a un treinta por ciento en un sentido o en el otro.
- ¿De verdad Base64 agranda un archivo un 33%?
- Antes de comprimir, sí: cuatro caracteres por cada tres bytes. En la red, en su mayor parte no. Base64 usa solo 64 de los 256 valores posibles de un byte, y esa redundancia es exactamente lo que elimina gzip, así que el tamaño comprimido suele quedar cerca del tamaño comprimido del archivo original. La página mide ambos para que lo veas.
- ¿Cómo de grande puede ser un data URI?
- Los navegadores modernos no imponen un límite estricto a un URI dentro de un documento, aunque las versiones antiguas de Internet Explorer lo dejaban en 32 KB. El tamaño es una cuestión de rendimiento, no de legalidad: un archivo incrustado no se puede cachear por separado y se vuelve a descargar con cada copia del documento. Esta página codifica hasta un megabyte y avisa por encima de treinta kilobytes.
- ¿Por qué se rompe en CSS mi data URI con un SVG?
- Casi siempre por un carácter sin escapar. Una almohadilla —de un color como #2563eb— inicia un identificador de fragmento y corta el URI en ese punto. Una comilla doble cierra la cadena de CSS en la que está. Escribe el SVG con comillas simples alrededor de sus atributos y usa el conjunto de escape mínimo, que escapa la almohadilla y la comilla doble y deja corto todo lo demás.
- ¿Puedo usar un data URI para un script o un iframe?
- Puedes, pero trátalo como una cuestión de seguridad y no de comodidad. Un data URI no hereda origen, y los navegadores ya bloquean la navegación de nivel superior hacia uno precisamente por eso. Una política de seguridad de contenido que permita data: en script-src o frame-src renuncia a casi todo lo que la política protegía; permitirlo en img-src o font-src es lo normal.
- ¿Por qué se rechazó mi Base64 seguro para URL?
- Porque un data URI admite Base64 estándar. El alfabeto seguro para URL cambia el más y la barra por el guion y el guion bajo, que son caracteres distintos y se descodifican a bytes distintos. Aceptarlo significaría que esta página descodifica tu URI de forma distinta al navegador que de verdad lo va a cargar.
- El navegador dice que mi archivo es de un tipo y esta página dice otro. ¿Cuál es el correcto?
- La página. Un navegador informa del tipo que deduce de la extensión del archivo, así que con un archivo renombrado se equivoca. Esta página lee la firma del principio del archivo, que es lo que declara el propio formato. El campo sigue siendo editable si tienes un motivo para sobrescribirlo.