- Query parameters are decoded and grouped
- Each parameter is percent-decoded and listed separately, so you can read values that were unreadable in the raw URL. A parameter repeated more than once becomes an array, which is the correct interpretation, a URL may legitimately carry the same key several times, and most frameworks expose those as a list.
- Passwords are redacted
- A URL can embed credentials as user:password@host. Since this output may be pasted into a ticket or a chat, any password is replaced with a placeholder in every field, including the full href, echoing it back would defeat the point of redacting it at all.
- Default ports disappear
- The port field is empty for https on 443 or http on 80, because the URL specification drops the default. That is not a parsing failure; it reflects that the URL is equivalent with or without it.
- The fragment never reaches the server
- Everything after # is handled by the browser alone and is not included in the HTTP request. This matters when debugging: a value in the fragment is invisible to server logs, which is why OAuth implicit flows that returned tokens there were so hard to audit.
- A scheme is required
- Parsing needs an absolute URL, so example.com/path alone is rejected, without a scheme, the string is a relative reference whose meaning depends on a base URL. Prefix it with https:// to parse.