URL Encoder and Decoder
Percent-encode text, query values or whole links, or decode them back to plain text. Six encoding modes, UTF-8 or Latin-1, double-encoding detection, a URL parts table and a query string to JSON converter. Nothing leaves your browser.
- Free, no sign-up
- Encode and decode
- Six encoding modes
- UTF-8 or Latin-1
- Double-encoding detection
- Nothing sent
People also use
How to encode or decode a URL in three steps
Type or paste text in the left box and the percent-encoded result appears on the right as you type. Choose Encode or Decode at the top, pick what to encode, and press Copy. ⇄ Swap moves the result back into the input and flips the mode, which is the quickest way to check that a value survives a round trip.
Most of the time you only need to url encode one value, such as a search term, a name or a redirect address, before you put it into a link. Keep the default Component mode for that. The other modes cover whole addresses, HTML forms, strict RFC 3986 output, every character, or only the characters that would break a link.
When you paste a full link, the page also breaks it into protocol, host, port, path and fragment, and lists each query parameter decoded. Below the main boxes are a Query string ⇄ JSON converter and a table of common codes. Everything runs in your browser, and nothing you type is sent anywhere.
- 1
Choose Encode or Decode
Pick the mode at the top. In Encode mode, choose what to encode: Component, Full URL, Form, RFC 3986, All characters or Only special. Leave the character set on UTF-8 unless an old system needs ISO-8859-1.
- 2
Type or paste
Put your text, value or link in the left box. The result updates as you type. Tick Each line separately to process a list of values, one per line.
- 3
Copy or swap
Press Copy to take the result, or ⇄ Swap to move it back into the input and switch between Encode and Decode.
The page remembers your choices, such as the mode, the encoding mode, the character set and the decode options, in this browser for next time. The text you type is never saved.
What percent-encoding is: reserved and unreserved characters
A URL can only contain a small set of characters, and some of them have a job. The ? starts the query, & separates parameters, = joins a name to its value, # starts the fragment and / separates path segments. If a value you want to send contains one of these, or a space, an accented letter or an emoji, it has to be written in a safe form first.
That safe form is percent-encoding, defined in RFC 3986. Each byte of a character is written as a % sign followed by two hexadecimal digits. A space is byte 32, hex 20, so it becomes %20. An ampersand is %26, and the % sign itself becomes %25 so it is not mistaken for the start of an escape. Characters outside plain ASCII are first turned into bytes with UTF-8, and each byte gets its own %XX.
RFC 3986 sorts characters into groups. Unreserved characters, the letters A to Z and a to z, the digits 0 to 9 and - . _ ~, never need encoding. Reserved characters have a special meaning in some part of a URL, so they must be encoded when they are part of the data rather than the structure. Everything else, including spaces, quotes, < > and all non-ASCII text, is always encoded.
| Group | Characters | When to encode |
|---|---|---|
| Unreserved | A–Z a–z 0–9 - . _ ~ | Never; they are safe everywhere |
| Reserved (gen-delims) | : / ? # [ ] @ | When they are data, not URL structure |
| Reserved (sub-delims) | ! $ & ' ( ) * + , ; = | When they are data, for example inside a query value |
| Everything else | space " < > % { } | \ ^ ` and non-ASCII | Always |
URL encode online: type, paste, copy
A tool to url encode online should not need a button, an account or a server, and this one does not. The result fills in while you type, the Copy button puts it on the clipboard, and a small counter shows how the length changes, for example 12 → 18 characters, which helps when a field or a link has a length limit.
Pasted something that already contains %XX codes while in Encode mode? A hint says This already looks URL-encoded, with a link to decode it instead. Encoding it again would turn every % into %25, a common cause of broken links.
Tick Each line separately to process many values at once. Every line is encoded or decoded on its own and the line breaks stay as they are, so a column of names or links pasted from a spreadsheet comes back as a clean column you can paste back.
Six ways to encode: which mode to choose
Component is the default and the one to use for a single piece of a URL: one query value, one path segment, or a whole URL that you pass as a parameter inside another URL. It works like JavaScript's encodeURIComponent, so & = ? / # are all encoded.
Full URL is for a complete address that you want to make safe without changing its structure. Like encodeURI, it keeps : / ? & = # and the other reserved characters, and encodes spaces and non-ASCII letters. Unlike encodeURI, it leaves existing %XX sequences alone, so a link that is already partly encoded is not encoded twice.
Form follows application/x-www-form-urlencoded, the format browsers use when they submit a form: spaces become + and everything except letters, digits and - . _ ~ is encoded. RFC 3986 is the strict version of the same rule with %20 for spaces, the format many API signing schemes, such as OAuth 1.0, expect.
Here is how each mode handles the same short sample, a b&c/é!, with UTF-8:
| Mode | What stays as it is | Result for a b&c/é! |
|---|---|---|
| Component | Letters, digits and - . _ ~ ! ' ( ) * | a%20b%26c%2F%C3%A9! |
| Full URL | Unreserved and reserved characters, and existing %XX | a%20b&c/%C3%A9! |
| Form | Letters, digits and - . _ ~; spaces become + | a+b%26c%2F%C3%A9%21 |
| RFC 3986 | Letters, digits and - . _ ~ | a%20b%26c%2F%C3%A9%21 |
| All characters | Nothing | %61%20%62%26%63%2F%C3%A9%21 |
| Only special | Printable ASCII except % & = ? # + " < > \ ^ ` { | } | a%20b%26c/%C3%A9! |
URL decode online: plus signs, broken codes and layers
Switch the mode to Decode to url decode online. Every %XX sequence is turned back into its byte, and the bytes are read as UTF-8 text, so %C3%A9 becomes é and %F0%9F%98%80 becomes 😀.
Treat + as a space is on by default, because form data and most query strings use + for spaces. Turn it off when you decode a path or a value where a plus sign is a real plus, such as a phone number like +44 or a Base64 string.
Broken sequences do not stop the decoder. A lone % or one followed by non-hex characters, as in 100% or %ZZ, is left exactly as it is, and a note counts how many broken or non-UTF-8 sequences were found. If accented letters come out as odd symbols, the text was probably encoded with ISO-8859-1; switch the character set and decode again.
When text has been encoded more than once, the page tells you how many layers it found, for example Encoded 2 times (double encoding), with a Decode all layers button. You can also tick Decode repeatedly, which keeps decoding, up to five times, until no %XX codes are left. The layer count is shown when you decode the text as one block, not with Each line separately.
URL encode space: %20 or +?
There are two ways to write a space, and both are correct in the right place. In the path of a URL, a space must be %20. In a query string sent by an HTML form, the format application/x-www-form-urlencoded uses + for a space, and most servers also accept %20 there.
So when you url encode space characters, the safest choice is %20: it means a space everywhere. A + only means a space in query strings and form bodies; in a path, /a+b really is a plus sign. Choose Form when a system specifically wants plus signs, and any other mode for %20.
The reverse problem is common too. A real plus sign in a value, such as C++ or an international phone number, must be sent as %2B. If it is sent as a bare +, the server reads it as a space. Every mode here except Full URL encodes a plus sign as %2B.
URL encode all characters: every byte as %XX
All characters mode encodes everything, even letters and digits, so hello becomes %68%65%6C%6C%6F. A browser decodes it to the same text, because %68 and h mean the same thing in a URL.
Why url encode all characters? It is useful for tests, to check that a server decodes every escape correctly, for teaching how bytes map to hex, and when a system requires a fully escaped value. It is not a way to hide anything: anyone can decode it in a second, so it is not encryption or security.
Output grows quickly. Each ASCII character becomes three characters, and each non-ASCII character becomes six to twelve. Watch the length counter under the result if a field has a limit.
URL encode only special characters: readable output
Only special encodes the minimum: spaces, control characters, non-ASCII letters and the characters that break or change a URL, which are % & = ? # + " < > \ ^ ` { | }. Letters, digits and other punctuation such as / : @ ! stay as they are.
Use it when you want to url encode only special characters and keep the result readable, for example a file path with spaces like /docs/My Report.pdf, which becomes /docs/My%20Report.pdf, or a title with accents in a link you will read later. It suits logs, documentation and links people will look at.
Because it keeps / and :, it is not the right mode for a value that will sit inside another URL, such as a redirect parameter. Use Component for that, so the inner address cannot be confused with the outer one.
encodeURIComponent vs encodeURI in JavaScript
JavaScript has two built-in functions, and mixing them up is a classic bug. encodeURIComponent encodes everything except letters, digits and - _ . ! ~ * ' ( ). Use it for any single value: a query parameter, a path segment or a URL you put inside another URL. It matches the Component mode.
encodeURI keeps the characters that give a URL its structure, ; , / ? : @ & = + $ #, and encodes the rest. Use it only for a whole address that may contain spaces or non-ASCII letters. If you use it on a value, an & or = inside that value stays raw and splits your query string in the wrong place. The Full URL mode is similar, but it also leaves existing %XX codes untouched.
To decode, use decodeURIComponent, which turns every %XX back into text but leaves + as it is. It throws a URIError on a broken sequence such as a lone %, which is why this page decodes tolerantly instead. For form data, replace + with a space first, or use URLSearchParams, which reads + as a space and builds query strings with + for spaces, like the Form mode here.
URL encode string values in Python, PHP, Java and C#
Every language can url encode string values, but the defaults differ, and that is where most mismatches come from. The main question is always the same: does the function write a space as %20 or as +, and which punctuation does it leave alone?
In Python, urllib.parse.quote keeps / by default, because it was written for paths; pass safe='' to encode / as well, for a query value. urllib.parse.urlencode turns a whole dict into a query string, with + for spaces. In PHP, rawurlencode follows RFC 3986 with %20, while urlencode uses + like a form.
In Java, URLEncoder is a form encoder, despite its name: it writes spaces as + and also encodes ~. Since Java 10 you can pass StandardCharsets.UTF_8 directly; on older versions, pass "UTF-8". In C#, Uri.EscapeDataString gives RFC 3986 output with %20, and WebUtility.UrlEncode gives + for spaces.
To compare your code with this page, use RFC 3986 mode for rawurlencode, quote(s, safe='') and Uri.EscapeDataString, Component for encodeURIComponent, and Form for quote_plus. PHP urlencode, Java URLEncoder and WebUtility.UrlEncode also match Form, apart from small differences in characters such as ~ and *.
| Language | Encode (%20 for spaces) | Form style (+ for spaces) | Decode |
|---|---|---|---|
| JavaScript | encodeURIComponent(s) | new URLSearchParams({ q: s }).toString() | decodeURIComponent(s) |
| Python | urllib.parse.quote(s, safe='') | urllib.parse.quote_plus(s) | unquote(s) / unquote_plus(s) |
| PHP | rawurlencode($s) | urlencode($s) | rawurldecode($s) / urldecode($s) |
| Java | URLEncoder.encode(s, StandardCharsets.UTF_8).replace("+", "%20") | URLEncoder.encode(s, StandardCharsets.UTF_8) | URLDecoder.decode(s, StandardCharsets.UTF_8) |
| C# | Uri.EscapeDataString(s) | WebUtility.UrlEncode(s) | Uri.UnescapeDataString(s) / WebUtility.UrlDecode(s) |
UTF-8 and Latin-1: why é becomes %C3%A9
Percent-encoding works on bytes, not letters, so a character first has to be turned into bytes. Today that means UTF-8, the encoding modern web standards require. Plain ASCII letters take one byte. Accented Latin letters and Greek, Cyrillic, Arabic and Hebrew letters take two. Chinese, Japanese and Hindi take three, and emoji take four.
That is why one character can turn into a long code: é becomes %C3%A9 and 😀 becomes %F0%9F%98%80. Decoding reverses it, and the decoder must use the same character set. If é was encoded as UTF-8 and decoded as Latin-1, you get é, the typical sign of a mix-up.
Some older systems still use ISO-8859-1 (Latin-1), where é is the single byte %E9. Choose ISO-8859-1 (Latin-1) under Character set to encode or decode that way. Latin-1 only covers 256 characters, so characters outside it, such as € or emoji, cannot be represented; this page writes them as %FF. Stay on UTF-8 unless you know the receiving system needs Latin-1.
| Character | UTF-8 bytes | Encoded (UTF-8) | Encoded (ISO-8859-1) |
|---|---|---|---|
| A | 1 | A (or %41) | A (or %41) |
| é | 2 | %C3%A9 | %E9 |
| ß | 2 | %C3%9F | %DF |
| € | 3 | %E2%82%AC | Not in Latin-1 |
| 中 | 3 | %E4%B8%AD | Not in Latin-1 |
| 😀 | 4 | %F0%9F%98%80 | Not in Latin-1 |
Double encoding: when %20 turns into %2520
Double encoding happens when text that is already encoded is encoded again. The % of %20 becomes %25, so the space ends up as %2520. Decode it once and you get %20, not a space. On a web page this shows up as a literal %20 or %2520 in a file name, a search box or an email subject.
It usually comes from two layers of code each doing their job: a form encodes a value, then a library encodes the whole link again, or a redirect URL is encoded once by your code and once by the framework. Fix it by encoding exactly once, at the moment you build the URL, and decoding exactly once when you read it.
Sometimes several layers are correct. A link inside the redirect parameter of another link, which itself sits inside a third link, needs one layer per level. In that case decode one layer at a time with Decode repeatedly turned off, and check each step.
This page helps from both sides. In Encode mode, a hint warns when the input already looks encoded. In Decode mode, the layer count shows how many times the text was encoded, and Decode all layers removes them in one go.
URL decoder for whole links: the URL parts table
Paste a full link, starting with https:// or another scheme, or with www., and a URL parts card appears under the boxes. In Decode mode it uses the decoded result. It shows the protocol, the host, the port, or (default) when none is given, the path with each segment decoded, and the fragment after #.
Below that, every query parameter is listed with its name and its decoded value, in the order they appear, repeated names included. This makes the page a handy url decoder for long tracking links, redirect chains and API calls: you can see at a glance what utm_source, a redirect_uri or a search term really says.
Copy parameters as JSON copies the same parameters as a JSON object. A name that appears more than once, such as tag=a&tag=b, becomes an array, so nothing is lost.
URL decode to JSON: query strings and back
The Query string ⇄ JSON card converts in both directions. Paste a query string such as q=hello%20world&page=2&tag=a&tag=b, or a whole link with a ? in it, and press Convert. You get a JSON object with each value decoded: {"q": "hello world", "page": "2", "tag": ["a", "b"]}. Repeated names become arrays and the fragment after # is ignored.
Values are always strings in this direction, because a query string has no types; 2 comes back as "2". That is how a server sees the data too, so a url decode to json step is a quick way to check what an API call actually sends.
Paste a JSON object instead, starting with {, and Convert builds the query string. Arrays become repeated names, null becomes an empty value, nested objects are written as JSON text, and spaces become +, as in a form. If the JSON is not valid, the card says Not valid JSON.
URL encode and decode in everyday work
The need to url encode and decode values comes up in many everyday jobs, not only in programming:
Search and share links
Put a search term, a name or a title with spaces, & or accents into a link without breaking it.
Redirect and callback URLs
Encode a full return address with Component before you add it as a redirect_uri or next parameter.
API requests
Build query strings for REST calls, and check what an existing call really sends.
Read tracking links
Paste a long marketing link and read every utm_ parameter, decoded, in the URL parts card.
Debug broken links
Find a stray %2520, an unencoded & or a + that should have been %2B.
Email and mailto links
Encode the subject and body of a mailto: link so spaces and line breaks survive; a new line is %0A.
Logs and analytics
Decode request paths and query strings from server logs to read them as plain text.
Spreadsheets and lists
Encode or decode a whole column at once with Each line separately.
URL encoder troubleshooting: common problems
A url encoder is simple in principle, but small details, such as a plus sign or a second layer of encoding, cause most broken links. Here are the usual problems and their fixes:
A + in my value became a space
The receiver treats + as a space in query strings. Encode the value with any mode except Full URL, so + is sent as %2B.
I see %2520 or a literal %20
The text was encoded twice. Encode once only; to clean up existing text, decode it with Decode repeatedly.
Accented letters look like é
The text was encoded in one character set and decoded in another. Try ISO-8859-1 (Latin-1) under Character set, or UTF-8 if you were on Latin-1.
Broken sequences were left as is
The input contains a % that is not followed by two hex digits, such as 50% off, or bytes that are not valid UTF-8. The rest is decoded normally.
My query string split in the wrong place
A value contained & or = and was not encoded, or was encoded with Full URL mode. Use Component for single values.
The URL parts card does not appear
It only shows for text that starts with a scheme such as https:// or with www. A bare domain or a path on its own is not parsed.
The result differs from my code
Check how your function writes spaces and which punctuation it keeps, then compare with RFC 3986, Component or Form mode as shown in the code table.
Copy does not work
Some browsers block the clipboard in private windows. Click in the result box, select all and copy with Ctrl+C, or Cmd+C on a Mac.
All settings at a glance
| Setting | Choices | What it does |
|---|---|---|
| Mode | Encode, Decode | Percent-encode text, or turn %XX codes back into text |
| What to encode | Component, Full URL, Form, RFC 3986, All characters, Only special | Which characters stay as they are, and whether spaces become %20 or + |
| Character set | UTF-8, ISO-8859-1 (Latin-1) | How characters become bytes, and bytes become characters again |
| Each line separately | On or off | Encode or decode every line on its own, keeping the line breaks |
| Treat + as a space | On (default) or off | In Decode mode, read + as a space, as in forms and query strings |
| Decode repeatedly | On or off (default) | In Decode mode, keep decoding, up to five times, until no %XX is left |
| ⇄ Swap | Button | Move the result into the input and switch between Encode and Decode |
Is it safe? Encoded in your browser, nothing sent
Everything on this page runs in your browser. The text, links and query strings you paste are not uploaded, not logged and not added to the address bar. That matters, because real links often contain session tokens, email addresses, API keys or private search terms.
The page remembers only your settings, such as the mode, the encoding mode, the character set and the decode options, in this browser's local storage. The text itself is never saved. You can clear the stored settings in your browser's site data settings.
Remember that percent-encoding is not encryption. Anyone who sees an encoded link can decode it, so never rely on it to hide a password or a token.
What to do next
Percent-encoding is one of several text encodings you meet on the web. For binary data inside text, such as an image or a token, use the Base64 tool. A JWT from a login link can be read with the JWT Decoder, and a Unix time in a query parameter with the Timestamp Converter.
Got JSON from the query string converter? The JSON Formatter makes it readable, and JSON to CSV turns a list of records into a spreadsheet. To compare a link before and after a change, paste both into the Diff Checker. Once a link is ready to share on paper or a screen, the QR Code Generator turns it into a code a phone can scan.
Frequently asked questions
How do I url encode online without installing anything?
Type or paste your text in the left box above; the encoded result appears on the right as you type. Keep Component mode for a single value, then press Copy. It works in any modern browser, and nothing is sent to a server.
How do I url decode online?
Switch the mode to Decode and paste the encoded text. Every %XX code is turned back into text, + is read as a space unless you turn that off, and broken sequences are left as they are instead of causing an error.
What does it mean to url encode and decode text?
Encoding replaces characters that are not allowed, or that have a special meaning in a URL, with a % sign and two hex digits per byte, such as %20 for a space. Decoding turns those codes back into the original text. Both are needed whenever data travels inside a link.
Can I use it as a url decoder for long links with many parameters?
Yes. Paste the whole link in Decode mode and the URL parts card lists the protocol, host, port, path and fragment, plus every query parameter with its decoded value. Copy parameters as JSON copies them as an object.
Which url encoder mode should I choose?
Use Component for one value or path part, Full URL for a whole address you want to keep working, Form when a system wants + for spaces, and RFC 3986 for strict API signing. All characters and Only special are for tests and for readable output.
How do I url encode space characters, as %20 or +?
Use %20 when in doubt; it means a space in every part of a URL. A + only means a space in query strings and form data. Choose Form mode to get +, or any other mode to get %20.
Why would I url encode all characters?
All characters mode turns every character, including letters and digits, into %XX. It is useful for testing that a server decodes correctly, for learning how bytes map to hex, or for systems that demand fully escaped values. It does not hide anything, because anyone can decode it.
How do I url encode only special characters and keep the text readable?
Choose Only special. It encodes spaces, control characters, non-ASCII letters and the characters that change a URL's meaning, such as % & = ? # and +. Letters, digits and other punctuation such as / and : stay as they are.
Can I url decode to JSON?
Yes. Paste a query string or a full link into the Query string ⇄ JSON card and press Convert. Each parameter becomes a key with its decoded value, and repeated names become arrays. Paste JSON instead to build a query string.
How do I url encode string values in Python or PHP?
In Python, use urllib.parse.quote(s, safe='') for output with %20, or quote_plus for + as the space. In PHP, rawurlencode gives RFC 3986 output with %20, while urlencode uses + like a form.
What is the difference between encodeURIComponent and encodeURI?
encodeURIComponent encodes everything except letters, digits and - _ . ! ~ * ' ( ), so use it for single values. encodeURI keeps the characters that give a URL its structure, such as / ? & = #, so use it only for a whole address. Using encodeURI on a value is a common bug.
What is percent-encoding?
It is the URL encoding defined in RFC 3986. Each byte of a character is written as % followed by two hexadecimal digits. Non-ASCII characters are first turned into UTF-8 bytes, so é becomes %C3%A9.
Which characters never need encoding?
The unreserved characters: letters A to Z and a to z, digits 0 to 9, and - . _ ~. Reserved characters such as / ? # & = + need encoding when they are part of the data, and everything else is always encoded.
What is %2520?
It is a double-encoded space. The space became %20, then the % was encoded again as %25. Decode with Decode repeatedly turned on, or press Decode all layers, to get the plain text back, and make sure your code encodes only once.
Why does a plus sign in my value turn into a space?
In query strings and form data, + means a space. A real plus sign must be sent as %2B. Every mode on this page except Full URL encodes + as %2B.
Why do accented letters look wrong after decoding?
The text was probably encoded in a different character set. Text encoded as ISO-8859-1 is not valid UTF-8, and UTF-8 read as Latin-1 shows things like é. Switch the Character set and decode again.
What happens to a broken % sequence?
It is left exactly as it is, for example the lone % in 50% off. A note under the result counts how many broken or non-UTF-8 sequences were found, and the rest is decoded normally.
Can I encode or decode many values at once?
Yes. Tick Each line separately and paste one value per line. Each line is processed on its own and the line breaks are kept, which suits a column copied from a spreadsheet.
Is percent-encoding the same as encryption?
No. Percent-encoding only makes text safe to put in a link, and anyone can decode it. Never use it to protect a password, a token or any other secret.
How do I encode a URL in Java or C#?
In Java, URLEncoder.encode(s, StandardCharsets.UTF_8) gives form-style output with + for spaces; replace + with %20 if you need %20. In C#, Uri.EscapeDataString gives RFC 3986 output with %20, and WebUtility.UrlEncode uses +.
Is my text sent anywhere?
No. Encoding, decoding, the URL parts table and the JSON converter all run in your browser. Only your settings are remembered in this browser; the text you type is never saved.
Encode or decode a link now
Six encoding modes, tolerant decoding, URL parts and query string to JSON. Free, private and done on your device.
Back to the toolLast updated October 2026 · Written and maintained by the FlipMyFormat team