Wanneer je een afbeelding naar Base64 omzet, krijg je een data-URI: een string als data:image/png;base64,iVBORw0KGgo… die je rechtstreeks in een HTML-src of een CSS-url() kunt plakken. De browser decodeert hem ter plekke en toont de afbeelding zonder aparte download. Geen bestand om te hosten, geen extra request.
Dus moet je dit doen? De korte regel: plaats een afbeelding inline als Base64 wanneer hij klein is (onder ongeveer 2 KB), zelden verandert en je één HTTP-request wilt besparen. Denk aan kleine pictogrammen en logo’s. Voor al het andere houd je het bij een gewoon afbeeldingsbestand: grote afbeeldingen, alles wat je op meerdere pagina’s hergebruikt, alles wat je door de browser wilt laten cachen. Het venijn zit in twee dingen. Base64 maakt een bestand ongeveer 33% groter, en zodra die tekst in je HTML of CSS is ingebed, kun je hem niet meer apart cachen.
Wil je de exacte cijfers voor een specifiek bestand, dan doet de Image to Base64-converter het encoderen in je browser en toont hij de precieze groottetoename, zodat je beslist op basis van echte data en niet op een vuistregel. Deze gids legt uit wat die data-URI eigenlijk is, de rekensom achter de groottekost, wanneer inlinen loont en wanneer een gewoon bestand wint.
Wat “afbeelding naar Base64” eigenlijk oplevert: de data-URI
Een afbeelding naar Base64 omzetten geeft je geen bestand. Het geeft je één lange string die het data-URI-formaat volgt zoals gedefinieerd in RFC 2397 (zie de data:-URL-referentie van MDN). De string bestaat uit drie delen:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…
└──┬─┘ └───┬───┘ └─┬──┘ └─────────┬──────────┘
data: MIME type marker the encoded image bytes
Het MIME-type vertelt de browser wat voor soort afbeelding hij decodeert. De gangbare voor afbeeldingen zijn image/png, image/jpeg, image/gif, image/webp, image/svg+xml en image/x-icon voor favicons. De ;base64,-marker zegt dat de payload die volgt Base64 is in plaats van platte tekst. Alles na de komma is de afbeelding, opnieuw uitgedrukt als printbare ASCII.
Dat laatste deel is belangrijk voor je privacy. De conversie draait volledig in je browser via de readAsDataURL van de FileReader-API, en er wordt niets naar een server geüpload. Je kunt een pre-launch-screenshot, een intern diagram of nog niet uitgebrachte artwork in de tool slepen en toekijken hoe het Netwerk-tabblad leeg blijft. Wil je weten hoe ruwe bytes die ASCII-string worden, dan behandelt understanding Base64 het encoderen vanaf de grond, en de complete Base64-gids breidt hetzelfde data-URL-idee uit naar fonts, PDF’s en andere bestandstypen.
Een echt voorbeeld: een transparante PNG van 68 byte
Hier is het kleinst denkbare geval, een transparante PNG van 1×1, 68 byte op schijf, als complete data-URI:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==
Plak dat in de adresbalk van een browser en je ziet (nou ja, niet ziet, want hij is transparant) een geldige afbeelding renderen met nul netwerkactiviteit. Let op de afsluitende ==: dat is padding, waar we zo op terugkomen. Zo ziet Base64 voor tekst er ook uit, alleen toegepast op afbeeldingsbytes. Als je alleen platte tekststrings hoeft te encoderen of decoderen, dan handelt de Base64-encoder/decoder dat geval af.
De 33% groottekost (en waarom die zich opstapelt)
Base64 werkt in vaste groepen: elke 3 byte binair worden 4 ASCII-tekens. Vier derde is ruwweg 1,33, en daar komt de +33% vandaan. Tel daar nog een byte of twee padding plus het voorvoegsel data:image/png;base64, bij op en de overhead ligt voor piepkleine bestanden iets hoger. Een PNG van 9 KB wordt bijvoorbeeld ongeveer 12 KB tekst.
Waarom precies 3-op-4? Base64 gebruikt een alfabet van 64 tekens: A–Z, a–z, 0–9, plus + en /. Vierenzestig symbolen is 6 bits informatie per teken. Binaire bytes zijn elk 8 bits. Het kleinste gemene veelvoud van 6 en 8 is 24 bits, oftewel 3 byte of 4 Base64-tekens, dus de encoder loopt 24 bits per keer door de afbeelding. Wanneer de lengte van de afbeelding geen net veelvoud van 3 is, vullen één of twee =-tekens de laatste groep aan. Die rekensom ligt vast; er is geen encoderinstelling die de 33% verkleint.
Die 33% is de zichtbare kost. De verborgen kost is dat hij zich opstapelt, en dat is het deel dat de meeste “plaats het gewoon inline”-adviezen overslaan:
- De afbeelding wordt opnieuw gedownload telkens als het omhullende bestand verandert. Een externe
logo.pngis zijn eigen resource. Plaats hem inline instyles.css, en dan maakt elke bewerking aan die stylesheet (een kleurtweak, een nieuwe regel) ook de cache voor de afbeelding ongeldig. Bezoekers downloaden de plaat die ze al hadden opnieuw. - Hij kan niet onafhankelijk gecachet worden. Een gewoon afbeeldingsbestand wordt één keer opgehaald en hergebruikt op elke pagina en bij elk bezoek. Een inline geplaatste data-URI is onderdeel van het document, dus hij wordt opnieuw verstuurd op elke pagina die hem inbedt en bij elke cache miss van dat document.
- CSS is render-blocking. De browser tekent niets totdat hij de CSS heeft. Stop een grote data-URI in een stylesheet en je hebt een render-blocking resource groter gemaakt, wat de eerste paint voor de hele pagina vertraagt.
Heffen gzip of brotli de 33% op?
Deels, niet volledig. Base64-tekst is repetitief genoeg dat gzip en brotli hem goed comprimeren en zo een flink stuk van de inflatie over de lijn terugwinnen. Maar twee dingen blijven waar. Ten eerste is de gecomprimeerde Base64 meestal nog iets groter dan het gecomprimeerde originele binair, omdat je de compressor een minder efficiënt startpunt hebt aangereikt. Ten tweede, en dit is het grotere punt, doet compressie niets aan caching of render-blocking. Een data-URI die over de lijn kleiner is, wordt nog steeds opnieuw gedownload met zijn omhullende bestand en kan nog steeds niet apart gecachet worden.
Met andere woorden: compressie is niet hetzelfde als het wegnemen van de inlining-kost. Als het onderscheid tussen minify, gzip en brotli vaag is, dan zet de code-minification-gids uiteen hoe die lagen stapelen, en waarom het uitknijpen van de bytes het cacheprobleem dat inlinen creëert nooit oplost.
Wanneer een Base64-afbeelding gebruiken (de beslismatrix)
De hele beslissing komt neer op een handvol factoren. Hier staan ze naast elkaar:
| Factor | Neig naar inlinen (Base64) | Neig naar een gewoon bestand |
|---|---|---|
| Grootte | Onder ~2 KB (groen) | Boven ~10 KB (rood); 2–10 KB is een afweging (oranje) |
| Hergebruik | Eén pagina, een plek of twee | Herhaald over veel pagina’s |
| Wijzigingsfrequentie | Verandert vrijwel nooit | Vaak bewerkt |
| Context | HTML-e-mail, op zichzelf staande widget of bookmarklet, JSON/API-payload, een kritiek above-the-fold-pictogram dat één bespaarde request waard is | Content-afbeeldingen, gedeelde cachebare assets |
Die groottedrempels zijn niet willekeurig. Ze weerspiegelen de stoplichtbadge die in de Image to Base64-converter is ingebouwd: groen onder 2 KB, oranje tot 10 KB, rood erboven. De tool leest je daadwerkelijke bestand en vertelt je in welke categorie het valt.
Een simpele vuistregel
Als je één regel onthoudt, maak het dan deze: onder ~2 KB en op slechts één of twee plekken gebruikt, loont inlinen meestal; boven ~10 KB of hergebruikt over pagina’s wint een gewoon gecachet bestand vrijwel altijd. Het middengebied van 2–10 KB is waar je de bespaarde request afweegt tegen de verloren cache voor jouw specifieke situatie.
Goede gevallen in detail
Een paar gevallen waarin Base64 zijn plek echt verdient:
- HTML-e-mail. Veel e-mailclients blokkeren extern gehoste afbeeldingen standaard om privacyredenen, wat elke layout breekt die op een extern logo leunt. Een kleine inline geplaatste data-URI rendert meteen zonder serverfetch. Houd deze beperkt tot logo’s en pictogrammen; plaats nooit een foto inline in een e-mail.
- Op zichzelf staande widgets en bookmarklets. Een bookmarklet of een insluitbare widget moet werken met nul externe afhankelijkheden. Door de pictogrammen inline te plaatsen blijft alles in één neerzetbaar bestand.
- JSON- en API-payloads. Een thumbnail meesturen binnen een JSON-document of een configuratiebestand is soms de schoonste optie: één round trip, één object, geen tweede request om aan te sluiten.
- Een kritiek above-the-fold-pictogram. Wanneer een klein logo deel uitmaakt van je Largest Contentful Paint en je één request van het kritieke pad wilt afschaven, kan inlinen helpen. Nadruk op klein.
Eén patroon bindt deze samen: in elk geval reist de asset mee met iets anders en zou hij anders zijn eigen leveringskanaal nodig hebben. Een e-mail kan niet op je CDN leunen, een bookmarklet heeft geen tweede bestand om op te halen, een JSON-respons is één payload. In elk daarvan is het alternatief voor inlinen niet “een gecachet bestand” maar “een ontbrekende afbeelding”, en dat verandert de rekensom volledig. Dat is de echte toets voor een goed Base64-geval: niet alleen “is het klein”, maar “is een apart bestand hier überhaupt een optie”.
Wanneer NIET inline plaatsen: caching, lazy loading en Core Web Vitals
De keerzijde is langer, want inlinen schakelt stilletjes een aantal dingen uit die de browser goed doet.
Het zwaarst weegt dat je onafhankelijke caching verliest. Dat steekt het meest voor terugkerende bezoekers. Een gewone afbeelding zit na het eerste bezoek in hun cache en laadt daarna voor altijd direct. Een inline geplaatste afbeelding heeft geen eigen cache-item: hij rijdt elke keer mee met het document, dus een terugkerende bezoeker betaalt de bytekost keer op keer.
Je verliest ook lazy loading. Met het attribuut loading="lazy" kan de browser afbeeldingen onder de vouw uitstellen totdat de gebruiker er in de buurt scrolt. Een data-URI wordt geparseerd en “gedownload” op het moment dat de HTML wordt gelezen, dus er valt niets uit te stellen. Plaats een dozijn afbeeldingen onder de vouw inline en je hebt ze allemaal in de initiële load gedwongen.
En je vergroot render-blocking resources. Zoals eerder opgemerkt, doet een data-URI binnen CSS een resource opzwellen die de eerste paint blokkeert. Hoe groter die stylesheet, hoe langer de pagina blanco blijft.
Decoderen kost meer op mobiel. Een data-URI wordt bij elke keer dat het document laadt opnieuw uit Base64 gedecodeerd, en op zwakkere telefoons stapelt dat CPU-werk zich op. Erger nog, de bytes belanden nooit in de schijfcache van de browser, dus een zware ingebedde afbeelding wordt bij elk bezoek opnieuw gedecodeerd in plaats van één keer gecachet en gedecodeerd zoals een gewoon bestand.
Er is ook een historische reden waarom dit advies is verschoven. Het oorspronkelijke argument voor inlinen, luid verkondigd in het HTTP/1.1-tijdperk, was request-reductie: elke verbinding kon één resource per keer ophalen, dus een pagina met 40 kleine pictogrammen betaalde 40 round trips. HTTP/2 veranderde dat door veel requests te multiplexen over één verbinding, wat extra kleine bestanden goedkoop maakte. De grote opbrengst van inlinen, minder requests, verdampte grotendeels, terwijl de kosten bleven: verloren caching, geen lazy loading, grotere render-blocking-bestanden. Als je oudere artikelen leest die enthousiast zijn over Base64-sprites, weeg ze dan af tegen het protocol dat je site vandaag daadwerkelijk draait.
De Core Web Vitals-hoek
Inlinen snijdt twee kanten op bij LCP (Largest Contentful Paint). Voor een kleine above-the-fold-afbeelding die het LCP-element is, kan het verwijderen van een request de LCP iets vervroegen. Maar plaats een grote afbeelding inline en je doet het tegenovergestelde: je vertraagt het document of de stylesheet waarin hij zit, waardoor de LCP voor de hele pagina opschuift. De groottedrempel bepaalt welke kant het opgaat.
Voor CLS (Cumulative Layout Shift) verandert inlinen niets aan de kernregel: een afbeelding heeft nog steeds expliciete width en height nodig (of een aspect-ratio-box) zodat de browser ruimte kan reserveren voordat hij rendert. Een data-URI zonder afmetingen verschuift de layout precies zoals een externe afbeelding zonder afmetingen.
Een betere hefboom dan inlinen is meestal het verkleinen van de bron. Een afbeelding comprimeren voordat je hem encodeert maakt zowel het bestand als elke resulterende data-URI kleiner. De gids over afbeeldingscompressie in browser vs Node behandelt hoe je dat client-side of in een buildstap doet, en WebP vs AVIF vs JPEG helpt je een formaat te kiezen dat van begin af aan klein is.
Zo plaats je afbeeldingen inline in HTML, CSS, Markdown en JSON
Zodra je een data-URI hebt, zie je hier hoe hij in elke context valt. Dit zijn de vier kant-en-klare snippets die de Image to Base64-converter voor je genereert.
HTML, plak de URI in elke src:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…" alt="logo">
CSS, wikkel hem in url() voor een background-image (dit is het canonieke patroon voor een base64 image in CSS):
.icon {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i…");
}
Markdown, een op zichzelf staande afbeeldingslink voor README’s, GitHub-issues en notebooks waar je geen bestand kunt hosten:

JSON, een ingebedde asset binnen een API- of configuratiepayload:
{ "icon": "data:image/png;base64,iVBORw0KGgo…" }
Alle vier werken overal waar een URL wordt geaccepteerd: img src, CSS-background, mask-image, zelfs een favicon-<link>. Elke moderne browser ondersteunt het data:-schema.
Deze snel genereren
Deze met de hand bouwen is foutgevoelig: één verkeerd MIME-type of een verdwaalde regelafbreking en de afbeelding faalt stil. Sleep je bestand in de Image to Base64-converter en hij produceert alle vier de snippets met hun eigen kopieerknoppen, plus de exacte groottetoename zodat je vooraf weet of de asset überhaupt inline hoort.
SVG: het bijzondere geval waarin Base64 meestal verliest
SVG breekt de gebruikelijke logica, want SVG is tekst, geen binair. Base64 bestaat om binaire data tekstveilig te maken, maar SVG is al XML-tekst. Het als Base64 encoderen blaast alleen een string op die geen encodering nodig had, en maakt hem daarbij onleesbaar. Dus specifiek voor SVG is Base64 vrijwel altijd de verkeerde keuze.
Vergelijk drie manieren om hetzelfde pictogram inline te plaatsen:
/* 1. Base64-data-URI — voegt de 33%-kost toe aan tekst die het niet nodig had */
.a { background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i…"); }
/* 2. URL-gecodeerde data-URI — percent-codeer een handvol tekens, geen 33%-kost */
.b { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'…%3C/svg%3E"); }
/* 3. Inline <svg> rechtstreeks in de HTML — volledig stijlbaar met CSS */
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M12 2 L22 22 H2 Z" fill="currentColor" />
</svg>
Optie 2 (URL-codering) is meestal kleiner dan optie 1, blijft leesbaar voor mensen en comprimeert beter. Je percent-codeert alleen de tekens die de URI zouden breken (<, >, # en aanhalingstekens) en laat de rest leesbaar. De aanpak van de URL-encoder/decoder staat in de tool zelf gedocumenteerd; grijp alleen naar Base64-SVG wanneer een build-pipeline dat specifiek vereist.
Waarom een inline <svg> vaak wint van een Base64-PNG-pictogram
Als je kiest tussen een Base64-gecodeerd PNG-pictogram en een inline <svg>, dan wint de SVG meestal op elk vlak. Hij schaalt naar elke grootte zonder vervaging en draagt geen 33%-kost, en anders dan welke data-URI dan ook kun je hem met CSS stijlen, animeren en met currentColor herkleuren. Een Base64-PNG is een blob met vaste resolutie waar je niet meer aan kunt komen zodra hij geëncodeerd is. Reserveer raster-Base64 voor gevallen waarin je echt een foto of een raster-screenshot inline nodig hebt.
De andere kant op decoderen: Base64 terug naar een afbeelding
Het omgekeerde probleem komt net zo vaak voor: je hebt een Base64-string (uit een API-respons, een logregel, een databasekolom of een stylesheet die je aan het debuggen bent) en je moet de daadwerkelijke plaat zien.
Twee details laten mensen struikelen. Ten eerste, ruwe Base64 versus een volledige data-URI. Een complete data-URI (data:image/png;base64,…) draagt zijn eigen MIME-type; een kale payload (iVBORw0KGgo…) niet. Om een kale payload te renderen zet je er ofwel een correct data:-voorvoegsel voor, of je laat een tool het formaat afleiden uit de leidende bytes: iVBORw0KGgo betekent PNG, /9j/ betekent JPEG, R0lGOD betekent GIF.
Ten tweede, regelafbreking. Base64 uit e-mail of oudere tooling is vaak afgebroken op 76 tekens per RFC 2045. Die newlines moeten voor het decoderen worden weggehaald, anders is de string ongeldig in een HTML-attribuut of url().
In de browser kun je een complete data-URI rechtstreeks aan een <img> geven:
<img src="data:image/png;base64,iVBORw0KGgo…" alt="decoded">
Op de server reconstrueert Node het bestand uit de payload:
import { writeFileSync } from "node:fs";
const b64 = "iVBORw0KGgoAAAANSUhEUgAA…"; // ruwe payload, geen data:-voorvoegsel
writeFileSync("output.png", Buffer.from(b64, "base64"));
Wil je een no-code-route, dan gebruik je de Base64 to Image-converter: plak een string (met of zonder het voorvoegsel, regelafbrekingen en al), bekijk een preview, lees de afmetingen en het MIME-type, en download een echte PNG, JPG, GIF of SVG. Hij haalt witruimte weg, tolereert een ontbrekend voorvoegsel en detecteert het formaat automatisch uit de magic bytes.
Eén controle die de moeite waard is bij een gedecodeerde afbeelding: kijk naar de gerapporteerde afmetingen. Als je één string uit een bestand met meerdere hebt getrokken en het resultaat is 1×1, dan heb je waarschijnlijk een tracking pixel te pakken in plaats van de asset die je wilde. En onthoud dat decoderen puur mechanisch en verliesvrij is: een Base64-PNG komt terug als precies dezelfde PNG, byte voor byte, zonder hercompressie. Het enige wat onderweg veranderde, was de container: een tekststring op de heenweg, een binair bestand op de terugweg.
FAQ
Moet ik mijn afbeeldingen naar Base64 omzetten?
Alleen wanneer het de moeite waard is: kleine (onder ~2 KB), zelden veranderende pictogrammen of logo’s waar het besparen van één HTTP-request ertoe doet, plus HTML-e-mail, op zichzelf staande widgets en JSON-payloads. Grote afbeeldingen of alles wat over pagina’s wordt hergebruikt, moet vrijwel altijd een gewoon bestand blijven, zodat je caching en lazy loading behoudt.
Hoeveel groter maakt Base64 een afbeelding?
Ongeveer 33% groter. Base64 codeert elke 3 byte binair als 4 ASCII-tekens, plus een beetje padding en het data:-voorvoegsel. Een PNG van 9 KB wordt ruwweg 12 KB tekst. Om een afbeelding naar Base64 om te zetten en de exacte toename voor jouw bestand te zien, rapporteert de tool het precieze getal in zijn metadatabalk.
Laadt Base64 afbeeldingen sneller?
Voor een heel klein above-the-fold-pictogram kan dat, door de round trip van één request te besparen. Voor grotere of hergebruikte afbeeldingen is het meestal langzamer: je verliest onafhankelijke caching, je kunt het niet lazy-loaden, en het inline plaatsen in CSS vergroot een render-blocking resource. Grootte is de doorslaggevende factor.
Kan ik een Base64-afbeelding in CSS gebruiken?
Ja: background-image: url("data:image/png;base64,…"). Het is prima voor kleine pictogrammen. Onthoud alleen dat de data-URI onderdeel wordt van de stylesheet, dus het hele bestand wordt opnieuw gedownload telkens als de CSS verandert, en de afbeelding kan niet apart ervan gecachet worden.
Moet ik SVG of Base64 gebruiken voor pictogrammen?
Geef de voorkeur aan een inline <svg> of een URL-gecodeerde SVG-data-URI. SVG is tekst, schaalt netjes en draagt geen 33%-kost, dus hij is meestal kleiner dan een Base64-PNG en je kunt hem met CSS stijlen. Grijp alleen naar Base64 wanneer je specifiek een rasterpictogram nodig hebt.
Hoe zet ik een Base64-string terug naar een afbeelding?
In de browser sleep je een volledige data:image/…;base64,…-URI in een <img src>. Op een server gebruik je Buffer.from(b64, "base64") om het bestand te schrijven. Een ruwe payload heeft een toegevoegd data:-voorvoegsel nodig, en bij regelafgebroken strings moeten de newlines er eerst af. De Base64 to Image-tool handelt dat allemaal af en laat je het resultaat downloaden.