URLs contain more structure than they appear to

A destination includes a scheme, host, optional port, path, query, and fragment. Treating it as an arbitrary string makes validation inconsistent and can introduce unsafe or surprising behavior.

Parse the complete value once with a tested URL parser, then apply rules to the structured result.

Fragments do not belong in the server request

A browser keeps the fragment after the hash sign and does not send it to the destination server. A redirect service can preserve it for client navigation, but a platform may intentionally remove fragments when its contract treats them as local UI state.

Whichever policy is chosen should be visible and tested. Silent encoding of the hash into a path changes the destination and is a common normalization bug.

Private destinations need special care

Loopback, private, link-local, and internal hosts can become dangerous when a platform also fetches previews or performs health checks. Rejecting them before storage simplifies the security boundary.

Hostname resolution needs additional checks in an isolated fetcher because a public-looking hostname can later resolve to a private address. String validation alone is not a complete SSRF defense.