Reading a URL that has been through a machine
URLs arrive encoded from everywhere useful. Server logs store them that way, analytics referrer reports keep them that way, error trackers and email link-wrappers pile encoding on top of encoding, and a URL copied out of a chat client is frequently escaped twice over.
Decoding turns that back into something readable. It is a small operation with a large payoff, because a decoded query string usually tells you immediately what a request was actually asking for — which search term produced an error, which filter combination generated a page nobody meant to publish, which campaign a visitor came from.
The anatomy of what comes back
Once decoded, a URL splits into parts worth reading separately. Everything before the question mark is the path, which identifies the resource. Everything between the question mark and any hash is the query string, made of name and value pairs separated by ampersands. Anything after a hash is the fragment, and it is worth knowing that the fragment never reaches the server — it exists only in the browser.
That last point explains a recurring puzzle: a URL that clearly contains an identifier which your server logs do not show. If it sits after the hash, the server was never told.
What the parameters reveal
Most of a decoded query string is campaign tracking, and it is a readable format once you know the five names:
utm_source — where the link was placed. A site, a newsletter, a platform.
utm_medium — the kind of channel. Email, cpc, social, referral.
utm_campaign — the campaign name, which is usually the most revealing field because people name campaigns candidly.
utm_term — a paid keyword, on advertising links.
utm_content — which variant of a creative or which link in a template was clicked.
Alongside those you will meet click identifiers: gclid from Google Ads, fbclid from Facebook, msclkid from Microsoft, and a growing collection of others. These are opaque strings that let the platform match a click to a visit. They carry no readable information for you, and they are worth recognising mainly because they create a distinct URL for every single click — which is where a great many duplicate-URL problems in analytics and indexing come from.
Spotting double encoding
If the decoded output still contains a percent sequence, the string was encoded twice. %2520 is %20 that has been encoded again, and it means two layers of code each escaped the same value.
This is a real bug rather than a curiosity. It breaks links in ways that are hard to see, because the address looks approximately right and simply resolves to the wrong place. Decode a suspect URL once, and if percent codes survive, you have found the fault and you know where to look: two components, both being careful.
The plus sign is ambiguous
A plus means a space in form-encoded query strings and means a literal plus everywhere else. There is no way to tell from the string alone which was intended, which is why the [msm_tool slug="url-decoder"] leaves plus signs untouched — converting them unconditionally would corrupt every path and identifier that legitimately contains one.
If you are reading a query string from an HTML form submission, mentally read pluses as spaces. If you are reading a path, or an identifier, or a value from an API, read them as pluses. Email addresses are the case where this matters most: the plus in an address with a tag is a real plus, and a decoder that silently converted it would hand you an address that does not exist.
Errors, and what they mean
Decoding fails on a percent sign not followed by two valid hexadecimal digits, and it fails on the whole string rather than skipping the bad character. That is stricter than it sounds and it is the right behaviour: a half-decoded string looks plausible and is wrong.
The usual cause is a literal percent sign that was never encoded. In a URL a percent has to be written as %25; a bare one makes the entire string invalid. Discount codes and pricing pages generate this constantly.
Worth noting too that HTML entities are a different mechanism. & and " come from HTML escaping, not from percent-encoding, and a URL copied out of page source can carry both. Each needs undoing separately, and a decoder handles only its own kind.
Two cautions
First, decoded text is not safe to output. It can contain angle brackets, quotation marks and script tags, because anyone can put anything in a URL. Decoding is for reading; putting the result into a page without escaping it again is one of the oldest vulnerabilities on the web.
Second, URLs carry more personal data than people expect. Query strings from logs and analytics routinely contain search terms, email addresses, order references, session tokens and occasionally passwords that somebody's badly built form put in a GET request. This is a good reason to prefer a decoder that runs in your own browser over one that posts your input to a server, and a better reason to check what your own URLs are carrying — anything in a query string ends up in server logs, in referrer headers sent to third parties, and in analytics reports that a good many people can read.