URL encode and decode

Percent-encode or decode text for a URL. Choose whether you're working with a whole URL, a single component such as a query value, or a form field — each one escapes a different set of characters. Everything happens in this page — nothing you type is ever sent anywhere, and this tool makes no network requests after it loads.

Options

Text to encode empty
Percent-encoded output empty

About this tool

Encode mode turns plain text into percent-encoded text. Decode mode does the reverse. The result depends on which of the three targets is selected, because each one is built for a different job and escapes a different set of characters — using the wrong one is the single most common URL-encoding mistake.

Full URL is for a string that is already a complete, structurally valid URL — it leaves the characters that give a URL its structure (: / ? # @ ! $ & ' ( ) * + , ; =) alone, and only escapes what would otherwise break it, such as a space. Note that square brackets are not in that set: encodeURI escapes [ and ] to %5B and %5D, which catches people out when an IPv6 host is involved. URL component is for a single value that is going into a URL — a query parameter, a path segment — so it escapes those structural characters too, since a raw & or / inside a value would otherwise be misread as part of the URL's structure. Form field matches what a browser actually sends when an HTML form is submitted: spaces become + rather than %20, and a few characters URL component leaves alone (! ~ ' ( )) are escaped as well.

"Swap direction" takes whatever is currently in the output box, puts it back in as input, and flips the mode — useful for checking a round trip.

How it works

Full URL and URL component use the browser's own encodeURI/decodeURI and encodeURIComponent/decodeURIComponent — the same approach as elsewhere on this site, favouring a correct native API over a hand-written one. Form field has no direct native encode/decode function, but the browser's URLSearchParams implements the exact algorithm a form submission uses, so this page uses that rather than reimplementing the percent-encoding rules by hand.

Which characters change, and which don't

Most URL-encoding questions are really one question about one character: does a dash need escaping, what does a comma turn into, why has a plus sign become a space. The table below answers that for every ASCII punctuation mark, in all three targets at once.

Every value in it was generated by running the browser's own encodeURI, encodeURIComponent and URLSearchParams — the same functions this page uses — rather than transcribed from a specification. Letters, digits, and anything not listed behaves like the group it would fall into; non-ASCII characters are shown at the bottom, because they encode as UTF-8 bytes and so take more than one percent sequence each.

CharacterFull URLURL componentForm field
Never escaped, whichever target you pick
- hyphen, often written dash - - -
_ underscore _ _ _
. full stop . . .
* asterisk * * *
Escaped by form field only
~ tilde ~ ~ %7E
! exclamation mark ! ! %21
' apostrophe ' ' %27
( opening parenthesis ( ( %28
) closing parenthesis ) ) %29
Kept by full URL, escaped by URL component and form field
, comma , %2C %2C
+ plus sign + %2B %2B
/ slash / %2F %2F
? question mark ? %3F %3F
# hash # %23 %23
& ampersand & %26 %26
= equals sign = %3D %3D
: colon : %3A %3A
; semicolon ; %3B %3B
@ at sign @ %40 %40
$ dollar sign $ %24 %24
Escaped by all three
space space %20 %20 +
% percent sign %25 %25 %25
[ opening square bracket %5B %5B %5B
] closing square bracket %5D %5D %5D
" double quote %22 %22 %22
< less than %3C %3C %3C
> greater than %3E %3E %3E
{ opening brace %7B %7B %7B
} closing brace %7D %7D %7D
| pipe %7C %7C %7C
\ backslash %5C %5C %5C
^ caret %5E %5E %5E
` backtick %60 %60 %60
£ pound sign %C2%A3 %C2%A3 %C2%A3
é e-acute %C3%A9 %C3%A9 %C3%A9

Two rows catch people out more than the rest. A plus sign is left alone by full URL but becomes %2B in the other two — and in the opposite direction, a literal + in a query string decodes back to a space under form-field rules, which is why a value that looked fine in the address bar can arrive at the server with spaces where the plus signs were. A space encodes to %20 in the first two targets but to + in form field, for the same reason.

Common questions

Does a dash or hyphen need URL encoding?

No. A hyphen is one of the unreserved characters, so none of the three targets touch it — - stays - whether you encode a full URL, a URL component or a form field. The same is true of the underscore, the full stop and the tilde in the first two targets. If you are seeing %2D somewhere, something has over-encoded on purpose or run an encoder twice; it will still decode correctly, but it is not what any of the standard functions produce.

What does a comma encode to?

%2C, but only in URL component and form field. Full URL leaves a comma alone, because a comma is a reserved character that some URL schemes use structurally. That difference is why the same comma can survive one encoder untouched and come out as %2C from another — neither is wrong, they are answering different questions.

Why has a plus sign in my URL turned into a space?

Because something decoded it with form-field rules. In application/x-www-form-urlencoded a space is written as +, so decoding runs that backwards and turns every literal + into a space. If the plus was meant literally — in a phone number, a search term, a base64 string — it has to be sent as %2B. Encoding it with URL component or form field on this page does exactly that.

Do parentheses need encoding?

Only for form fields. Full URL and URL component both leave ( and ) as they are; form field escapes them to %28 and %29, along with !, ~ and '. All four are legal unencoded in a URL, so a link with bare parentheses in it is valid — the trouble is usually that some other piece of software has guessed where the link ends, not that the URL is malformed.

What's the difference between a full URL and a URL component?

A full URL already has structure — scheme, host, path, query — built from characters like /, ?, & and =. Encoding it as a whole must leave those alone or it stops being a valid URL. A component is a single piece of data — the value of one query parameter, say — that is going to be placed inside that structure, so anything that could be mistaken for structure has to be escaped first. Encoding a whole URL with the component setting will wrongly escape its own :// and ?.

Why does form field encode differently from URL component?

application/x-www-form-urlencoded — the format an HTML form submits with the default encoding — predates encodeURIComponent and follows its own rule set: a space becomes + instead of %20, and ! ~ ' ( ) get escaped even though URL component leaves them as-is. Decoding form field data with the wrong setting will leave literal + characters in the result instead of turning them back into spaces.

Why did decoding leave some %XX sequences unchanged?

Only with Full URL selected, and only by design. decodeURI deliberately does not unescape a percent sequence that represents one of the characters reserved for URL structure (; / ? : @ & = + $ , #) — if it did, a literal encoded slash inside a path segment could be mistaken for a path separator after decoding. Switch to URL component to decode those too.

Is my text sent anywhere to encode or decode it?

No. Everything happens in your browser. There is no fetch, no beacon and no logging, and this page carries no third-party scripts.

When encoding or decoding goes wrong

"A % is not followed by two hex digits"

A percent sign in percent-encoded text must always be followed by exactly two hexadecimal characters (0–9, A–F). A lone %, or one followed by fewer than two hex digits, usually means the text was copied incompletely — check the position given against the source.

"Not a valid UTF-8 byte sequence"

Only shown for Full URL and URL component. Multi-byte characters — accents, symbols, most non-Latin scripts, emoji — are encoded as several linked %XX groups that must all be present and in order. This error means one of those groups is missing or out of place, almost always because the text was cut short somewhere in the middle of a character.

Form field decode didn't report an error, but the result looks wrong

That's expected, not a bug in this tool. The application/x-www-form-urlencoded format — the one a real HTML form submits — is defined to treat a malformed % sequence as a literal, unchanged % rather than fail, because that's what browsers actually do with it. Switch to URL component to get a strict check instead.

The same job at the command line

More tools

See the whole toolbox — thirty-seven free tools planned, all running in your browser.