Was ist URL-Parsing?
URL-Parsing ist der Vorgang, einen Uniform Resource Locator in seine einzelnen Bestandteile zu zerlegen: Protokoll (Schema), Hostname, Port, Pfadname, Query-Parameter und Fragment-Bezeichner. Jede URL folgt einer Struktur, die durch RFC 3986 und den WHATWG URL Standard definiert ist. Ein URL-Parser liest die rohe Zeichenkette, identifiziert jedes Segment anhand seiner Trennzeichen (://, :, /, ?, #, &, =) und gibt sie als separate, zugängliche Felder zurück.
Browser führen URL-Parsing jedes Mal durch, wenn du eine Adresse eingibst oder auf einen Link klickst. Der JavaScript-URL-Konstruktor, das Python-Modul urllib.parse und das Go-Paket net/url implementieren alle Parser, die denselben strukturellen Regeln folgen. Eine URL zu parsen ist das Gegenteil von URL-Encoding: Statt Zeichen für den sicheren Transport zu transformieren, zerlegst du eine bereits gebildete URL in ihre Bestandteile.
Eine typische URL wie https://api.example.com:8080/v1/users?page=2&limit=10#section enthält sechs verschiedene Komponenten. Die Trennzeichen – ://, :, /, ?, &, =, und # – machen das Parsing deterministisch: Jedes signalisiert eine Grenze und ermöglicht es einem Parser, Felder ohne Mehrdeutigkeit zu extrahieren.
Warum einen Online-URL-Parser verwenden?
Eine URL manuell mit dem Auge aufzuteilen ist fehleranfällig, besonders wenn die Zeichenkette encodierte Zeichen, mehrere Query-Parameter oder nicht-standardmäßige Ports enthält. Dieses Tool parst die URL mit demselben WHATWG-konformen Algorithmus, den Browser verwenden, und zeigt jede Komponente in einer übersichtlichen, kopierbaren Tabelle an.
Anwendungsfälle für den URL-Parser
URL-Komponentenreferenz
Die folgende Tabelle zeigt jede Property, die der JavaScript-URL-Konstruktor beim Parsen einer URL zurückgibt. Dieselben Komponenten existieren in Pythons urlparse-Ergebnis, Gos url.URL-Struct und PHPs parse_url-Ausgabe, obwohl sich die Property-Namen zwischen den Sprachen unterscheiden.
| Property | Beispiel | Beschreibung |
|---|---|---|
| protocol | https: | Scheme including the trailing colon |
| hostname | api.example.com | Domain name or IP address |
| port | 8080 | Port number (empty string if default) |
| pathname | /v1/users | Path starting with / |
| search | ?page=2&limit=10 | Query string including the leading ? |
| hash | #section | Fragment identifier including the leading # |
| origin | https://api.example.com:8080 | protocol + hostname + port |
| host | api.example.com:8080 | hostname + port |
| username | admin | Credentials before @ (rarely used in practice) |
| password | secret | Credentials before @ (avoid in production URLs) |
| href | (full URL) | The complete, serialized URL string |
WHATWG URL Standard vs. RFC 3986
Zwei Spezifikationen definieren, wie URLs geparst werden sollen. Sie stimmen in der Grundstruktur überein, weichen aber in Randfällen voneinander ab – und diese Abweichung ist meist der Grund, wenn dein Browser eine URL anders behandelt als dein Server.
In der Praxis treten die meisten Unterschiede beim Parsen von URLs mit internationalisierten Domainnamen (IDN), fehlenden Schemas oder ungewöhnlichen Zeichen auf. Der WHATWG-Parser konvertiert IDN-Hostnamen automatisch in Punycode, während strikte RFC 3986-Parser diese möglicherweise ablehnen. Wenn du eine URL in dieses Tool einfügst und andere Ergebnisse als dein serverseitiger Code liefert, ist der WHATWG-vs-RFC-Unterschied die wahrscheinlichste Ursache.
Code-Beispiele
Jede wichtige Programmiersprache hat einen eingebauten URL-Parser. Die folgenden Beispiele parsen dieselbe URL und extrahieren ihre Komponenten. Beachte die kleinen Namensunterschiede zwischen den Sprachen: Python verwendet scheme statt protocol, und Go stellt RawQuery statt search bereit.
const url = new URL('https://api.example.com:8080/v1/users?page=2&limit=10#section')
url.protocol // → "https:"
url.hostname // → "api.example.com"
url.port // → "8080"
url.pathname // → "/v1/users"
url.search // → "?page=2&limit=10"
url.hash // → "#section"
// Iterate over query parameters
for (const [key, value] of url.searchParams) {
console.log(`${key} = ${value}`)
}
// → "page = 2"
// → "limit = 10"
// Modify and re-serialize
url.searchParams.set('page', '3')
url.toString()
// → "https://api.example.com:8080/v1/users?page=3&limit=10#section"from urllib.parse import urlparse, parse_qs
result = urlparse('https://api.example.com:8080/v1/users?page=2&limit=10#section')
result.scheme # → 'https'
result.hostname # → 'api.example.com'
result.port # → 8080
result.path # → '/v1/users'
result.query # → 'page=2&limit=10'
result.fragment # → 'section'
# Parse query string into a dict
params = parse_qs(result.query)
params['page'] # → ['2']
params['limit'] # → ['10']
# Reconstruct with modifications
from urllib.parse import urlencode, urlunparse
new_query = urlencode({'page': '3', 'limit': '10'})
urlunparse(result._replace(query=new_query))
# → 'https://api.example.com:8080/v1/users?page=3&limit=10#section'package main
import (
"fmt"
"net/url"
)
func main() {
u, err := url.Parse("https://api.example.com:8080/v1/users?page=2&limit=10#section")
if err != nil {
panic(err)
}
fmt.Println(u.Scheme) // → "https"
fmt.Println(u.Hostname()) // → "api.example.com"
fmt.Println(u.Port()) // → "8080"
fmt.Println(u.Path) // → "/v1/users"
fmt.Println(u.RawQuery) // → "page=2&limit=10"
fmt.Println(u.Fragment) // → "section"
// Query params as map
q := u.Query()
fmt.Println(q.Get("page")) // → "2"
fmt.Println(q.Get("limit")) // → "10"
}<?php $url = 'https://api.example.com:8080/v1/users?page=2&limit=10#section'; $parts = parse_url($url); $parts['scheme']; // → "https" $parts['host']; // → "api.example.com" $parts['port']; // → 8080 $parts['path']; // → "/v1/users" $parts['query']; // → "page=2&limit=10" $parts['fragment']; // → "section" // Parse query string into an array parse_str($parts['query'], $params); $params['page']; // → "2" $params['limit']; // → "10"