Een HTML-entiteit is een manier om een teken te schrijven zodat de browser het als tekst toont in plaats van als markup. Typ een kale < in je content en de browser begint een tag te lezen; schrijf je in plaats daarvan <, dan verschijnt er gewoon een letterlijke < op de pagina. Die omwisseling is het hele idee achter HTML-entiteiten encoderen.
Vijf tekens hebben een speciale betekenis in HTML en zijn degene die je het vaakst escapet: <, >, &, " en '. Je escapet ze om twee redenen. De eerste is weergave: je wilt code of markup als tekst tonen. De tweede, en belangrijkere, is veiligheid: het escapen van onvertrouwde invoer is de basis om cross-site scripting (XSS) tegen te houden.
Er zijn drie onderling uitwisselbare manieren om elke entiteit te schrijven, namelijk benoemd (<), decimaal (<) en hexadecimaal (<), en ze verwijzen allemaal naar hetzelfde teken. De lastigere vraag is wanneer je moet escapen en waarmee, want het juiste antwoord hangt af van waar de waarde terechtkomt: HTML-tekst, een attribuut, een script of een URL. Hieronder komen de notaties aan bod, de gereserveerde set, een beslismatrix per context en de valkuilen waar mensen het vaakst in trappen.
Wat is een HTML-entiteit? (anatomie)
Een HTML-entiteit, ook wel een tekenverwijzing genoemd, is een korte code die voor één enkel teken staat. Elke entiteit begint met een ampersand & en eindigt met een puntkomma ;. Wat daartussen staat bepaalt welk teken je krijgt.
Er zijn drie vormen:
&name;— een benoemde verwijzing, zoals<of©.&#decimal;— een decimale numerieke verwijzing, zoals<.&#xhex;— een hexadecimale numerieke verwijzing, zoals<.
De browser leest de verwijzing, zoekt het teken op waar ze naar wijst en geeft dat ene teken weer. Aan het zichtbare resultaat verandert niets: < en een kale < zien er identiek uit. Het enige verschil is dat de entiteit als tekst wordt behandeld, nooit als het begin van een tag.
De drie notaties: benoemd, decimaal, hexadecimaal
Alle drie de notaties verwijzen naar hetzelfde Unicode-codepunt; ze verschillen alleen in spelling. Een benoemde entiteit is de leesbare vorm, maar bestaat alleen voor tekens met een gedefinieerde naam. Een decimale entiteit schrijft het codepunt in grondtal 10. Een hexadecimale entiteit schrijft hetzelfde codepunt in grondtal 16, wat één op één overeenkomt met de U+XXXX-notatie die je in de Unicode-standaard ziet.
| Teken | Benoemd | Decimaal | Hex |
|---|---|---|---|
< | < | < | < |
& | & | & | & |
© | © | © | © |
é | é | é | é |
Omdat hex U+XXXX rechtstreeks weerspiegelt (é is U+00E9, dus é), grijpen veel ontwikkelaars ernaar wanneer ze een specifiek codepunt documenteren of erover redeneren. Voor alledaagse markup lezen benoemde entiteiten het prettigst.
De vijf gereserveerde tekens die je moet escapen
Dit zijn de speciale HTML-tekens die veranderen hoe de browser een document parseert. Verschijnt er één in content die getoond moet worden in plaats van uitgevoerd, dan escape je hem.
| Teken | Benoemd | Decimaal | Hex | Wat er breekt als je het niet escapet |
|---|---|---|---|---|
< | < | < | < | Begint een tag; de browser leest de tekst erna als markup |
> | > | > | > | Sluit een tag voortijdig af |
& | & | & | & | Begint een entiteit; de rest kan als verwijzing worden gelezen |
" | " | " | " | Beëindigt een dubbel aangehaalde attribuutwaarde te vroeg |
' | ' | ' | ' | Beëindigt een enkel aangehaalde attribuutwaarde te vroeg |
De HTML-ampersand-entiteit is de wortel van het hele systeem. Het teken & begint elke entiteit, dus het moet als eerste worden geëscaped. Escape je de punthaken vóór de ampersand, dan escape je de & opnieuw in de entiteiten die je net hebt gemaakt. Meer over die valkuil hieronder.
Wanneer moet je eigenlijk escapen? (contextbewust)
Hier zitten de meeste bugs en de meeste kwetsbaarheden. De regel zelf is kort: escape op het moment van uitvoer, afgestemd op de context waar de waarde terechtkomt. Een waarde die op de ene plek veilig is, is op een andere plek gevaarlijk, dus de codering die je toepast moet bij de bestemming passen.
HTML-elementinhoud
Wanneer je een waarde tussen tags zet, binnen een <p>, een <div> of een <td>, escape je <, > en &. De aanhalingstekens hier escapen is onschadelijk maar overbodig. Wil je de tekst <strong> als letterlijke tekens tonen in plaats van het volgende woord vet te maken, codeer hem dan naar <strong> en de browser drukt de tag af in plaats van hem toe te passen.
HTML-attribuutwaarden
Binnen een attribuut worden de aanhalingstekens cruciaal. Staat een waarde in title="…" en bevat ze een niet-geëscapede ", dan beëindigt die de attribuutwaarde te vroeg en kan een aanvaller nieuwe attributen toevoegen. Dat is een klassieke XSS-vector. Escape " (en bij voorkeur ook ') in attribuutcontext. Een waarde als He said "hi" moet He said "hi" worden om ingesloten te blijven.
Binnen <script> of inline JavaScript
HTML-entiteiten helpen hier niet. Een string die in een <script>-blok of een inline event handler wordt opgebouwd, heeft JavaScript- of JSON-string-escaping nodig, geen tekenverwijzingen. " schrijven in een JS-stringliteraal levert die zes letterlijke tekens op, geen aanhalingsteken. Gebruik voor deze context de JSON escapen-tool, en lees de volledige gids over JSON-string-escaping voor de \uXXXX-regels die binnen een script daadwerkelijk gelden.
Binnen een URL
Een URL heeft zijn eigen escape-schema: percent-encoding. HTML-entiteiten maken een waarde niet URL-veilig. De string a&b c hoort in een query als a%26b%20c, niet als a&b c: de spatie breekt de URL nog steeds, en de & scheidt nog steeds parameters. Gebruik hiervoor de URL Decoder & Encoder, en de gids voor URL-encoding en -decoding voor de volledige regels over gereserveerde versus niet-gereserveerde tekens.
De beslismatrix
| Context | Escape met | Voorbeeld | Verkeerde keuze die faalt |
|---|---|---|---|
| HTML-elementinhoud | HTML-entiteiten (< > &) | <strong> → <strong> | Een kale < injecteert een tag |
| HTML-attribuutwaarde | HTML-entiteiten (" ' cruciaal) | "hi" → "hi" | Een niet-geëscapede " breekt eruit |
<script> / inline JS | JS- / JSON-string-escaping | " → \" | HTML-entiteiten zijn inert in JS |
| URL / querystring | Percent-encoding | spatie → %20 | & en entiteiten breken de URL alsnog |
Benoemd versus numeriek: welke gebruik je?
Benoemde entiteiten zijn leesbaar en de juiste standaard voor de gangbare gereserveerde tekens en bekende symbolen, zoals <, &, © en —. Ze bestaan echter alleen voor tekens met een gedefinieerde naam. Numerieke entiteiten, decimaal of hex, kunnen elk codepunt coderen, ook die zonder naam, en vormen daarmee de universele terugvaloptie. Kun je niet garanderen dat het ontvangende systeem een bepaalde benoemde entiteit ondersteunt, dan is numeriek de veilige keuze.
Waarom de apostrof ' is en niet '
De benoemde entiteit ' werd pas in HTML5 en XML geïntroduceerd. In HTML4 is ze ongedefinieerd, dus een handvol oudere parsers en e-mailclients geeft ze weer als de letterlijke tekst ' in plaats van als een apostrof. De numerieke verwijzing ', en haar decimale tweelingbroer ', wijst naar precies hetzelfde teken, U+0027, en wordt begrepen door elke conforme parser die ooit is geschreven. Goed geteste escape-bibliotheken zoals he geven om precies deze reden ' uit voor het enkele aanhalingsteken, en een goede encoder volgt die conventie zodat de uitvoer veilig in elke HTML-, XML- of attribuutcontext kan worden gezet.
Tekenset versus entiteiten: wanneer codeer je niet-ASCII?
Een tekenset, zoals UTF-8, bepaalt hoe tekens als bytes worden opgeslagen. Een entiteit is een manier om een teken te spellen met alleen kale ASCII (&, #, ;, letters, cijfers). Dit zijn verschillende lagen, en ze door elkaar halen leidt tot onnodig coderen.
Op een UTF-8-pagina (zo’n beetje elke moderne pagina die <meta charset="utf-8"> declareert) zijn letters met accenten, streepjes en emoji geldige kale tekens. Laat é, — en 😀 precies zoals ze zijn. Alles in entiteiten coderen doet er alleen toe wanneer de tekst een verouderde single-byte-tekenset of een systeem dat kale UTF-8 verminkt moet overleven; een modus “alle niet-ASCII coderen” bestaat voor die gevallen. Weet je niet zeker hoe bytes, codepunten en tekens zich tot elkaar verhouden, dan zet de gids voor UTF-8-, UTF-16- en Unicode-encoding het model uiteen.
Veelvoorkomende valkuilen bij HTML-entiteiten
& als laatste escapen veroorzaakt dubbel escapen
Volgorde doet ertoe. Vervang je < en > vóór &, dan krijgen de entiteiten die je net hebt gemaakt (<, >) hun leidende & ook geëscaped, dus < wordt uiteindelijk &lt; en verschijnt als de letterlijke tekst <. Escape altijd & eerst, dan de rest. Deze ene regel voorkomt de meest voorkomende encodingbug die er is.
Reeds geëscapede tekst dubbel coderen
Tekst die al geëscaped is opnieuw door een encoder halen, codeert ze nog eens. & wordt &amp;, en de bezoeker ziet & op de pagina in plaats van &. Escape precies één keer, op het moment van uitvoer. Passeert een waarde meerdere lagen, zorg dan dat slechts één daarvan escapet.
Mojibake bij het decoderen
De andere richting op heeft zijn eigen valstrik. Decodeer met de verkeerde tekenset, of decodeer twee keer, en je krijgt verminkte uitvoer: de klassieke mojibake. Toont een pagina letterlijk &lt; waar je < verwachtte, plak het dan in de HTML-entiteiten decoderen-tool om precies te zien waar de entiteiten naar verwijzen; ze verwerkt benoemde, decimale en hex-verwijzingen, en zelfs verouderde niet-afgesloten verwijzingen zoals © zonder afsluitende puntkomma.
Escapen vertrouwen als complete remedie tegen XSS
Escapen is de eerste verdedigingslinie, niet de enige. Omdat HTML meerdere contexten met verschillende regels kent, laat escapen voor de verkeerde een gat open: aanhalingstekens in attributen, JS-escaping in een script, percent-encoding in URL’s. Combineer correct, contextbewust escapen met een Content Security Policy en de automatische escaping van je framework. Zie entiteiten encoderen als de basis, met CSP en framework-standaarden daarbovenop.
Zo encodeer en decodeer je entiteiten in de praktijk
Wanneer je HTML met de hand opbouwt, escape je hem zelf. Hier is een correcte escapeHtml() die de &-eerst-volgorde afhandelt, plus de betere aanpak voor echte applicatiecode.
// The five reserved characters and their safe entities:
// < → < > → > & → & " → " ' → '
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
De zelfgeschreven functie is nuttig om te begrijpen wat er gebeurt en voor eenmalige conversies, maar geef in productie de voorkeur aan het ingebouwde pad. element.textContent instellen laat de browser voor je escapen, en moderne frameworks escapen geïnterpoleerde waarden automatisch. Bewaar handmatig escapen voor de gevallen die het platform niet dekt.
Voor losse klussen escapet de HTML-entiteiten encoderen-tool de gereserveerde set (benoemd, decimaal of hex), en de HTML-entiteiten decoderen-tool draait dat terug. De twee zijn exacte tegenpolen voor de gereserveerde tekens, dus je kunt tekst zonder verlies door beide heen-en-weer halen.
Veelgestelde vragen
Wat is een HTML-entiteit?
Een HTML-entiteit is een korte code die begint met & en eindigt met ; en die één enkel teken voorstelt. De browser geeft het teken weer waar de entiteit naar wijst in plaats van het als markup te behandelen. Zo toont < een letterlijke < en toont & een letterlijke &.
Welke tekens moet ik escapen in HTML?
De vijf gereserveerde speciale HTML-tekens: <, >, &, " en '. In elementinhoud heb je vooral <, > en & nodig; in attribuutwaarden worden de aanhalingstekens " en ' ook cruciaal. Escape de ampersand & eerst zodat de andere entiteiten niet dubbel geëscaped worden.
Moet ik benoemde of numerieke (decimale/hex) entiteiten gebruiken?
Gebruik benoemde entiteiten (<, ©) voor leesbaarheid bij de gangbare tekens, want die zijn makkelijk te herkennen. Gebruik numerieke entiteiten (decimaal < of hex <) wanneer je een teken zonder gedefinieerde naam moet coderen, of wanneer je niet kunt garanderen dat de ontvanger een bepaalde benoemde entiteit ondersteunt. Beide vormen verwijzen naar hetzelfde codepunt.
Beschermen HTML-entiteiten tegen XSS?
Ze vormen de basis, mits correct toegepast. Het escapen van de vijf gereserveerde tekens voordat je onvertrouwde invoer in HTML-element- of attribuutinhoud zet, houdt tag- en script-injectie tegen. Maar escapen is contextafhankelijk: scriptblokken hebben JavaScript-escaping nodig en URL’s percent-encoding. Combineer correct contextbewust escapen met CSP en automatische escaping van het framework.
Waarom toont mijn pagina &lt; in plaats van <?
Dat is dubbel escapen. De tekst is twee keer gecodeerd, of de & is na de punthaken geëscaped, waardoor de & in < werd omgezet in &. De bezoeker ziet dan < als letterlijke tekst. Escape precies één keer en escape altijd & eerst. De decoder-tool kan bevestigen waar de entiteiten naar verwijzen.
Moet ik tekens als é, — of emoji escapen?
Meestal niet. Op een pagina die <meta charset="utf-8"> declareert, zijn letters met accenten, streepjes en emoji geldige kale tekens die geen codering nodig hebben; laat ze zoals ze zijn. Codeer niet-ASCII alleen wanneer de tekst door een verouderde single-byte-tekenset of een systeem dat kale UTF-8 beschadigt moet passeren.