FlowingDev

Prozent-Encoding erklärt: So entschlüsselst du %20, %3F und andere URL-Hieroglyphen

Erfahre, warum URLs bestimmte Zeichen nicht enthalten dürfen und wie Prozent-Encoding unsichere Zeichen in ein sicheres, universelles Format für das Web übersetzt.

Tool ausprobieren: URL-Kodierer

In einem Satz

URL-Encoding, offiziell Prozent-Encoding genannt, ist der Prozess, bei dem Zeichen, die eine besondere Bedeutung haben oder in einer URL ungültig sind, in ein sicheres, universell verständliches Format übersetzt werden, damit sie ohne Verwirrung übertragen werden können.

Das Problem, das es löst

In der Ursuppe des frühen Webs war das Leben einfach. URLs – oder allgemeiner, URIs (Uniform Resource Identifiers) – wurden als saubere, vorhersagbare Methode entwickelt, um eine Ressource zu lokalisieren. Die Architekten, darunter Sir Tim Berners-Lee, bauten dieses System auf dem Fundament eines begrenzten Zeichensatzes auf: ASCII.

Das funktionierte super, solange man nur auf http://example.com/reports/April.html verweisen musste. Aber was passiert, wenn die Dinge komplizierter werden?

Schau dir die Anatomie einer URL an. Sie hat Teile: ein Schema (http:), einen Host (example.com), einen Pfad (/search) und vielleicht einen Query-String (?q=dogs&cats). Bestimmte Zeichen sind die Regisseure in diesem Theaterstück. Der Doppelpunkt (:) trennt das Schema. Der Schrägstrich (/) trennt Pfadsegmente. Das Fragezeichen (?) leitet die Query-Parameter ein. Das Et-Zeichen (&) trennt einen Parameter vom nächsten.

Hier fängt der Ärger an. Was ist, wenn du nach dem genauen String "C++ & C#" suchen willst? Wenn du das einfach in eine URL klatscht, erhältst du .../search?q=C++ & C#. Ein Webserver sieht das und ist hoffnungslos verwirrt. Er denkt, die Anfrage sei für "C++ ", sieht dann ein Et-Zeichen und erwartet ein weiteres Schlüssel-Wert-Paar, bekommt aber nur ein einsames " C#". Chaos. Die beabsichtigte Bedeutung geht verloren.

Darüber hinaus sind einige Zeichen einfach nicht erlaubt. Ein Leerzeichen ist ein klassischer Unruhestifter. Wann ist ein Leerzeichen Teil eines Dateinamens und wann nur ein Tippfehler, den ein Browser ignorieren sollte? Und was ist mit Zeichen außerhalb des einfachen englischen Alphabets? Das Web ist global! Wie packt man Résumé.pdf oder 你好.html in eine URL, die für ASCII konzipiert wurde?

Prozent-Encoding löst diese ganze Klasse von Problemen. Es bietet eine Notluke, eine Möglichkeit zu sagen: „Hey, Herr Webserver, das/die nächste(n) Zeichen ist/sind nicht strukturell. Interpretiere sie nicht. Das sind reine Daten.“ Es ist der Universalübersetzer, der sicherstellt, dass eine URL in einem Browser in Brasilien dasselbe bedeutet wie auf einem Server in Berlin.

Wie es unter der Haube funktioniert

Die „Magie“ hinter dem Prozent-Encoding ist überraschend einfach. Es ist weniger ein Zaubertrick als vielmehr eine simple Substitutionschiffre, auf deren Verwendung sich alle geeinigt haben.

Die Besetzung: Reservierte vs. nicht reservierte Zeichen

Zuerst musst du wissen, welche Zeichen cool sind und welche problematisch. Sie fallen in ein paar Gruppen.

Zeichentyp Zeichen Wann encoden?
Nicht reserviert A-Z a-z 0-9 - _ . ~ Niemals. Das sind die VIPs der URL-Welt. Sie sind immer sicher.
Reserviert : / ? # [ ] @ ! $ & ' ( ) * + , ; = Manchmal. Diese haben eine besondere strukturelle Bedeutung. Wenn du sie für ihre Bedeutung verwenden willst (wie / in einem Pfad), encodest du sie nicht. Wenn du sie als reine Daten verwenden willst (wie ein & in einer Suchanfrage), musst du sie encoden.
Andere (Unsicher) (Leerzeichen), `< > " % { } \ ^` und alle Nicht-ASCII-Zeichen

Das Wichtigste ist der Kontext. Das Zeichen ? ist in Ordnung, wenn es das eine ? ist, das den Pfad vom Query-String trennt. Aber wenn du ein buchstäbliches Fragezeichen innerhalb des Wertes eines Query-Parameters benötigst, musst du es encoden.

Der Zaubertrick: Prozent + Hex

Der Encoding-Prozess ist ein einfacher Tanz in drei Schritten:

  1. Wähle ein Zeichen, das du encoden musst. Nehmen wir das Et-Zeichen &.
  2. Finde seinen Bytewert unter Verwendung eines Standardzeichensatzes. Für das Web ist dieser Standard UTF-8. In UTF-8 (und seinem Vorgänger ASCII) wird das Zeichen & durch die Dezimalzahl 38 dargestellt.
  3. Wandle diese Zahl in eine zweistellige Hexadezimalzahl um und stelle ein Prozentzeichen (%) voran. Dezimal 38 ist 26 in Hexadezimal.

Also wird aus & ein %26.

Probieren wir noch ein paar aus:

  • Ein Leerzeichen ist dezimal 32, was hex 20 ist. Encodet: %20.
  • Ein Fragezeichen (?) ist dezimal 63, was hex 3F ist. Encodet: %3F.
  • Das Prozentzeichen (%) selbst ist dezimal 37, hex 25. Um also ein buchstäbliches % zu encoden, schreibst du %25.

Dieses System ist genial, weil das Prozentzeichen selbst kein nicht reserviertes Zeichen ist. Ein Parser weiß also, dass er, wann immer er ein % sieht, zwei nachfolgende Hex-Ziffern erwarten sollte.

Was ist mit nicht-englischen Zeichen?

Hier wird UTF-8 entscheidend. Ein einfaches ASCII-Zeichen wie A ist ein Byte groß. Aber ein Zeichen wie das französische é oder das chinesische 好 wird in UTF-8 durch mehrere Bytes dargestellt. Der Encoding-Prozess ist derselbe, nur für jedes Byte wiederholt.

Nehmen wir é:

  1. In UTF-8 wird é durch zwei Bytes dargestellt: C3 und A9 (in Hex).
  2. Encode jedes Byte einzeln:
    • C3 wird zu %C3.
    • A9 wird zu %A9.
  3. Kombiniere sie: é wird zu %C3%A9.

Der Decodier-Prozess ist genau umgekehrt. Ein Browser oder Server sieht %C3%A9, schnappt sich die beiden Bytes C3 und A9, jagt sie durch einen UTF-8-Decoder und erhält das wunderschöne é-Zeichen zurück.

Geschichten aus der echten Welt

Theorie ist super, aber schauen wir mal, wo es zur Sache geht.

Der Fall der verschwindenden Suchanfrage

Eine Junior-Entwicklerin, Maya, baute eine Suchfunktion für eine technische Dokumentationsseite. Benutzer konnten nach Dingen wie "C++", "promises & async/await" und so weiter suchen. Sie baute die Such-URL, indem sie einfach Strings verknüpfte: site.com/search?q= + userInput.

Die Dinge liefen aus dem Ruder. Eine Suche nach promises & async/await erzeugte die URL .../search?q=promises & async/await. Der Server meldete jedoch nur den Suchbegriff "promises ". Das & wurde als Trennzeichen für einen neuen Parameter, async/await, interpretiert, der verworfen wurde, da er keinen Schlüssel hatte. Ihre Suchergebnisse waren komplett falsch.

Die Lektion: Maya lernte eine goldene Regel der Webentwicklung: immer alle dynamischen Daten, die in einen URL-Bestandteil eingefügt werden, prozent-encoden. Nachdem sie anfing, die Benutzereingaben zu encoden, wurde die URL korrekterweise zu .../search?q=promises%20%26%20async%2Fawait. Der Server erhielt nun den vollständigen, korrekten String und die Suche funktionierte perfekt.

Der internationale Zwischenfall

Ein Online-Shop beschloss, ein neues Produkt eines deutschen Partners vorzustellen: den „Fußball“. Das Marketingteam erstellte dafür eine sprechende URL: store.com/products/Fußball. In ihren modernen Browsern im Büro sah alles gut aus.

Aber der Launch-Tag war ein Chaos. Die Support-Tickets fluteten nur so herein. Einige Benutzer erhielten „404 Not Found“-Fehler. Andere sahen eine URL, die wie .../products/Fu%C3%9Fball in ihrer Browserleiste aussah, während wieder andere .../products/FuÃball sahen. Das System war ein Flickenteppich aus alten und neuen Komponenten, und sie behandelten das Nicht-ASCII-Zeichen ß (Eszett) nicht konsistent. Einige Teile encodeten es nicht, andere encodeten es unter Annahme von UTF-8, und einige Altsysteme decodierten es unter Annahme eines anderen Zeichensatzes, was zu Zeichensalat (Mojibake) führte.

Die Lektion: Sich darauf zu verlassen, dass Browser und Server Nicht-ASCII-Zeichen in URLs „einfach so handhaben“, ist ein Rezept für Inkonsistenzen. Proaktives und konsistentes Prozent-Encoding aller nicht-reservierten Zeichen nach dem UTF-8-Standard stellt sicher, dass deine URLs robust sind und im gesamten Web-Ökosystem, alt und neu, vorhersagbar funktionieren.

Das Doppel-Encoding-Debakel

Ein Team baute ein Single-Sign-On-System (SSO). Der Ablauf funktionierte so: service-a.com leitete den Benutzer zu sso.com/login weiter und übergab seine eigene URL als Parameter, damit der Benutzer nach dem Einloggen zurückgeschickt werden konnte. Die Weiterleitungs-URL sah so aus: sso.com/login?redirect_uri=https://service-a.com/dashboard?param=1.

Der Entwickler bei service-a.com war schlau und hat den redirect_uri-Wert encodet, was zu Folgendem führte: sso.com/login?redirect_uri=https%3A%2F%2Fservice-a.com%2Fdashboard%3Fparam%3D1.

Das von ihnen verwendete Web-Framework hatte jedoch eine Middleware-Schicht, die „aus Sicherheitsgründen“ automatisch alle ausgehenden Query-Parameter URL-encodete. Sie sah den bereits encodeten String und encodete ihn noch einmal. Das % in %3A wurde zu %25, also wurde %3A zu %253A. Die endgültige URL war ein verstümmeltes Chaos aus Doppel-Encoding. Als der Benutzer auf sso.com landete, decodierte es die URL einmal und erhielt den einfach-encodeten String, den es nicht als Weiterleitung verwenden konnte, was den Login-Vorgang komplett lahmlegte.

Die Lektion: Sei dir deiner gesamten Toolchain bewusst. Encode Daten am Punkt ihrer Erstellung und stelle sicher, dass kein anderes System in der Kette sie erneut encodet. Doppel-Encoding ist ein häufiger Fehler, der einen zum Kopfkratzen bringt und eine gültige URL in nutzlosen Müll verwandelt.

Häufige Fehler und Fallstricke

  • Die gesamte URL encoden. Tu das niemals. Wenn du https://example.com prozent-encodest, bekommst du so etwas wie https%3A%2F%2Fexample.com. Das ist keine gültige URL mehr; der Scheme- und Authority-Teil sind jetzt nur noch ein sinnloses Durcheinander von Zeichen. Du darfst nur die einzelnen Komponenten encoden, die es benötigen (wie Werte von Query-Parametern oder bestimmte Pfadsegmente).
  • Gar nicht encoden. Die häufigste Sünde. Rohe Benutzereingaben oder Daten mit Sonderzeichen direkt in einen URL-String zu stopfen, ist eine Einladung für Sicherheitslücken (wie Cross-Site Scripting) und kaputte Funktionalität.
  • Den Kontext vergessen. Das &-Zeichen ist im Pfad einer URL in Ordnung, aber im Query-String ist es ein reserviertes Trennzeichen. Dasselbe gilt für /. Du musst reservierte Zeichen nicht encoden, wenn sie für ihren speziellen Zweck verwendet werden.
  • Verwechslung von + mit %20. Im application/x-www-form-urlencoded Content-Type (der von HTML-Formularen verwendet wird) werden Leerzeichen im Query-String oft als +-Zeichen encodet. Obwohl viele Server das verstehen, ist das offizielle Prozent-Encoding für ein Leerzeichen %20. Die Verwendung von %20 ist eindeutig und funktioniert in allen Teilen einer URL korrekt, nicht nur im Query-String. Im Zweifelsfall bleib bei %20.
  • Einen veralteten Zeichensatz verwenden. Das Web läuft auf UTF-8. Wenn du deine Daten mit einem anderen Zeichensatz (wie ISO-8859-1) encodest, wird ein Server, der UTF-8 erwartet, die Bytes falsch interpretieren und deine Daten verstümmeln. Gib immer UTF-8 an und verwende es.

Warum du es auf dem Schirm haben solltest

Wenn du Code schreibst, der mit URLs zu tun hat, musst du Prozent-Encoding verstehen. Das ist nicht optional. Du solltest darüber nachdenken, wann immer du:

  • eine URL aus Variablen oder Benutzereingaben zusammenbaust.
  • eine API-Anfrage mit Parametern in der URL machst.
  • internationale Zeichen in Dateinamen, Benutzerprofilen oder Inhalten verarbeitest, die in einer URL erscheinen könnten.
  • eine URL auf der Serverseite parst, um Daten zu extrahieren.
  • Weiterleitungen schreibst oder URLs als Parameter an andere Dienste übergibst.

Kurz gesagt, Prozent-Encoding ist ein fundamentaler Teil der Web-Infrastruktur. Es zu ignorieren führt zu fehlerhafter, unsicherer und unzuverlässiger Software. Zu wissen, wie es funktioniert, ist ein Zeichen für einen professionellen Webentwickler.

Geh tiefer

  • RFC 3986: Die kanonische Spezifikation für Uniform Resource Identifier (URI). Abschnitt 2 definiert den Zeichensatz und die Regeln für das Prozent-Encoding. Es ist die ultimative Quelle der Wahrheit.
  • MDN Web Docs: encodeURIComponent(): Ein praktischer Leitfaden für JavaScript-Entwickler, der erklärt, welche Funktion man warum verwenden sollte. Der Abschnitt „Siehe auch“ verlinkt auf andere verwandte Encoding-Funktionen.
  • Wikipedia: Prozent-Kodierung: Ein umfassender und sehr gut lesbarer Überblick über das Konzept, seine Geschichte und seine verschiedenen Nuancen.
  • W3C: Character encodings: Eine übergeordnete Einführung, warum Zeichenkodierungen im Web wichtig sind, mit UTF-8 als Held der Geschichte.

Theorie erledigt. Zeit, loszulegen — 100 % in deinem Browser.

Tool ausprobieren: URL-Kodierer