Warum URLs eine Kodierung benötigen
Eine URL besteht aus Zeichen – und nicht alle Zeichen sind „sicher" für die direkte Verwendung. URLs werden über das Internet durch Systeme übertragen, die bestimmte Zeichen möglicherweise als bedeutungstragende Sonderzeichen interpretieren (wie ? für Query-Strings, & zum Trennen von Parametern oder # für Fragment-Bezeichner). Andere Zeichen sind Nicht-ASCII-Zeichen (wie chinesische oder arabische Buchstaben), und manche Zeichen können durch ältere HTTP-Infrastruktur verstümmelt werden.
URL-Kodierung (offiziell als Percent-Encoding bezeichnet) löst dieses Problem, indem unsichere Zeichen durch ein % gefolgt von der zweistelligen hexadezimalen Darstellung des Bytewerts des Zeichens ersetzt werden.
Ein Leerzeichen (0x20) → %20
Ein At-Zeichen (0x40) → %40
Ein Schrägstrich (0x2F) → %2F
Der RFC-Standard
URL-Kodierung ist in RFC 3986 (Uniform Resource Identifiers) definiert. Laut diesem Standard:
Nicht-reservierte Zeichen — können überall in einer URL ohne Kodierung sicher verwendet werden:
- A–Z, a–z, 0–9
-,_,.,~
Reservierte Zeichen — haben in URIs eine besondere Bedeutung und müssen percent-kodiert werden, wenn sie als Datenwert verwendet werden:
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
Alles andere – einschließlich Leerzeichen, Nicht-ASCII-Zeichen und Zeichen wie ", <, >, {, } – muss percent-kodiert werden.
Percent-Encoding in der Praxis
Ein Leerzeichen kodieren
Das Leerzeichen (U+0020) wird als %20 kodiert. In Query-Strings sieht man auch + anstelle von %20 – dies stammt aus dem HTML-Formular-URL-Kodierungsstandard (application/x-www-form-urlencoded), bei dem Leerzeichen als + kodiert werden. Beide sind unterschiedlich:
%20— RFC 3986 Percent-Encoding (Leerzeichen in Pfaden und Headern)+— HTML-Formular-Kodierung (Leerzeichen in Query-Strings)
Beim Dekodieren solltest du stets wissen, welche Konvention gilt, um Fehler zu vermeiden.
Nicht-ASCII-Zeichen
Nicht-ASCII-Zeichen werden zunächst in UTF-8 kodiert, dann wird jedes Byte percent-kodiert:
Chinesisches Zeichen 中 (U+4E2D)
UTF-8-Bytes: 0xE4 0xB8 0xAD
Percent-kodiert: %E4%B8%AD
Das deutsche Wort Ärger enthält zum Beispiel das Sonderzeichen Ä (U+00C4), das als %C3%84 percent-kodiert wird.
JavaScript-Kodierungsfunktionen
JavaScript stellt mehrere eingebaute Funktionen für URL-Kodierung bereit:
encodeURI()
Kodiert eine vollständige URI — entwickelt, um eine vollständige URL zu kodieren und dabei deren Struktur zu erhalten. Zeichen, die zur URI-Syntax gehören, werden nicht kodiert: ; , / ? : @ & = + $ #.
encodeURI("https://example.com/search?q=hallo welt&lang=deutsch")
// "https://example.com/search?q=hallo%20welt&lang=deutsch"
encodeURIComponent()
Kodiert eine URI-Komponente — entwickelt, um einzelne Werte wie Query-Parameter-Werte zu kodieren. Es kodiert alles außer A–Z a–z 0–9 - _ . ! ~ * ' ( ).
encodeURIComponent("hallo welt & mehr")
// "hallo%20welt%20%26%20mehr"
encodeURIComponent("https://example.com")
// "https%3A%2F%2Fexample.com"
Wann welche Funktion verwenden
| Szenario | Funktion |
|---|---|
| Gesamte URL kodieren | encodeURI() |
| Query-Parameter-Wert kodieren | encodeURIComponent() |
| Pfadsegment kodieren | encodeURIComponent() |
| URL in eine andere URL einbetten | encodeURIComponent() |
Die komplementären Dekodierungsfunktionen
decodeURI(encodedURI)
decodeURIComponent(encodedComponent)
Verwende niemals die veralteten Funktionen escape() und unescape() — sie behandeln Nicht-ASCII-Zeichen anders und erzeugen falsche Ergebnisse.
Häufige Fallstricke und Stolpersteine
Doppelte Kodierung
Ein häufiger Fehler ist die Kodierung einer Zeichenkette, die bereits kodiert ist:
encodeURIComponent(encodeURIComponent("hallo welt"))
// "hallo%2520welt"
// %25 ist die Kodierung von %, also wurde %20 zu %2520
Prüfe immer, ob der Wert bereits kodiert ist, bevor du ihn kodierst.
Die + vs. %20-Falle
Wenn du einen Query-String, der + für Leerzeichen verwendet, mit decodeURIComponent dekodierst, wird + nicht als Leerzeichen dekodiert — du musst + zuerst durch %20 ersetzen oder die URLSearchParams-API verwenden:
new URLSearchParams("q=hallo+welt").get("q")
// "hallo welt" ✓
decodeURIComponent("hallo+welt")
// "hallo+welt" ✗ — hat noch ein wörtliches Pluszeichen
Fragment-Bezeichner
Das #-Zeichen in URLs markiert den Beginn eines Fragment-Bezeichners (für seiteninterneAnker). Wenn du ein # in Daten hast, muss es als %23 kodiert werden, sonst behandelt der Browser alles danach als Fragment.
Internationalisierte Domainnamen (IDN)
Domainnamen mit Nicht-ASCII-Zeichen (wie bücher.de) verwenden Punycode-Kodierung, nicht Percent-Encoding. Browser konvertieren IDNs intern in Punycode: bücher.de → xn--bcher-kva.de.
URL-Struktur-Referenz
Eine URL hat folgende Komponenten (gemäß RFC 3986):
scheme://userinfo@host:port/path?query#fragment
| Komponente | Beispiel | Kodierungsregeln |
|---|---|---|
| Scheme | https | Buchstaben, Ziffern, +, -, . |
| Host | example.com | Domain-Labels + Punkte |
| Port | 8080 | Nur Ziffern |
| Path | /search/results | Mit %XX kodiert, außer nicht-reservierte + :@!$&'()*+,;= |
| Query | q=hallo+welt | + für Leerzeichen in Formulardaten, %20 allgemein |
| Fragment | #section-2 | Wird nicht an Server gesendet; nur Browser |
Serverseitige Überlegungen
URL-Normalisierung
Server sollten URLs vor der Verarbeitung normalisieren — z. B. %41 (das zu A dekodiert) genauso behandeln wie A. Allerdings haben manche Zeichen im kodierten vs. unkodierten Zustand unterschiedliche Bedeutungen: / vs. %2F in Pfaden — viele Webserver behandeln diese aus Sicherheitsgründen unterschiedlich (Schutz vor Path-Traversal).
SQL-Injection über URL-Parameter
Bereinige und validiere URL-Parameter stets, bevor du sie in Datenbankabfragen verwendest, auch nach der URL-Dekodierung. URL-Kodierung ist keine Sicherheitsgrenze.
Werkzeuge und APIs
Die URL-API des Browsers
Moderne Browser und Node.js stellen die URL-API für die strukturierte Arbeit mit URLs bereit:
const url = new URL("https://example.com/search?q=hallo welt&page=1");
console.log(url.searchParams.get("q")); // "hallo welt" (automatisch dekodiert)
url.searchParams.set("q", "neuer wert & special");
console.log(url.href);
// https://example.com/search?q=neuer+wert+%26+special&page=1
Die URL-API verarbeitet Kodierung/Dekodierung transparent, was generell der bevorzugte Ansatz gegenüber manuellen encodeURIComponent-Aufrufen ist.
Zusammenfassung
URL-Kodierung ist ein grundlegendes Konzept, dem jeder Web-Entwickler täglich begegnet, oft ohne es zu bemerken. Die wichtigsten Punkte zum Merken:
- Percent-Encoding (
%XX) ist der Standardmechanismus zur Kodierung unsicherer Zeichen in URIs. - Verwende
encodeURIComponent()für einzelne Werte undencodeURI()für vollständige URLs. - Achte auf den Unterschied zwischen
+und%20in Query-Strings. - Vermeide doppelte Kodierung — prüfe, ob eine Zeichenkette bereits kodiert ist, bevor du sie kodierst.
- Bevorzuge die modernen APIs
URLundURLSearchParamsfür die programmatische Arbeit mit URLs.