URL Encoding Guide for Web Developers
URLs can only contain a limited set of ASCII characters. Any character outside that set — spaces, special symbols, accented letters, emoji — must be percent-encoded before being placed in a URL. A single missing %20 or an unencoded & in a query string can silently break your API requests. This guide covers everything you need to encode URLs correctly.
What is percent-encoding?
Each byte is replaced by a % followed by its two-digit hexadecimal value. For example, a space (byte 0x20) becomes %20, and & (byte 0x26) becomes %26.
// Without encoding — the & breaks the query string https://api.example.com/search?q=salt & pepper // Correctly encoded https://api.example.com/search?q=salt%20%26%20pepper
encodeURIComponent — encode a single value
Use this for encoding individual query parameter values. It encodes everything except letters, digits, and - _ . ! ~ * ' ( ).
encodeURIComponent('hello world'); // 'hello%20world'
encodeURIComponent('price=₹1,500'); // 'price%3D%E2%82%B91%2C500'
encodeURIComponent('path/to/file'); // 'path%2Fto%2Ffile'
encodeURIComponent('2024-01-01T00:00Z'); // '2024-01-01T00%3A00Z'encodeURI — encode a full URL
Use this when you have a complete URL and want to encode only the characters that are not allowed. It preserves structural characters like :// ? & = # /.
encodeURI('https://example.com/path with spaces?q=hello world');
// → 'https://example.com/path%20with%20spaces?q=hello%20world'
// Note: & = ? : // are preservedBuilding query strings correctly
// Bad — manually concatenating is error-prone
const url = `/search?q=${query}&page=${page}`;
// Good — use URLSearchParams
const params = new URLSearchParams({ q: query, page, sort: 'desc' });
const url = `/search?${params.toString()}`;
// URLSearchParams handles all encoding automaticallyNode.js: URL and URLSearchParams
import { URL } from 'url';
const base = new URL('https://api.example.com/search');
base.searchParams.set('q', 'cron expression & scheduler');
base.searchParams.set('lang', 'en');
console.log(base.toString());
// https://api.example.com/search?q=cron+expression+%26+scheduler&lang=enDecoding — when to use decodeURIComponent
// Reading a query param from a URL
const raw = new URL(window.location.href).searchParams.get('q');
// URLSearchParams decodes automatically — no manual decode needed
// But if you have a raw encoded string:
decodeURIComponent('hello%20world'); // 'hello world'
decodeURIComponent('%E0%A4%A8%E0%A4%AE%E0%A4%B8%E0%A5%8D%E0%A4%A4%E0%A5%87'); // 'नमस्ते'Common mistakes
- Double-encoding: calling
encodeURIComponenton an already-encoded string produces%2520instead of%20. - Using
encodeURIfor query param values — it won't encode&and=, breaking the query string. - Forgetting to encode redirect URLs passed as query parameters — the embedded URL's
?and&will corrupt the outer URL. - Not encoding file names in download URLs — spaces and brackets in filenames cause broken links in some browsers.
Frequently Asked Questions
encodeURIComponent encodes a single value for use inside a URL — it escapes characters like &, =, and / that would otherwise be read as URL structure. encodeURI encodes a complete URL and leaves structural characters like :// ? & = # intact. Using encodeURI on a query parameter value is a common bug, since it will not escape & or =.
You get double-encoding: the % from the first encoding pass gets encoded again into %25, turning a correct %20 into %2520. This is one of the most common URL encoding bugs, usually caused by encoding a value both on the client and again on the server, or by a framework that encodes automatically.
No, in most cases. URLSearchParams decodes values automatically when you read them, so calling decodeURIComponent on top of that will decode the value twice. Reach for decodeURIComponent directly only when you have a raw percent-encoded string that did not come through URLSearchParams.
Encode or decode any URL instantly
Use our free URL Encoder / Decoder to percent-encode or decode any string in your browser. Supports both encodeURIComponent and encodeURI modes. No data is uploaded.