A URL has more structure than most people register at a glance: scheme, an optional userinfo segment, host, optional port, path, query string, and fragment — and several of those components are specifically abused in phishing links because browsers render only the parts users actually look at. The userinfo segment (https://real-bank.com@evil.com/) is the most classic trick: everything before the @ is authentication info for the URL, and the actual host is everything after it, so a link that appears to start with a trusted domain name can resolve entirely elsewhere.
Percent-encoding lets any byte appear in a URL component using %XX hex notation, and it's frequently applied more than once — a query parameter value can be percent-encoded, and that whole encoded string can itself be percent-encoded again as it passes through a redirect chain or a URL-shortening service. Decoding only one layer when there are two hides the actual destination, which matters a great deal when the parameter in question is a redirect target.
Internationalized domain names add another layer: a domain containing non-ASCII characters is actually transmitted as ASCII using punycode, an xn-- prefixed encoding — xn--80ak6aa92e.com decodes to a Cyrillic-lookalike string, not to any Latin text, even though the rendered domain in a browser's address bar can look completely unremarkable. Combined with confusable characters, this is the exact mechanism behind most homograph domain attacks.
This parser breaks the URL into every component, decodes percent-encoding recursively until it stabilizes, decodes any punycode hostname labels back to their intended Unicode form, and cross-checks the decoded hostname against a confusables table and the userinfo-segment trick — surfacing exactly what a user would actually be taken to, not just what the link displays.
Edge cases worth knowing
- A userinfo segment designed to look like the actual domain
- https://paypal.com.verify-account.example/ has paypal.com as a path-like subdomain label, not the host — the actual host is verify-account.example. This parser makes the true host unmistakable, separated from every other component.
- Multiple layers of percent-encoding in a redirect parameter
- A ?next=%2568%2574%2574%2570... parameter can encode a URL that itself needs another decode pass to reveal. This parser decodes recursively until no further percent-encoding is found, rather than stopping after one pass.
- A punycode domain that decodes to plain ASCII lookalikes
- Not every xn-- domain is malicious — many are legitimate internationalized domains for non-English businesses. This parser decodes and displays the Unicode form either way; whether it's suspicious depends on whether the decoded characters are confusable with a well-known brand, which the confusables cross-check flags explicitly.
Common mistakes
- Reading the first recognizable-looking domain name in a URL as the actual host, when it's really part of the path, a subdomain, or the userinfo segment.
- Decoding percent-encoding once and treating the result as final when the value was multiply-encoded through a chain of redirects.
- Clicking a link with an unfamiliar xn-- prefix without decoding it to see what script it actually represents.
- Trusting an https:// scheme as a signal of legitimacy — it guarantees an encrypted connection to whatever the host is, not that the host is who it claims to be.