URL-Encoding ersetzt ein Zeichen durch ein Prozentzeichen und zwei Hexadezimalziffern: Ein Leerzeichen wird zu %20, ein Ampersand wird zu %26, ein Fragezeichen wird zu %3F. Der Zweck ist, zu verhindern, dass ein Zeichen als URL-Syntax gelesen wird, wenn Sie es als Daten meinten. Nicht mehr.
Der Grund, warum es schwerer wirkt, ist, dass fast jede Frage dazu eigentlich eine Frage nach dem Geltungsbereich ist. Welche Zeichen, in welchem Teil der URL, maskiert von welcher Schicht? Den Geltungsbereich falsch einschätzen, und Sie bekommen einen von zwei klassischen Fehlern: einen Tracking-Parameter, der lautlos abgeschnitten wird, oder ein Ziel, das als https%3A%2F%2Fexample.com ankommt und einen 404 auslöst. Dieser Beitrag behandelt die zwei Zeichenmengen, die die Antwort entscheiden, die Stellen, an denen sich die Regeln ändern, und wie man prüft, was ein Link tatsächlich trägt. Für das größere Bild, was ein Redirect mit all dem macht, siehe Arten von Redirects.
Die zwei Mengen, die alles entscheiden
RFC 3986 Abschnitt 2.3 definiert eine unreserved-Menge, die niemals Encoding braucht: Buchstaben, Ziffern und genau vier Satzzeichen - Bindestrich, Punkt, Unterstrich, Tilde. Enthält Ihr Wert nur diese, gibt es nichts zu tun.
Alles andere fällt in eine von zwei Kategorien. Reserved-Zeichen tragen strukturelle Bedeutung: : / ? # [ ] @ trennen die Teile einer URL, und ! $ & ' ( ) * + , ; = trennen Dinge innerhalb dieser Teile. Abschnitt 2.2 listet sie auf. Sie sind als Syntax legal und müssen encodiert werden, wenn sie als Daten auftreten. Der Rest ist alles außerhalb von ASCII, das Byte für Byte encodiert wird, nachdem es in UTF-8 umgewandelt wurde - weshalb ein einzelner Buchstabe mit Akzent meist sechs statt drei Zeichen kostet.
Daraus ergibt sich die einzige Regel, die man sich merken muss: ein Zeichen encodieren, wenn es Daten sind und sonst als Syntax gelesen würde. Ein Ampersand zwischen zwei Parametern ist Syntax. Ein Ampersand innerhalb eines Kampagnennamens ist Daten, und lässt man ihn unangetastet, endet die Parameterliste genau dort.
Den Wert encodieren, nicht die URL
Das ist der Fehler, den ich am häufigsten sehe, und er hat immer dieselbe Form. Jemand hat eine URL, weiß, dass sie Encoding braucht, und fügt das Ganze in einen Encoder ein - und bekommt:
https%3A%2F%2Fexample.com%2Fspring%3Futm_campaign%3Dspring%20sale
Dieser String ist keine URL. Es ist ein URL-förmiges Stück Text, das immer nur ein Wert innerhalb einer anderen URL sein kann - genau dorthin gehört er, wenn man ein Ziel durch einen Redirector schickt, und genau dorthin gehört er nicht, wenn man versucht, ihn zu öffnen.
Die korrekte Behandlung encodiert jeden Wert für sich:
https://example.com/spring?utm_campaign=spring%20sale&utm_source=flyer
Schema, Host, Pfadtrennzeichen sowie ? und & bleiben als Syntax stehen. Nur der Wert hat sich geändert. Jede Sprache liefert zwei Funktionen für diese Unterscheidung, und die falsche zu wählen, ist die andere Hälfte des Problems: MDNs Seite zu encodeURIComponent sagt unumwunden, dass encodeURI reservierte Zeichen bewusst unangetastet lässt, weil es eine ganze URI erwartet, während encodeURIComponent sie maskiert, weil es ein Fragment davon erwartet. Werte wollen encodeURIComponent. In Python ist das urllib.parse.quote, in Go url.QueryEscape, in PHP rawurlencode.
Leerzeichen ist %20, außer wenn es ein Plus ist
Beides ist korrekt, an unterschiedlichen Stellen, und das ist der mit Abstand verwirrendste Punkt an diesem Thema.
In einem Pfad oder einer generischen URI ist ein Leerzeichen %20. In einem Query-String, der so aufgebaut ist wie ein HTML-Formular ihn baut, ist ein Leerzeichen +, weil genau das die application/x-www-form-urlencoded-Serialisierung im WHATWG-URL-Standard vorschreibt. Beide Formen werden von jedem serverseitigen Query-Parser, dem Sie wahrscheinlich begegnen, als Leerzeichen gelesen.
Die Falle liegt in der umgekehrten Richtung. Ist ein Pluszeichen Daten - eine Telefonnummer, ein Suchbegriff, eine Kampagne namens spring+summer - muss es als %2B geschrieben werden. Bleibt es in einem Query-String unangetastet, wird es zu einem Leerzeichen, und Sie verbringen einen Nachmittag damit, sich zu fragen, warum die Nummer in Ihrem CRM ihre Landesvorwahl verloren hat.
| Zeichen | Encodiert | Warum es wichtig ist |
|---|---|---|
| Leerzeichen | %20 oder + | + nur innerhalb eines Query-Strings, %20 überall |
& | %26 | Nicht encodiert, endet die Parameterliste genau dort |
? | %3F | Nicht encodiert, wird alles danach zur Query |
# | %23 | Nicht encodiert, erreicht der Rest den Server gar nicht erst |
+ | %2B | Nicht encodiert in einer Query, kommt es als Leerzeichen an |
% | %25 | Nicht encodiert, werden die nächsten zwei Zeichen verschluckt |
Die #-Zeile verdient eine Anmerkung, denn sie ist die, die den verwirrendsten Bug-Report produziert. Ein Fragment wird nie an den Server gesendet. Ein unencodiertes # in ein Redirect-Ziel setzen, und der Server sieht eine abgeschnittene URL, während die Adressleiste des Browsers immer noch richtig aussieht, sodass die Person, die es meldet, schwört, der Link sei in Ordnung.
Wenn Sie Kampagnen-URLs öfter als gelegentlich von Hand bauen, hören Sie damit auf: Unser UTM-Builder encodiert jeden Wert während der Eingabe, und UTM-Namenskonventionen behandelt, wie man Werte wählt, die von vornherein kein Encoding brauchen. Das Ergebnis auf der eigenen Domain kürzen, und das encodierte Chaos ist nichts mehr, das sich jemand ansehen muss.
Double Encoding und wie man es erkennt
Double Encoding ist, was passiert, wenn ein Wert zwei Schichten durchläuft, die beide ihre Aufgabe erfüllen. Das Prozentzeichen selbst ist ein Zeichen, das maskiert werden muss, sodass %20 zu %2520 wird und %2520 zu %252520.
Die Symptome sind erkennbar, sobald man sie einmal gesehen hat. Ein Seitentitel, der einem echten Besucher spring%20sale anzeigt. Ein Parameter, der mit sichtbaren Escape-Sequenzen in der Analytics ankommt. Ein Redirect, der beim ersten Hop funktioniert und beim zweiten fehlschlägt. Die Ursache ist fast immer ein Encode-Aufruf, der um einen Wert gelegt wird, der schon encodiert ankam, oft weil er aus einer Datenbank kam, die die encodierte Form gespeichert hat.
Die Lösung ist, festzulegen, welche Schicht das Encoding besitzt, und die anderen komplett davon fernzuhalten. Einmal decodieren, wenn Sie einen Wert lesen, einmal encodieren, wenn Sie ihn in eine URL schreiben, und nie beides in derselben Funktion tun.
Wo das in der Praxis zuschlägt
Drei Stellen, in der Reihenfolge, in der Sie ihnen wahrscheinlich begegnen.
Tracking-Parameter. Ein Kampagnenwert mit einem unencodierten Ampersand schneidet die Parameterliste ab, sodass die Session als Direktzugriff in Ihrer Analytics landet und die Kampagne kein Credit bekommt. Es gibt keine Fehlermeldung. UTM-Parameter erscheinen nicht in GA4 behandelt die Diagnose von der Reporting-Seite aus, und Browser entfernen UTM-Parameter behandelt den anderen Grund, warum ein Parameter zwischen Klick und Seite verschwinden kann.
Redirects. Serverregeln re-encodieren uneinheitlich, und ob ein Query-String überhaupt überlebt, hängt von der verwendeten Direktive ab. Ein 301-Redirect in .htaccess hat die vollständige Tabelle für Apache; die Kurzfassung ist, dass eine Regel, die den Query-String ersetzt, den Ihren lautlos verwirft.
QR-Codes. Encoding bläht die Payload-Länge auf, und die Payload-Länge entscheidet, wie dicht der gedruckte Code ist. Jedes Leerzeichen kostet drei Zeichen statt eines, jeder Buchstabe mit Akzent sechs. Eine Tracking-URL mit ein paar encodierten Kampagnennamen kann einen Code um eine Version oder zwei nach oben treiben, was bei Visitenkarten-Größe einen echten Unterschied macht - QR-Code scannt nicht listet die Payload-Länge genau aus diesem Grund unter den vier Ursachen. Einen Kurzlink statt der vollen URL zu encodieren, ist die günstigste verfügbare Lösung.
Prüfen, was ein Link tatsächlich trägt
Zwei Befehle klären fast jede Streitfrage. Der erste zeigt, was der Server nach einem Redirect erhält:
curl -sI 'https://example.com/spring?utm_campaign=spring%20sale' | grep -i '^location'
Der zweite baut das Encoding für Sie, statt Ihren Fingern zu vertrauen, was nützlich ist, wenn ein Wert mehrere Übeltäter gleichzeitig enthält:
curl -G --data-urlencode 'utm_campaign=spring & summer sale' \
--data-urlencode 'utm_source=flyer' \
-o /dev/null -w '%{url_effective}\n' https://example.com/spring
Die Ausgabe als Daten lesen, nicht als Dekoration. Sehen Sie %2520, haben Sie ein Double-Encoding-Problem, sehen Sie einen Wert, der zu früh endet, haben Sie ein unencodiertes Trennzeichen, und sehen Sie %3A%2F%2F am Anfang, haben Sie die ganze URL encodiert. Unser Link-Checker macht die Redirect-Hälfte im Browser, falls Sie kein Terminal öffnen möchten.
Die Gewohnheit, die sich lohnt, ist, sich die finale URL einmal mit eigenen Augen anzusehen, bevor eine Kampagne rausgeht. Encoding-Bugs sind im Browser unsichtbar und im Terminal offensichtlich, und sie kosten Sie Attribution statt Uptime, weshalb sie so lange überleben.
Die Cornerstone-Serie lesen
Dieser Beitrag gehört zum Engineering-Cluster. Für die Redirect-Seite behandelt Arten von Redirects jeden Statuscode und jede clientseitige Methode, und wie URL-Shortener funktionieren behandelt, was zwischen Klick und Seite passiert.
Verwandte Beiträge im Blog
Häufig gestellte Fragen
Was ist URL-Encoding?
Ein Zeichen wird durch ein Prozentzeichen ersetzt, gefolgt von seinem Byte-Wert in Hexadezimal, damit das Zeichen nicht mit URL-Syntax verwechselt werden kann. Ein Leerzeichen wird zu %20, ein Ampersand wird zu %26, ein Fragezeichen wird zu %3F. Der Mechanismus ist in RFC 3986 definiert und wird auch Percent-Encoding genannt.
Welche Zeichen müssen URL-encodiert werden?
Alles außerhalb der unreserved-Menge, die RFC 3986 als Buchstaben, Ziffern und die vier Zeichen Bindestrich, Punkt, Unterstrich und Tilde definiert. Alles andere ist entweder reservierte Zeichensetzung mit struktureller Bedeutung oder ein Byte außerhalb von ASCII, und beides muss percent-encodiert werden, wenn es innerhalb eines Werts statt als Syntax auftritt.
Sollte ich die ganze URL encodieren oder nur Teile davon?
Nur die Teile. Eine vollständige URL durch einen Encoder zu schicken, macht aus https://example.com https%3A%2F%2Fexample.com, was überhaupt keine URL mehr ist. Jeden Query-Parameter-Wert und jedes Pfadsegment einzeln encodieren, und Schema, Host und Trennzeichen unangetastet lassen.
Ist ein Leerzeichen %20 oder ein Pluszeichen?
Beides, an unterschiedlichen Stellen. In einem Pfad und in einer generischen URI ist ein Leerzeichen %20. In einem Query-String, der so aufgebaut ist wie ein HTML-Formular ihn baut, ist ein Leerzeichen ein Pluszeichen, weil genau das die application/x-www-form-urlencoded-Serialisierung vorschreibt. Ein tatsächliches Pluszeichen innerhalb eines Query-Werts muss deshalb als %2B geschrieben werden, sonst wird es als Leerzeichen gelesen.
Was ist Double Encoding?
Etwas zu encodieren, das bereits encodiert war, sodass %20 zu %2520 wird, weil das Prozentzeichen selbst zu %25 maskiert wird. Das Symptom ist eine Seite, die ein wörtliches %20 in ihrem Text anzeigt, oder ein Parameter, der mit sichtbaren Escape-Sequenzen ankommt. Es ist fast immer ein Wert, der zwei Schichten durchläuft, die ihn jeweils hilfsbereit encodiert haben.
Warum machen encodierte Zeichen einen QR-Code schwerer scannbar?
Weil jedes davon drei Zeichen statt eines kostet. Ein Leerzeichen ist ein Zeichen an Absicht und drei an Payload, sodass eine Handvoll davon den Code um eine Version oder zwei nach oben treiben kann, was mehr Module auf derselben Druckfläche bedeutet. Eine lange Tracking-URL in einen QR-Code zu encodieren, ist einer der schnellsten Wege, einen Code zu bauen, der nur aus der Nähe scannt.
Elido testen
URL einfügen, kurzer Link in Sekunden
Kein Konto nötig. Link bleibt 30 Tage aktiv. Konto erstellen, um ihn dauerhaft zu behalten.
Kostenlos, keine Anmeldung erforderlich · 2 pro Tag