Générateur de Data URI
Encodez une image, une police ou du texte en data: URI, ou décodez-en un : Base64 et encodage pour-cent mesurés l’un contre l’autre. Dans votre navigateur.
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
Ici l’encodage pour-cent est plus court : 255 caractères contre 272, soit 17 d’économie.
Tailles
- Octets source
- 174
- URI, en Base64
- 272
- URI, en encodage pour-cent
- 255
Un fichier dans une adresse
Un data URI est un fichier entier écrit sous forme d’adresse. Au lieu de désigner une ressource que le navigateur doit aller chercher, il transporte les octets eux-mêmes : une icône peut donc vivre dans la feuille de style qui l’utilise, et une petite image dans le HTML qui l’affiche. Le RFC 2397 a défini le schéma en 1998 et il est pris en charge partout depuis deux décennies.
La grammaire est brève. Après le schéma viennent un type de média facultatif avec des paramètres facultatifs, puis un indicateur base64 facultatif, puis une virgule, puis les données. Tout ce qui précède la virgule est l’en-tête et tout ce qui suit est la charge utile : c’est pourquoi le navigateur coupe à la première virgule et pourquoi une virgule dans la charge utile est sans danger.
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
Un en-tête vide est licite et signifie text/plain;charset=US-ASCII, la seule valeur par défaut que la spécification vous donne. Cette page signale qu’elle l’a appliquée plutôt que d’afficher un type de média que vous n’avez jamais écrit.
Deux encodages, et lequel est plus court
Le RFC définit deux façons d’écrire la charge utile, et le choix n’est pas affaire de style : pour un fichier donné l’un des deux est nettement plus court, et lequel dépend entièrement de ce que contient le fichier.
Base64 réécrit chaque groupe de trois octets en quatre caractères d’un alphabet de 64. Le coût est fixe et prévisible : exactement un tiers de plus, plus le remplissage. Cela marche avec n’importe quoi, d’où le réflexe de s’en servir par défaut.
L’encodage pour-cent laisse tel quel tout caractère licite dans une URL et dépense trois caractères pour chacun des autres. Avec une charge utile essentiellement en ASCII simple — un SVG, une petite feuille de style, un bloc JSON — la plupart des octets passent intacts et le résultat est plus court qu’en Base64, souvent de vingt à trente pour cent. Avec un PNG ou une police, où presque chaque octet doit être échappé, on approche du triple de l’original, bien pire que Base64.
Le nombre de caractères échappés est lui-même un choix, et cette page propose les deux réponses :
- Le jeu strict échappe tout octet hors des caractères non réservés du RFC 3986 : lettres, chiffres, trait d’union, point, tiret bas et tilde. Le résultat est sûr dans n’importe quel contexte, au prix de l’échappement de ponctuations qui n’en avaient pas besoin.
- Le jeu minimal conserve tout ce que la grammaire du data URI autorise réellement, dont les barres obliques, les deux-points, les signes égal, les guillemets et les parenthèses dont le balisage est plein. C’est là que l’encodage pour-cent l’emporte, et c’est pourquoi un SVG écrit avec des apostrophes autour de ses attributs s’encode bien mieux qu’un SVG écrit avec des guillemets doubles.
- La destination ajoute une règle de plus. Dans un attribut HTML, une esperluette nue ouvre une référence de caractère : choisir la destination img l’échappe donc aussi. Rien d’autre ne change : le guillemet double, les chevrons et la barre oblique inverse sont déjà hors du jeu autorisé et sont échappés aux deux niveaux.
- Le signe pour-cent est toujours échappé, à tous les niveaux. Il ouvre une séquence d’échappement, donc un pour-cent littéral doit s’écrire %25, sinon les deux caractères suivants sont lus comme de l’hexadécimal.
Plutôt que de vous laisser deviner, la page encode la charge utile des deux manières et indique les deux longueurs ainsi que l’écart. Prenez le gagnant, ou fixez l’encodage à la main si vous avez une raison.
Les 33 % sont un chiffre d’avant compression
Presque toute discussion sur les data URI répète que Base64 ajoute un tiers à la taille du fichier. C’est arithmétiquement vrai et pratiquement trompeur, car le chiffre décrit les octets avant qu’ils n’atteignent le réseau, et tout serveur compresse le texte en sortie.
Base64 n’ajoute pas d’information ; il étale la même information sur plus de caractères, n’utilisant que 64 des 256 valeurs qu’un octet peut prendre. C’est exactement le genre de redondance que gzip et Brotli existent pour retirer. Sur une charge utile déjà compressée — un PNG, un JPEG, une police WOFF2 — le compresseur ne peut rien sur les données elles-mêmes, mais il peut retasser le Base64 jusqu’à très près de la taille d’origine. Le fameux tiers disparaît en grande partie.
Cette page mesure donc au lieu d’affirmer. Elle compresse trois choses avec l’implémentation gzip du navigateur : la charge utile telle qu’elle serait servie en fichier séparé, le document qui la porte en Base64, et le document qui la porte en encodage pour-cent. Ces trois chiffres sont la version honnête de l’argument de la taille, et ils montrent souvent que le vrai coût de l’intégration n’est pas la taille du tout.
Les vrais coûts sont ailleurs. Un fichier intégré ne peut pas être mis en cache pour lui-même : il est retéléchargé avec chaque copie du document qui le porte et ne sera jamais partagé entre deux pages. Il bloque aussi : une feuille de style ne finit pas son analyse tant qu’elle n’a pas lu en entier l’URI installé au milieu. HTTP/2 a supprimé l’essentiel du coût par requête qui rendait l’intégration attrayante. Pour une icône minuscule présente sur chaque page, l’échange reste raisonnable ; au-delà de quelques dizaines de kilo-octets, en général non, et c’est pourquoi cette page commence à avertir à trente.
Le type vient des octets
Un data URI n’est utile que si le type de média est juste. Trompez-vous et le navigateur refusera d’afficher l’image, appliquera le mauvais analyseur, ou — pour tout ce qui est servi avec un type qu’il ne reconnaît pas — proposera un téléchargement à la place.
Quand vous déposez un fichier, le navigateur annonce un type de son cru, mais cette annonce est déduite de l’extension du fichier et de rien d’autre. Renommez un JPEG en .png et le navigateur l’appellera PNG. Cette page lit plutôt les premiers octets. Presque tout format binaire commence par une signature : PNG par un octet impossible en ASCII suivi des lettres PNG, JPEG par trois octets fixes, PDF par un signe pour-cent et le mot PDF, WOFF et WOFF2 par leurs étiquettes de quatre caractères. Quand la signature et l’extension divergent, la signature l’emporte et la divergence est signalée.
La liste est volontairement courte : les formats que les gens intègrent réellement, pas tout ce qu’un navigateur sait renifler. Si rien ne correspond et que les octets sont du texte valide, le type est textuel, SVG et XML étant distingués par ce qui ouvre le balisage. Si rien ne correspond du tout, la réponse est application/octet-stream, et le champ reste modifiable, car une supposition fausse est pire qu’une ignorance avouée.
Pour les charges utiles textuelles, le jeu de caractères compte aussi. La valeur par défaut de la spécification est US-ASCII, qui n’est plus ce que personne veut dire aujourd’hui : un type de média textuel est donc proposé avec charset=utf-8 accolé. L’omettre ne corrompt pas les octets, mais change la façon dont on les relit.
En relire un
L’autre moitié du travail revient plus souvent : vous avez trouvé un data: URI dans une feuille de style, un export du DOM ou une page enregistrée, et vous voulez savoir ce que c’est. Collez-le et la page le démonte : le type de média, ses paramètres, l’encodage employé, le nombre d’octets décodés contre le nombre de caractères que cela coûte, et ce que sont ces octets indépendamment de ce que prétend l’en-tête. Une image est rendue, un texte est affiché, tout le reste reçoit ses premiers octets en hexadécimal.
Le décodage est strict, car un URI collé est une entrée non fiable et une réponse plausible mais fausse est pire qu’une erreur. Une virgule manquante, un type de média mal formé, un signe pour-cent non suivi de deux chiffres hexadécimaux, un caractère hors de l’alphabet Base64 : chacun échoue en indiquant la position du problème au lieu d’être réparé en silence.
Deux choses sont tolérées, parce que tout navigateur les tolère et qu’un URI copié depuis une feuille de style repliée serait sinon inutilisable. Les espaces dans la charge utile sont retirés et le remplissage Base64 manquant est complété. Les deux sont signalés, pour que vous sachiez que l’URI que vous avez n’est pas tout à fait celui qui marche partout.
Une chose qui y ressemble est refusée d’emblée. L’alphabet Base64 sûr pour URL, qui remplace le plus et la barre oblique par le trait d’union et le tiret bas, est celui des JSON Web Token — ce n’est pas celui qu’accepte un data URI. L’accepter en silence reviendrait à décoder vers d’autres octets que le navigateur, donc il est rejeté nommément, avec la position du caractère fautif.
Où cela s’exécute
Tout se passe dans votre navigateur. Le fichier que vous choisissez est lu par l’API de fichiers locale et n’est jamais téléversé ; l’encodage, la mesure de compression et le décodage tournent sur votre machine, et rien n’est stocké ni journalisé. Cela compte ici plus qu’ailleurs, car les fichiers que l’on transforme en data URI sont souvent des ressources internes, et les URI que l’on colle pour les inspecter proviennent de pages en production.
Questions fréquentes
- Mon fichier est-il téléversé quelque part ?
- Non. Le fichier est lu localement par l’API de fichiers du navigateur, encodé sur votre machine et envoyé nulle part. Il en va de même pour un URI que vous collez afin de le décoder.
- Faut-il utiliser Base64 ou l’encodage pour-cent ?
- Celui qui est le plus court pour vos données, ce que la page mesure pour vous. En règle générale : l’encodage pour-cent pour le SVG, le CSS, le JSON et le texte en général, Base64 pour les images, les polices et tout ce qui est déjà compressé. L’écart atteint souvent vingt à trente pour cent dans un sens ou dans l’autre.
- Base64 grossit-il vraiment un fichier de 33 % ?
- Avant compression, oui : quatre caractères pour trois octets. Sur le réseau, en grande partie non. Base64 n’utilise que 64 des 256 valeurs possibles d’un octet, et cette redondance est exactement ce que gzip retire : la taille compressée est donc généralement proche de la taille compressée du fichier d’origine. La page mesure les deux pour que vous le constatiez.
- Quelle taille peut atteindre un data URI ?
- Les navigateurs modernes n’imposent pas de limite stricte à un URI dans un document, même si les vieilles versions d’Internet Explorer le plafonnaient à 32 Ko. La taille est une question de performance et non de légalité : un fichier intégré ne peut pas être mis en cache séparément et est retéléchargé avec chaque copie du document. Cette page encode jusqu’à un mégaoctet et avertit au-delà de trente kilo-octets.
- Pourquoi mon data URI SVG casse-t-il en CSS ?
- Presque toujours à cause d’un caractère non échappé. Un dièse — venu d’une couleur comme #2563eb — ouvre un identifiant de fragment et tronque l’URI à cet endroit. Un guillemet double termine la chaîne CSS dans laquelle il se trouve. Écrivez le SVG avec des apostrophes autour de ses attributs et utilisez le jeu d’échappement minimal, qui échappe le dièse et le guillemet double et laisse tout le reste court.
- Puis-je utiliser un data URI pour un script ou une iframe ?
- Oui, mais traitez cela comme une question de sécurité et non de commodité. Un data URI n’hérite d’aucune origine, et les navigateurs bloquent déjà la navigation de premier niveau vers un tel URI pour cette raison. Une politique de sécurité du contenu qui autorise data: dans script-src ou frame-src abandonne l’essentiel de ce qu’elle protégeait ; l’autoriser dans img-src ou font-src est ordinaire.
- Pourquoi mon Base64 sûr pour URL a-t-il été refusé ?
- Parce qu’un data URI accepte du Base64 standard. L’alphabet sûr pour URL échange le plus et la barre oblique contre le trait d’union et le tiret bas, qui sont des caractères différents décodés en octets différents. L’accepter signifierait que cette page décode votre URI autrement que le navigateur qui le chargera réellement.
- Le navigateur annonce un type et cette page un autre. Lequel a raison ?
- La page. Un navigateur annonce le type qu’il déduit de l’extension du fichier : il se trompe donc sur un fichier renommé. Cette page lit la signature en tête du fichier, c’est-à-dire ce que le format lui-même déclare. Le champ reste modifiable si vous avez une raison de le remplacer.