X Xerobit

URL Encoding in JavaScript — encodeURIComponent vs encodeURI

JavaScript has two URL encoding functions: encodeURI for full URLs and encodeURIComponent for individual components. Learn the difference, when to use each, how to encode query...

Mian Ali Khalid · · 4 min read
Use the tool
URL Encoder / Decoder
Percent-encode and decode URLs per RFC 3986.
Open URL Encoder / Decoder →

JavaScript has two URL encoding functions with subtly different purposes. Using the wrong one is a common bug that causes broken URLs in production.

Use the URL Encoder to encode and decode URLs instantly.

encodeURI vs encodeURIComponent

// encodeURI: encodes a FULL URL — leaves :, /, ?, &, =, #, @ intact
encodeURI('https://example.com/path?q=hello world&lang=en')
// 'https://example.com/path?q=hello%20world&lang=en'
// Notice: :, /, ?, &, = are preserved (needed for URL structure)

// encodeURIComponent: encodes a URL COMPONENT — encodes :, /, ?, &, =, # too
encodeURIComponent('hello world & more')
// 'hello%20world%20%26%20more'
encodeURIComponent('https://example.com/path')
// 'https%3A%2F%2Fexample.com%2Fpath'

Rule of thumb:

  • Use encodeURI when you have a complete URL and want to make it safe for transmission
  • Use encodeURIComponent for individual values that go INTO a URL (query param values, path segments)

Common mistake: encoding query parameter values

const query = 'fish & chips';
const category = 'food/drinks';

// WRONG: encodeURI won't encode & or / 
const url = `https://api.com/search?q=${encodeURI(query)}&cat=${encodeURI(category)}`;
// 'https://api.com/search?q=fish & chips&cat=food/drinks' ← broken!

// RIGHT: encodeURIComponent for each value
const url = `https://api.com/search?q=${encodeURIComponent(query)}&cat=${encodeURIComponent(category)}`;
// 'https://api.com/search?q=fish%20%26%20chips&cat=food%2Fdrinks' ✓

Build URLs safely with URLSearchParams

// URLSearchParams handles encoding automatically:
const params = new URLSearchParams({
  q: 'fish & chips',
  category: 'food/drinks',
  page: 1,
  sort: 'relevance',
});

const url = `https://api.example.com/search?${params}`;
// 'https://api.example.com/search?q=fish+%26+chips&category=food%2Fdrinks&page=1&sort=relevance'
// Note: URLSearchParams uses + for spaces (form encoding), not %20

// Append multiple values for same key:
const params = new URLSearchParams();
params.append('tag', 'javascript');
params.append('tag', 'css');
params.append('tag', 'html');
// 'tag=javascript&tag=css&tag=html'

Decode URLs

// decodeURIComponent: decodes encoded characters
decodeURIComponent('fish%20%26%20chips')  // 'fish & chips'
decodeURIComponent('hello+world')         // 'hello+world' (+ is NOT decoded)

// Note: + as space is application/x-www-form-urlencoded convention
// Replace + before decoding for form data:
function decodeFormValue(str) {
  return decodeURIComponent(str.replace(/\+/g, ' '));
}

decodeFormValue('hello+world')  // 'hello world'
decodeFormValue('fish+%26+chips')  // 'fish & chips'

// Parse query string:
const qs = '?q=fish+%26+chips&page=2';
const params = new URLSearchParams(qs);
params.get('q')    // 'fish & chips' (URLSearchParams handles + automatically)
params.get('page') // '2'

URL class for robust URL manipulation

// URL class: construct and manipulate URLs safely
const url = new URL('https://example.com/search');
url.searchParams.set('q', 'fish & chips');
url.searchParams.set('page', '2');
url.pathname = '/api/v2/search';

url.toString()
// 'https://example.com/api/v2/search?q=fish+%26+chips&page=2'

// Parse existing URL:
const parsed = new URL('https://user:pass@example.com:8080/path?q=hello#section');
parsed.hostname    // 'example.com'
parsed.port        // '8080'
parsed.pathname    // '/path'
parsed.search      // '?q=hello'
parsed.hash        // '#section'
parsed.username    // 'user'

Encode path segments

// Path segments need encodeURIComponent (encode /) 
// but typically you want / preserved in the path:

const userId = 'user/with/slashes';
const filename = 'my file.pdf';

// Each segment encoded separately:
const path = `/users/${encodeURIComponent(userId)}/files/${encodeURIComponent(filename)}`;
// '/users/user%2Fwith%2Fslashes/files/my%20file.pdf'

// The URL object handles this too:
const url = new URL('https://example.com');
url.pathname = `/files/${encodeURIComponent(filename)}`;
url.toString()
// 'https://example.com/files/my%20file.pdf'

Characters that DON’T need encoding

// These are "unreserved characters" — safe in any URL component:
// A-Z a-z 0-9 - _ . ~

// encodeURIComponent does NOT encode these:
encodeURIComponent('hello-world_test.file~123')
// 'hello-world_test.file~123' (unchanged)

// Everything else gets percent-encoded
encodeURIComponent('hello world!')
// 'hello%20world!'

Related posts

Related tool

URL Encoder / Decoder

Percent-encode and decode URLs per RFC 3986.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.