URL-Parser & Decoder

Parsen Sie jede URL in ihre Komponenten, Protokoll, Host, Port, Pfad, Query-Parameter und Fragment.

URL-Anatomie: Sechs Komponenten, eine lange Geschichte

Eine URL wird in sechs konzeptionelle Teile zerlegt: scheme://userinfo@host:port/path?query#fragment. Das scheme sagt dem Client, welches Protokoll zu verwenden ist (https, http, ftp, mailto, file, data) und ist der einzige immer vorhandene Teil. Die Komponente userinfo (username:password@) ist im modernen Gebrauch selten; Browser entfernen sie meist aus angezeigten URLs, weil sie seit den 1990ern ein Phishing-Vektor ist. Der host ist der Netzwerkort, ein registrierter Domainname, eine IP-Adresse (IPv4 als gepunktetes Quartett oder IPv6 in eckigen Klammern) oder ein spezieller Name wie localhost. Der port ist der TCP/UDP-Port (80 default für HTTP, 443 für HTTPS, etc.); wenn weggelassen, gilt der Default des Schemas. Der path ist die durch Schrägstriche getrennte Hierarchie, die die Ressource innerhalb des Hosts identifiziert. Der query string (alles nach dem ?) trägt durch & getrennte Schlüssel-Wert-Paare, verwendet für Filterung, Pagination, Tracking, Formular-Übermittlung. Das Fragment (alles nach #) ist der einzige Teil der URL, der nie an den Server geschickt wird, er wird vollständig clientseitig vom Browser verarbeitet, um zu einem bestimmten Abschnitt zu scrollen oder, in Single-Page-Apps, den Routen-Zustand anzuzeigen.

Das Format des Query-Strings selbst hat eine Gabelung: traditionelles ?key=value&key2=value2 mit Werten, die nach RFC 3986 percent-encodiert sind, vs die ältere form-encoded-Konvention application/x-www-form-urlencoded, bei der + ein Leerzeichen bedeutet (ursprünglich für HTML-Formular-Übermittlungen). Die meisten Parser handhaben beide, aber die Konvertierung ist asymmetrisch: %20 dekodiert immer zu einem Leerzeichen; + dekodiert nur innerhalb eines Query-Strings zu einem Leerzeichen, nie innerhalb eines Paths. Das ist einer der häufigsten URL-Parsing-Bugs in der Praxis.

Eine kurze Geschichte der URL

Die URL (ursprünglich „Universal Document Identifier“, dann „Universal Resource Locator“) wurde von Tim Berners-Lee zwischen seinem März-1989-Memo „Information Management: A Proposal“ am CERN (das, das sein Chef Mike Sendall mit „Vague but exciting“ kommentierte) und den ersten öffentlich browsbaren Webseiten vom August 1991 erfunden. Die kanonische erste URL war http://info.cern.ch/hypertext/WWW/TheProject.html, veröffentlicht am 6. August 1991. Die IETF-Diskussionen von 1992 benannten UDIs in URLs um, um einen Vokabularstreit zu umgehen. RFC 1738 („Uniform Resource Locators“), verfasst von Berners-Lee, Masinter und McCahill, wurde im Dezember 1994 als erste formale URL-Syntax veröffentlicht. RFC 2396 folgte im August 1998 und verallgemeinerte URLs zum breiteren URI-Konzept. Die aktuelle kanonische Spezifikation ist RFC 3986 („URI Generic Syntax“), veröffentlicht Januar 2005, herausgegeben von Berners-Lee, Roy Fielding und Larry Masinter, ein STD-66 Internet Standard, der höchsten Reifestufe der IETF. RFC 3986 ist das, was jeder URL-Parser nominell anvisiert. In der Praxis weichen moderne Browser in zahlreichen Edge Cases von RFC 3986 ab, weshalb die WHATWG einen separaten URL Living Standard auf url.spec.whatwg.org pflegt, der beschreibt, was Browser tatsächlich tun; die WHATWG-Spec strebt ausdrücklich an, RFC 3986 und RFC 3987 mittelfristig abzulösen, und beide weichen weiterhin bei Dingen wie der Behandlung von führenden Leerzeichen, Percent-Encoding-Sets und Unicode-Normalisierung voneinander ab.

Unreservierte, reservierte und percent-encodierte Zeichen

RFC 3986 §2.3 definiert die unreservierten Zeichen: die einzigen Zeichen, die in jeder URI-Komponente ohne Percent-Encoding garantiert sicher sind: A-Z, a-z, 0-9, Bindestrich (-), Punkt (.), Unterstrich (_) und Tilde (~). 66 Zeichen insgesamt. Alles andere ist entweder ein reserviertes Zeichen mit struktureller Bedeutung in irgendeiner Komponente (gen-delims (:/?#[]@) und sub-delims (!$&'()*+,;=)) oder „sonstig“ und muss percent-encodiert werden, wenn es in einer URI erscheint. Percent-Encoding (RFC 3986 §2.1) nimmt die Byte-Folge eines Zeichens (in UTF-8, sofern das Schema nichts anderes vorgibt) und ersetzt jedes Byte durch %HH, wobei HH der zweistellige Hex-Wert des Bytes ist. So wird ein UTF-8-encodiertes é (Bytes 0xC3 0xA9) zu %C3%A9; das russische Wort привет wird zu %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82: zwei Bytes pro Zeichen, sechs %XX-Tripel und 36 percent-encodierte Zeichen URL für sechs kyrillische Buchstaben.

Browser zeigen percent-encodierte Paths auf zwei Arten an: die meisten modernen Browser (Chrome, Firefox, Safari) dekodieren und rendern die ursprünglichen Unicode-Glyphen in der Adressleiste, wenn die Codierung gültiges UTF-8 ist, kopieren aber die wörtliche percent-encodierte Form, wenn der Nutzer die URL kopiert. Ältere Browser und viele Web-Logs zeigen nur die percent-encodierte Form, deshalb können „hübsche Unicode-URLs“ irreführend sein: sie sehen in der Adressleiste schön aus und in jedem Text, in dem sie geteilt werden, hässlich. RFC 3987 („Internationalized Resource Identifiers“, IRIs), veröffentlicht Januar 2005, formalisierte Unicode-URLs in ihrer nicht-encodierten Form; Punycode (RFC 3492, März 2003) definiert, wie internationalisierte Domainnamen für DNS Label für Label in ASCII codiert werden: das chinesische Top-Label 中国 wird zu xn--fiqs8s, sodass example.中国 auf DNS-Ebene zu example.xn--fiqs8s wird. Die kanonische Demonstration sind Wikipedias IRI-URLs: https://ja.wikipedia.org/wiki/東京 funktioniert in jedem modernen Browser, obwohl die zugrundeliegende Anfrage den Path als /wiki/%E6%9D%B1%E4%BA%AC kodiert.

Der WHATWG-URL-Standard, was Browser tatsächlich tun

RFC 3986 der IETF sagt eine Sache; Browser tun etwas leicht anderes. Die WHATWG (das Standardisierungsgremium der Browser-Hersteller) pflegt einen separaten URL Living Standard auf url.spec.whatwg.org, der die algorithmische Zustandsmaschine beschreibt, die Browser tatsächlich ausführen, einschließlich Behandlung von führendem Whitespace, Steuerzeichen, je nach Komponente variierender Percent-Encoding-Sets und Unicode-Normalisierung. Die WHATWG-Spec ist das, was der URL-Konstruktor des Browsers (new URL(input)) implementiert, und das, worauf Node.js, Deno und Bun für ihr eingebautes URL-Parsing alle konvergiert sind. Der Ada-URL-Parser: geschrieben in C++ von Yagiz Nizipli, Daniel Lemire und anderen, wurde der WHATWG-konforme Parser, der das URL-Parsing von Node.js seit Node.js 18.16.0 (April 2023) antreibt und den älteren url.parse()-Pfad ablöst; er ist messbar schneller als jede vorherige Implementierung und der De-facto-Standard für hochperformantes URL-Parsing in 2026. RFC 3986 und die WHATWG-Spec sind nach wie vor nicht vollständig in Einklang gebracht, und historische Divergenz taucht in Legacy-Code-Pfaden und älteren Runtime-Versionen noch auf.

Der Query-String, und die URLSearchParams-API

Der Query-String ist technisch nur „alles nach dem ? und vor dem #“, die Spec definiert nicht wirklich, wie er zu interpretieren ist. Die Konvention ?key=value&key=value mit &-Trennern ist Konvention, nicht Anforderung. In der Praxis dominieren zwei Query-String-Formate: application/x-www-form-urlencoded (das Standardformat für HTML-Formular-Übermittlung, bei dem + ein Leerzeichen bedeutet) und die Standard-URI-Query-Konvention (bei der Leerzeichen immer %20 ist). Die URLSearchParams-API des Browsers (Teil des WHATWG URL Living Standard) handhabt beide Formate transparent für das Parsing und gibt beim Stringifizieren die form-encoded-Variante aus. Wiederholte Schlüssel sind legal: ?tag=red&tag=blue&tag=green ist gültig, und URLSearchParams.getAll('tag') liefert ['red', 'blue', 'green']. Verschiedene Web-Frameworks behandeln wiederholte Schlüssel unterschiedlich: Rails und Express sammeln wiederholte Schlüssel in Arrays, während PHP frühere Werte durch spätere ersetzt, sofern der Schlüssel nicht die Klammer-Konvention name[] verwendet, eine ständige Quelle von Cross-Framework-Bugs in API-Integrationen.

Häufige URL-Parsing-Stolperfallen

Häufige Anwendungsfälle

Datenschutz: URLs tragen echte Geheimnisse

URLs werden im Allgemeinen nicht als geheim behandelt, tragen aber oft Daten, die es sind. OAuth-Callback-URLs enthalten Access Tokens. Magic-Link-Login-URLs enthalten Einmal-Authentifizierungs-Tokens. Passwort-Reset-Links enthalten Reset-Tokens. Interne API-URLs enthalten interne Hostnamen und Routing-Pfade, die Infrastruktur preisgeben. Sogar gewöhnliche Anwendungs-URLs verraten Nutzerverhalten durch Query-Parameter, Suchbegriffe, Filterauswahlen, Profil-IDs, Session-Identifier. Der Referer-Header leakt die vorherige URL an jede verlinkte Site, gemindert durch den 2017 als W3C Candidate Recommendation eingeführten Referrer-Policy-Header (Browser-Defaults variieren weiterhin). URLs landen in Server-Access-Logs, im Browser-Verlauf, in Browser-Bookmarks, in CDN-Logs, in Analytics-Pipelines, in Chat-App-Link-Vorschauen. Ein serverseitiger URL-Parser sieht jede URL, die in ihn eingefügt wird; ein Nur-Browser-Parser nicht. Für interne API-URLs, OAuth-Callbacks mit Tokens, Passwort-Reset-Links oder jede URL, die du nicht auf der Festplatte eines Fremden haben möchtest, ist ein Nur-Browser-Parser die richtige Architektur. Überprüfe es im Network-Tab der DevTools, während du parst, oder nimm die Seite nach dem Laden offline (Flugmodus).

Häufig gestellte Fragen

Welche Teile enthält eine URL?

Sechs konzeptionelle Teile: scheme (https, http, ftp, mailto), userinfo (im modernen Gebrauch selten, meist von Browsern als Phishing-Mitigation entfernt), host (Domain oder IP), port (Default 80 für HTTP, 443 für HTTPS), path (durch Schrägstriche getrennte Hierarchie), query (Schlüssel-Wert-Paare nach ?) und fragment (nach #, nie an den Server gesendet). Die vollständige Grammatik steht in RFC 3986 §3 (Januar 2005, STD 66) und im WHATWG URL Living Standard.

Wie dekodiere ich URL-encodierte Zeichen?

Percent-Encoding ersetzt unsichere Zeichen durch ein % gefolgt vom Hex-Code des Bytes: ein Leerzeichen ist %20, ein Doppelpunkt %3A, ein Schrägstrich %2F, ein Ampersand %26, das At-Zeichen %40. UTF-8-Multibyte-Zeichen werden Byte für Byte kodiert, also wird é zu %C3%A9 (zwei Bytes). Der Parser dekodiert in der angezeigten Ausgabe automatisch alle percent-encodierten Zeichen. Die JavaScript-Standardfunktionen sind encodeURIComponent() zum Kodieren einzelner Werte und decodeURIComponent() zum Dekodieren.

Was ist ein URL-Fragment?

Das Fragment (alles nach #) ist der einzige Teil der URL, der vollständig clientseitig verarbeitet wird, er wird nie in HTTP-Anfragen an den Webserver gesendet. Ursprünglicher Zweck: den Browser zu einem Anker-Element mit dieser ID zu scrollen. Moderne Verwendungen umfassen Routen-Zustand von Single-Page-Applications (#/dashboard/profile), OAuth-Implicit-Flow-Tokens (heute zugunsten von Authorization Code mit PKCE nicht mehr empfohlen) und PDF-Seitennavigation (file.pdf#page=5). Weil Fragmente den Server nicht erreichen, sind sie ein Ort, um Werte zu verstecken, die nicht in Server-Logs auftauchen sollten.

Warum bedeutet + manchmal Leerzeichen und manchmal +?

Es existieren zwei Encoding-Konventionen. application/x-www-form-urlencoded (das Standardformat für HTML-Formular-Übermittlung) kodiert Leerzeichen als +; Standard-Percent-Encoding (nach RFC 3986) kodiert Leerzeichen als %20. Beides ist in Query-Strings gültig; in Paths und Fragmenten ist nur %20 gültig. URLSearchParams handhabt beides transparent. Der Cross-Context-Bug entsteht, wenn Code encodeURIComponent (das Leerzeichen als %20 kodiert) für Query-Parameter verwendet, die der Server in form-encoded erwartet, oder umgekehrt.

Werden relative URLs unterstützt?

Der Parser erwartet eine vollständige URL mit Schema. Für einen relativen Path wie /api/users stelle eine Basis-URL voran (https://example.com/api/users), um ihn zu parsen. Etwas Relative-URL-Parsing (Auflösung gegen eine Basis-URL, wie der Browser es für href-Attribute macht) steht auf der Roadmap, die Zwei-Argument-Form des WHATWG-URL-Konstruktors (new URL(relative, base)) handhabt das und ist das, was Produktions-Code verwenden sollte.

Werden meine URLs irgendwohin gesendet?

Nein. Das Parsen läuft vollständig in deinem Browser über den WHATWG-URL-Konstruktor, die URL, die du einfügst, verlässt dein Gerät nie. Überprüfe es im Network-Tab der DevTools, während du auf Parse klickst, oder nimm die Seite nach dem Laden offline (Flugmodus). Sicher für OAuth-Callback-URLs mit Access Tokens, Passwort-Reset-Links mit Einmal-Tokens, interne API-URLs, die Infrastruktur preisgeben, oder jede URL, die du nicht auf der Festplatte eines Fremden haben möchtest.

Verwandte Tools