URL Encoder / Decoder

Encode and decode URLs and query parameter values with correct percent-encoding.

URL Encode and Decode Online: Percent-Encoding for Query Strings and Full URLs

Choose Encode or Decode and paste your text; this URL encoder and decoder updates the result as you type. When encoding, pick what you are encoding: a single query value or path segment, which escapes every reserved character, or a complete URL, which keeps `:`, `/`, `?`, `&` and `=` so the address still works. When decoding, tick Treat + as space for data from HTML forms. Everything runs in your browser, so URLs containing tokens or personal data are not sent anywhere.

What URL encoding is

URLs may only contain a limited set of ASCII characters. RFC 3986 defines the unreserved characters, A–Z, a–z, 0–9, -, ., _ and ~, which never need encoding. Everything else is written as percent-encoding: each byte becomes % followed by two hexadecimal digits. Non-ASCII text is first converted to UTF-8 bytes, so one character can become several escapes.

space      %20
&          %26
=          %3D
/          %2F
é          %C3%A9          (two UTF-8 bytes)
😀         %F0%9F%98%80    (four UTF-8 bytes)

Reserved characters such as /, ?, #, & and = have a structural meaning in a URL. They must be encoded when they are part of data, for example an & inside a search term, and left alone when they separate the parts of the URL. That distinction is why there are two encode modes.

Encoding a value versus a whole URL

Query value / path segment uses JavaScript's encodeURIComponent. It escapes everything except letters, digits and - _ . ! ~ * ' ( ), which is what you want for a single parameter value: a search term, a redirect URL passed as a parameter, or a file name in a path.

Full URL uses encodeURI, which leaves the characters that give a URL its structure untouched and only escapes spaces, non-ASCII characters and a few others. Use it to clean up a complete address with spaces or accented letters, never to encode a value that will be inserted into another URL.

encodeURIComponent('a b&c=d/é?😀')
// 'a%20b%26c%3Dd%2F%C3%A9%3F%F0%9F%98%80'

encodeURI('https://example.com/a b?q=café&x=1#top')
// 'https://example.com/a%20b?q=caf%C3%A9&x=1#top'

The classic bug is building a query string by concatenation with encodeURI or with no encoding at all. A value containing & then splits into two parameters, and a value containing # cuts off the rest of the URL. Encode each value separately, or let URLSearchParams do it.

Space as %20 or +

Both appear in the wild. In a URL path, a space must be %20. In query strings submitted by HTML forms, the application/x-www-form-urlencoded format writes a space as +, and URLSearchParams in JavaScript, PHP's urlencode and Python's quote_plus follow that convention.

decodeURIComponent does not turn + into a space, because in a generic URL a + is a literal plus. When you decode form data or a query string produced by a form, tick Treat + as space. When you decode a value that may contain a real plus sign, such as a phone number or a Base64 string, leave it unticked.

new URLSearchParams({ q: 'a b&c' }).toString()   // 'q=a+b%26c'
urlencode('a b/é')      // PHP: 'a+b%2F%C3%A9'
rawurlencode('a b/é')   // PHP: 'a%20b%2F%C3%A9'

Decoding errors and double encoding

Decoding fails with URIError: URI malformed when a % is not followed by two hex digits, or when the escapes do not form valid UTF-8, for example a truncated %E0%A4%A. A literal percent sign in data must itself be encoded as %25.

Double encoding happens when already encoded text is encoded again: %20 becomes %2520, because the % is encoded as %25. If a decoded result still contains %20 or %3D, decode once more, and then find the place in your code that encodes twice, usually a framework that encodes parameters automatically after you already did.

URL encoding in code

# Python
from urllib.parse import quote, quote_plus, unquote, urlencode
quote('a b/é')             # 'a%20b/%C3%A9'   note: '/' is kept by default
quote('a b/é', safe='')    # 'a%20b%2F%C3%A9'
quote_plus('a b/é')        # 'a+b%2F%C3%A9'
urlencode({'q': 'a b', 'page': 2})   # 'q=a+b&page=2'

# Shell
curl -G https://api.example.com/search --data-urlencode 'q=café & bar'

Python's quote keeps / unless you pass safe='', which surprises people encoding a value that contains a slash. In JavaScript, new URL() and url.searchParams.set() handle encoding for you and are the safest way to build URLs.

Where URL encoding matters

Redirect and callback URLs passed as parameters, such as ?redirect= or OAuth redirect_uri, must be fully encoded or the inner URL's own query string leaks into the outer one. UTM campaign parameters with spaces or ampersands in campaign names need encoding. API calls with search terms, file names in download links and email mailto: links with a subject and body all rely on it. Paste any of them into the decoder to see what the server will actually receive.

Frequently asked questions

How do I decode a URL?

Select Decode and paste the encoded text. Percent escapes such as %20 and %C3%A9 are converted back to characters. Tick Treat + as space if the text comes from an HTML form.

What is the difference between encodeURI and encodeURIComponent?

encodeURIComponent escapes all reserved characters and is for single values. encodeURI keeps characters like :, /, ?, & and = so a complete URL still works, and must not be used for values inside a URL.

Why is a space encoded as + instead of %20?

HTML forms use the application/x-www-form-urlencoded format, where a space is +. In URL paths and generic encoding a space is %20. Both decode to a space in query strings from forms.

What does %2520 mean?

The text was encoded twice: %20 (a space) had its % encoded again as %25. Decode twice to recover the original, and fix the code that encodes twice.

Why do I get URI malformed?

A % is not followed by two hex digits, or the escapes are not valid UTF-8, often because the string was cut short. A literal % in data must be written as %25.

Is URL encoding encryption?

No. It only makes text safe to put in a URL, and anyone can decode it. Never rely on it to hide tokens or personal data.