decodeURI()

Decodes a complete URL's percent-escapes while leaving reserved delimiters encoded.

Signature
decodeURI(encodedURI)
  • Added in JavaScript ECMAScript 3 (1999)

Parameters

ParameterTypeDescription
$encodedURIstringA complete, encoded Uniform Resource Identifier. Other values are converted to strings.

Return value

stringA new string with percent-escapes decoded as UTF-8, except those representing the reserved characters ; / ? : @ & = + $ , #.

Errors

Throws URIError if a % is not followed by two hexadecimal digits, or if the escape sequence does not encode a valid UTF-8 character.

decodeURI() undoes encodeURI() and nothing more. It deliberately refuses to decode escapes for the reserved characters ; / ? : @ & = + $ , #, so %2F stays %2F and %3F stays %3F. That preserves the URL's structure: a slash that was escaped because it was data does not suddenly become a path separator.

What it is good for

Turning an encoded URL back into something readable — a link label, a breadcrumb, a log line, a diff. It is a display transformation, not a parsing step.

What it is not good for

Reading a single query value. Those need decodeURIComponent(), or better, URLSearchParams. If you decode a parameter with decodeURI() you will get back a value that still contains %26 and %3D.

It throws

A malformed escape raises a URIError: a bare %, a non-hex pair, or a truncated multi-byte sequence. URLs from untrusted sources routinely contain these, so wrap the call and fall back to showing the raw string.

Note also that a decoded URL is not necessarily a valid one — decoding is not re-encoding, and a display string should not be turned back into a request without running it through encodeURI() again.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Render a human-readable version of an encoded URL in a link or a log.
  • Compare two URLs after normalising their escaping.
  • Show a filename from an encoded path without breaking the path structure.

Frequently asked questions

What is the difference between decodeURI and decodeURIComponent?

decodeURI leaves escapes for the reserved characters ; / ? : @ & = + $ , # encoded, while decodeURIComponent decodes everything. Use decodeURI on a complete URL and decodeURIComponent on an individual value.

Why does decodeURI not decode %2F?

Because %2F represents a slash, which is a URI delimiter — decoding it would change the URL's path structure. That preservation is the entire reason the two decode functions are separate.

How do I stop decodeURI from throwing on user input?

Wrap the call in try/catch and return the original string on failure, since a bare % or a truncated UTF-8 escape raises URIError. Untrusted or hand-edited URLs contain these often enough that an unguarded call is a reliable crash.

More examples

A clean round trip

encodeURI escapes the spaces and Cyrillic characters; decodeURI restores them exactly. The pair is symmetric as long as the original contained no literal percent signs.

Example · javascript
const original = "https://example.com/отчёт 2024/final draft.pdf";
const encoded = encodeURI(original);

console.log(encoded);
console.log(decodeURI(encoded));
console.log(decodeURI(encoded) === original); // true

Why the reserved set stays encoded

The encoded slash keeps "reports/2024" as a single path segment. decodeURI respects that; decodeURIComponent destroys it by turning the escape into a real separator.

Example · javascript
// A path segment whose data contains a slash
const seg = encodeURIComponent("reports/2024");
const url = `https://example.com/files/${seg}`;
console.log(url);

console.log(decodeURI(url));          // %2F preserved — still one segment
console.log(decodeURIComponent(url)); // %2F decoded — now two segments
console.log(new URL(url).pathname.split("/").length);

Displaying untrusted URLs safely

The second and third inputs both throw URIError — one has a bare percent sign, the other an overlong UTF-8 encoding — so the helper falls back to the raw string instead of failing the render.

Example · javascript
function readable(url) {
  try {
    return decodeURI(url);
  } catch {
    return url;
  }
}

console.log(readable("https://example.com/a%20b"));
console.log(readable("https://example.com/100%"));
console.log(readable("https://example.com/%C0%80"));

Discussion

  • Be the first to comment on this lesson.