URL Encoding in JavaScript

Deep dive into JavaScript's URL encoding functions. Learn the differences between encodeURIComponent() and encodeURI() and when to use each.

JavaScript September 1, 2025 8 min read

JavaScript's URL Encoding Functions

If you’ve ever worked with URLs in JavaScript, you’ve probably come across two oddly similar functions: encodeURIComponent() and encodeURI(). At first glance, they look like they’re doing the same job—but they’re not. Each serves a slightly different purpose, and using the wrong one can quietly break your app in ways that are tricky to debug.

Let’s break them down and figure out when to use which.

encodeURIComponent() vs encodeURI(): What’s the Difference?

encodeURIComponent()

This one’s the stricter sibling. encodeURIComponent() encodes pretty much everything except a handful of safe characters:


A-Z a-z 0-9 - _ . ! ~ * ' ( )
  

Because it’s so thorough, you’ll want to use it for individual parts of a URL—things like query parameters or path segments. Basically, anywhere a stray & or = could cause chaos.


// Example: encodeURIComponent()
const param = "hello world & special=chars";
const encoded = encodeURIComponent(param);
console.log(encoded); 
// Output: "hello%20world%20%26%20special%3Dchars"
  

encodeURI()

encodeURI(), on the other hand, is more forgiving. It leaves characters like ?, &, =, and # alone because those symbols are essential for structuring a full URL. Here’s the list of what it keeps intact:


A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #
  

This function shines when you need to encode an entire URL but still want it to work as a proper address.


// Example: encodeURI()
const url = "https://example.com/hello world?param=value&other=special chars";
const encodedUrl = encodeURI(url);
console.log(encodedUrl);
// Output: "https://example.com/hello%20world?param=value&other=special%20chars"
  

When to Use Which

Use encodeURIComponent() when encoding:

  • Query parameter values (and names)
  • Fragment identifiers
  • Path segments
  • Any string that’s just a piece of the URL

// Correct usage: encoding query parameters
const baseUrl = "https://example.com/search";
const query = "javascript & web development";
const category = "programming/how-to";

const url = `${baseUrl}?q=${encodeURIComponent(query)}&cat=${encodeURIComponent(category)}`;
console.log(url);
// Output: "https://example.com/search?q=javascript%20%26%20web%20development&cat=programming%2Fhow-to"
  

Use encodeURI() when encoding:

  • A full URL you don’t want to break
  • URLs with spaces in paths
  • Situations where query separators (&, =, ?) must remain untouched

// Correct usage: encoding a complete URL with spaces
const path = "https://example.com/my page.html";
const encodedPath = encodeURI(path);
console.log(encodedPath);
// Output: "https://example.com/my%20page.html"
  

Warning: Don’t use encodeURI() for query parameters—it won’t encode critical characters like &, =, or ?. That’s a recipe for broken URLs.

Decoding: The Other Half of the Story

Of course, what you encode you’ll eventually need to decode. JavaScript gives you two matching functions:

  • decodeURIComponent() – for strings encoded with encodeURIComponent()
  • decodeURI() – for strings encoded with encodeURI()

// Encoding and decoding
const original = "hello world & special=chars";

// Encode
const encoded = encodeURIComponent(original);
console.log(encoded); // "hello%20world%20%26%20special%3Dchars"

// Decode
const decoded = decodeURIComponent(encoded);
console.log(decoded); // "hello world & special=chars"
  

Note: Always decode with the matching function. Mixing them up can lead to half-decoded messes.

Common Mistakes (and How to Dodge Them)

1. Using the wrong function for query parameters


// ❌ Wrong
const baseUrl = "https://example.com/search";
const query = "value with & and =";
const badUrl = `${baseUrl}?q=${encodeURI(query)}`;
// Breaks: & and = stay unencoded

// ✅ Correct
const goodUrl = `${baseUrl}?q=${encodeURIComponent(query)}`;
  

2. Double encoding


// ❌ Wrong
const text = "hello world";
const doubleEncoded = encodeURIComponent(encodeURIComponent(text));
// "hello%2520world"

// ✅ Correct
const singleEncoded = encodeURIComponent(text);
// "hello%20world"
  

3. Ignoring errors while decoding


// ❌ Wrong
decodeURIComponent("%E0%A4%A"); // Throws an error

// ✅ Correct
function safeDecodeURIComponent(encoded) {
  try {
    return decodeURIComponent(encoded);
  } catch (e) {
    console.warn("Failed to decode:", encoded);
    return encoded;
  }
}
  

Going a Step Further

Custom encoding for special cases


// Custom encode
function customEncode(str) {
  let encoded = encodeURIComponent(str);
  encoded = encoded.replace(/%20/g, '+'); // Spaces to +
  encoded = encoded.replace(/%2B/g, '+'); // Preserve +
  return encoded;
}

// Custom decode
function customDecode(encoded) {
  encoded = encoded.replace(/\+/g, '%20');
  return decodeURIComponent(encoded);
}
  

Handling Unicode gracefully


const unicodeText = "café résumé";
const encodedUnicode = encodeURIComponent(unicodeText);
console.log(encodedUnicode); // "caf%C3%A9%20r%C3%A9sum%C3%A9"

const decodedUnicode = decodeURIComponent(encodedUnicode);
console.log(decodedUnicode); // "café résumé"
  

Browser Support

Good news: every modern browser supports these functions, and they’ve been around since the very first version of ECMAScript back in 1997. The only gotcha? Invalid sequences. Newer browsers will throw an error, while older ones might behave unpredictably. When in doubt, wrap decoding in try...catch.

Real-World Examples

Building a URL with parameters


function buildUrl(baseUrl, params) {
  const queryString = Object.keys(params)
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join('&');
  
  return `${baseUrl}?${queryString}`;
}

const params = {
  q: "javascript tutorial",
  page: "1",
  sort: "relevance",
  category: "web development"
};

console.log(buildUrl("https://example.com/search", params));
  

Parsing query parameters


function parseQueryParams(url) {
  const queryString = url.split('?')[1];
  if (!queryString) return {};
  
  return queryString.split('&').reduce((params, pair) => {
    const [key, value] = pair.split('=').map(decodeURIComponent);
    params[key] = value;
    return params;
  }, {});
}

const testUrl = "https://example.com/search?q=javascript%20tutorial&page=1";
console.log(parseQueryParams(testUrl));
// {q: "javascript tutorial", page: "1"}