The tool you need, ready to use

URL Encoder and Decoder

Paste a URL with % codes into the encoded box and it is decoded into plain text; type text in the plain text box and it is encoded at once with the rule you pick. The URL is split into scheme, host, path and query values, and values from older Windows-1252 sites or encoded twice are recognized. The symbol map and the results by function below show where the same text is encoded differently.

Last updated 2026-10-22All math stays in your browser
Examples

    Symbol map
    Press a symbol to see below how each rule changes it. Move between symbols with the arrow keys.

    Results by language and functionFrom the text box · press to copy

      Last updated 2026-10-22Your inputs are not stored

      ROBERIN standardThe tool you need,
      ready to use.
      • Clear at a glanceInputs and results sit where you expect them.
      • Result firstThe key number comes first; the working only when you need it.
      • Ask lessNo sign-up and no unnecessary details.

      URL encoding writes each unsafe byte as % plus two hex digits

      A URL can carry letters, digits and a small set of symbols as they are. Any other character is first turned into bytes, and each byte is written as % followed by two hexadecimal digits. This is called percent-encoding, or URL encoding. In UTF-8 the letter é takes two bytes, so it becomes %C3%A9, and a space becomes %20 (or + in a form submission). Decoding does the reverse: it turns each %XX back into a byte and reads the bytes as text.

      The same text encodes differently depending on where it goes in a URL. A search term placed in one query value must also have &, =, / and ? encoded, while text that is already a full URL must keep those separators or the link stops working. This tool converts whichever box you edit, splits a URL into its parts and decodes each one, and recognizes values made on older Windows-1252 sites and values that were encoded twice. URL encoding is not encryption: anyone can reverse it.

      When you need to encode or decode a URL

      • A pasted link is full of % codes: a link such as /search?q=caf%C3%A9+near+me is hard to read in a chat or a document. Paste it into the encoded box and the search term and path appear as plain text.
      • Putting a search term or product name into a link: an unencoded 'Tom & Jerry' makes everything after & a separate parameter, and the + in 'C++' is read as a space. Encode it with the Single value rule so it arrives as typed.
      • Passing a return URL after login or checkout: the URL in redirect_uri or returnUrl must be encoded as a whole, or its own ? and & get mixed up with the outer URL.
      • Building an API signature: OAuth 1.0 and AWS Signature Version 4 keep only RFC 3986 unreserved characters and write a space as %20. One different character and the signature check fails.
      • Reading server logs and analytics: request paths and referrer URLs are stored encoded. To see which search term a visit came from, you have to decode it.
      • Old PHP forms and shop pages: pages that were served as Windows-1252 (often declared as ISO-8859-1) encode 'café' as caf%E9, which a UTF-8 decoder cannot read.

      How to use it

      1. Decode: paste a URL or value with % codes into the encoded box on the right. The tool picks a rule from the shape of what you pasted (a URL gets Whole URL, a visible + gets Form +) and the decoded text appears in the plain text box.
      2. Encode: type text in the plain text box and choose the rule that matches where it will go. Use Single value for a query value, file name or redirect target, Whole URL for a complete URL, Form + for the same output as an HTML form, and Strict for signatures.
      3. Read the URL breakdown: when the text is a URL or a query string, the tool splits it into scheme, host, path, query values and fragment and decodes each. If a value contains another URL, 'Decode this URL' opens it. With several lines, it breaks down the line that has the cursor.
      4. Character encoding: the default is auto-detect. When the bytes are not valid UTF-8, the tool reads them as EUC-KR, Shift_JIS or Windows-1252, whichever fits, and says which one it used. To encode for an older site, choose the encoding yourself.
      5. Symbol map and function results: press a symbol to see how the four rules change it and why. The results by language and function show your text run through JavaScript, PHP and Python functions and mark the characters that differ from the current rule. Press a row to copy that result.

      Four rules: what each one keeps

      Each rule keeps a different set of symbols besides letters and digits. When another tool or your code gives a different result, this is almost always the reason.

      Characters each rule keeps, and how it writes a space
      RuleKept (besides letters and digits)SpaceExisting %Used for · equivalent function
      Single value- _ . ! ~ * ' ( )%20Becomes %25Query values, path segments · JavaScript encodeURIComponent()
      Whole URLSeparators : / ? # [ ] @ ! $ & ' ( ) * + , ; = and - . _ ~ (a few differ by position)%20KeptAddress bar, links · the browser's URL Standard
      Form +* - . _+Becomes %25HTML form submission · URLSearchParams, Java URLEncoder
      Strict- . _ ~%20Becomes %25OAuth 1.0, AWS signatures · PHP rawurlencode()

      The four characters Strict keeps are the RFC 3986 unreserved characters, so encoding them or not gives the same URL. Single value also keeps ! ' ( ) * because JavaScript follows the unreserved set of the older RFC 2396; the URL Standard defines this same set separately as its component set.

      The Form + rule matches URLSearchParams. When a browser actually submits an HTML form, line breaks in a multi-line field are sent as %0D%0A, while this tool and URLSearchParams keep them as %0A (measured in Chromium 151).

      Symbol by symbol

      Here are the symbols people confuse most often and how each rule changes them. The Whole URL column shows the query position of an http or https URL. In the symbol map above the tool you can press all 35 symbols.

      One symbol encoded by each rule
      SymbolSingle valueWhole URL (query)Form +StrictencodeURI()
      Space%20%20+%20%20
      &%26&%26%26&
      =%3D=%3D%3D=
      +%2B+%2B%2B+
      /%2F/%2F%2F/
      ?%3F?%3F%3F?
      #%23#%23%23#
      %%25%%25%25%25
      ~~~%7E~~
      ****%2A*
      ''%27%27%27'
      !!!%21%21!
      é%C3%A9%C3%A9%C3%A9%C3%A9%C3%A9

      The Whole URL rule keeps % so that existing %XX codes survive. The cost is that a literal % has to be checked for two hex digits after it, so the tool reports how many such % characters it found. PHP urlencode() is close to the form rule but also changes * to %2A, and Python quote() is the Strict rule plus / kept.

      %20 and +: how a space is read

      Writing a space as + is the rule of HTML form submission (application/x-www-form-urlencoded). In a path, + is simply a plus sign. In a query, it can become a space or stay a plus depending on which function the receiving side uses to decode. Writing a real plus as %2B and a space as %20 gives the same meaning everywhere.

      Results of decoding a+b%20c%2B with each function (checked 2026-10-22)
      FunctionResult+ read as space
      JavaScript decodeURIComponent()a+b c+No
      JavaScript URLSearchParamsa b c+Yes
      PHP urldecode()a b c+Yes
      PHP rawurldecode()a+b c+No
      Python unquote()a+b c+No
      Python unquote_plus()a b c+Yes

      This tool reads + as a space only under the Form + rule. If you decode with Single value or Strict and a + remains, the status line offers a 'Read with Form + rule' button. The Whole URL rule keeps + to protect the structure, and the URL breakdown below decodes query values with the form rule.

      Encoding a whole URL: encodeURI() versus the browser

      encodeURI(), the usual choice for a complete URL, keeps the separators but also encodes % and does not treat the domain specially. A browser address bar follows the URL Standard: it uses a different set for the path, query and fragment, leaves existing %XX alone, and turns an international domain into Punycode. The Whole URL rule of this tool follows the browser.

      The same URL through encodeURI() and the URL Standard (Whole URL rule)
      InputencodeURI()Whole URL (URL Standard)
      https://example.com/a%20bhttps://example.com/a%2520bhttps://example.com/a%20b
      https://bücher.de/https://b%C3%BCcher.de/https://xn--bcher-kva.de/
      https://example.com/?q=[1]https://example.com/?q=%5B1%5Dhttps://example.com/?q=[1]
      https://example.com/?q=it'shttps://example.com/?q=it'shttps://example.com/?q=it%27s
      https://example.com/?next=https://b.com/?x=1&y=2https://example.com/?next=https://b.com/?x=1&y=2https://example.com/?next=https://b.com/?x=1&y=2

      As the last row shows, neither method can fix a URL that sits unencoded inside a value, because the outer URL reads y=2 as its own parameter. Encode the inner URL separately with Single value and attach it as next=https%3A%2F%2Fb.com%2F%3Fx%3D1%26y%3D2. When the Whole URL rule finds such a value, the status line warns you.

      Double encoding and decoding one layer

      Encoding text that is already encoded turns % into %25. So %20 becomes %2520; decoding once gives %20 again, and you must decode a second time to get the space. It usually happens when a framework or HTTP library encodes values for you and the code encodes them once more. RFC 3986 section 2.4 also says not to encode or decode the same text twice.

      'café crème' encoded repeatedly with the Single value rule
      TimesResultLength
      1caf%C3%A9%20cr%C3%A8me22 characters
      2caf%25C3%25A9%2520cr%25C3%25A8me32 characters
      3caf%2525C3%2525A9%252520cr%2525C3%2525A8me42 characters

      When the encoded box contains %25 followed by two hex digits, the tool guesses a double encoding and shows a 'Decode one more layer' button. The button changes only %25XX into %XX and leaves other separators alone. If the original text really contained the characters '%20', decoding another layer changes the meaning, so check where the value came from.

      Older URLs encoded in Windows-1252

      Current URLs are UTF-8 by default (RFC 3986 section 2.5), but older Western European sites, especially PHP and ASP forms served as ISO-8859-1, send form values as single bytes. 'é' is then %E9 instead of %C3%A9. Browsers treat the ISO-8859-1 label as Windows-1252 (Encoding Standard), which differs mainly in the range 0x80 to 0x9F, such as € at %80. The URL Standard also says that the query of an http or https URL is encoded with the page's character encoding, while the path is always UTF-8.

      The same character in UTF-8 and Windows-1252
      CharacterUTF-8Windows-1252
      é%C3%A9%E9
      ñ%C3%B1%F1
      ü%C3%BC%FC
      €%E2%82%AC%80
      AAA

      Decoding a Windows-1252 value as UTF-8 fails because a lone %E9 is not a valid UTF-8 sequence, and you get �. The auto-detect option of this tool first tries UTF-8 and, if that fails, reads the bytes as EUC-KR, Shift_JIS and Windows-1252 and keeps the reading with the most common characters. To build a value for an older site, choose Windows-1252 yourself. A character that does not exist in the chosen encoding (an emoji, for example) is written like a browser form does it: as &#number; encoded to %26%23number%3B.

      International domain names become Punycode

      A host name is never percent-encoded. Under the internationalized domain names rules (IDNA), a name with accented or non-Latin letters becomes an ASCII name that starts with xn-- (Punycode, RFC 3492). The Whole URL rule converts only the host this way, encodes the path and query as %XX, and shows the original characters again when you decode an xn-- name.

      Domain names and their Punycode
      DomainPunycode
      bücher.dexn--bcher-kva.de
      münchen.dexn--mnchen-3ya.de
      café.frxn--caf-dma.fr
      例え.jpxn--r8jz45g.jp

      In code

      // JavaScript
      encodeURIComponent('café crème & C++');          // caf%C3%A9%20cr%C3%A8me%20%26%20C%2B%2B
      decodeURIComponent('%C3%A9');                     // é (URIError on a bad %)
      new URLSearchParams({ q: 'café near me' }).toString(); // q=caf%C3%A9+near+me
      new URL('https://café.example/menu').href;        // https://xn--caf-dma.example/menu
      
      # Python
      from urllib.parse import quote, quote_plus, unquote, urlencode
      quote('café crème', safe='')                      # caf%C3%A9%20cr%C3%A8me
      quote_plus('café crème')                          # caf%C3%A9+cr%C3%A8me
      unquote('%E9', encoding='cp1252')                 # é
      urlencode({'q': 'café near me', 'page': 2})       # q=caf%C3%A9+near+me&page=2
      
      // PHP
      rawurlencode('café crème');   // caf%C3%A9%20cr%C3%A8me
      urlencode('café crème');      // caf%C3%A9+cr%C3%A8me
      http_build_query(['q' => 'café near me', 'page' => 2]);  // q=caf%C3%A9+near+me&page=2
      
      // Java
      URLEncoder.encode("café crème", StandardCharsets.UTF_8);          // caf%C3%A9+cr%C3%A8me
      URLDecoder.decode("caf%C3%A9+cr%C3%A8me", StandardCharsets.UTF_8); // café crème

      Form-rule functions (URLSearchParams, Python quote_plus(), PHP urlencode(), Java URLEncoder) write a space as +, so for a path segment or a signature use a function that produces %20.

      Common mistakes

      • Encoding a whole URL with the Single value rule: you get https%3A%2F%2F…, which does not open as a link. Use Whole URL to fix a URL itself, and Single value only when the URL becomes a value of another URL.
      • Leaving & or # inside a value: 'A&B' delivers only A, and everything after # never reaches the server. Encode with Single value to get A%26B and %23.
      • C++ arrives as 'C' and two spaces: the receiving side decodes with the form rule and the + was left as it is. Write C%2B%2B.
      • A value shows up as %2520: a library already encoded it and the code encoded it again. Decide on one place where encoding happens.
      • Decoding a Windows-1252 value as UTF-8: the text is garbled or shows �. Switch the character encoding to Windows-1252 and decode again.
      • decodeURIComponent stops with an error: a value such as '100%' has no two hex digits after the %, which throws URIError. This tool leaves such a % as it is and shows its position.

      Limits

      • The tool only converts characters. It does not check that a URL opens or is safe, and it never connects to the address.
      • The Whole URL rule applies only the URL Standard sets for each component. It does not do the other clean-up a browser performs, such as lowercasing the scheme and host, resolving ../, removing a default port or adding / to an empty path. Browsers also differ on a few symbols; Chrome 151, for example, encodes | in a path as %7C.
      • URLs that are not http or https, such as mailto:, are also encoded with the path set. The URL Standard has its own rule for the opaque path of those URLs, so space handling can differ.
      • Auto-detect is a guess. Short values and rare characters (extended CP949 characters, half-width kana in Japanese pages) can be read with the wrong encoding, so choose one yourself when the result looks wrong. Only EUC-KR, Shift_JIS and Windows-1252 are supported as legacy encodings, not EUC-JP or Big5.
      • The URL breakdown only reads and copies. To edit or add query items, use the URL query ↔ parameter table tool. The results by language and function compare only the first 4,000 characters.

      As of: encoding sets come from the URL Standard (version of October 19, 2026) and RFC 3986, signature rules from RFC 5849 and the AWS documentation, and function behavior from each language's documentation, all checked on October 22, 2026. The values in the tables gave the same results in this tool, PHP 8.5, Python 3.14, Node.js 26 and Chromium 151.

      Sources

      Frequently asked questions

      What are URL encoding and decoding?

      URL encoding writes each byte of a character that cannot appear in a URL as % followed by two hex digits, and decoding turns that notation back into the character. In UTF-8, é takes 2 bytes, so it becomes %C3%A9, and decoding gives é again. It is a notation, not encryption, so anyone can reverse it.

      What is the difference between encodeURI and encodeURIComponent?

      encodeURIComponent is meant for a single value, so it also encodes separators such as & = / ? # :, while encodeURI is meant for a whole URL and leaves them alone. That is why encoding the term 'A&B' with encodeURI leaves the & and splits the value in two. encodeURI also turns an existing %20 into %2520, so for a whole URL the Whole URL rule of this tool (URL Standard) is safer.

      Is a space %20 or +?

      Both are used. In paths and most values it is %20, while HTML form submission and URLSearchParams write a space as +. Decoding differs too: decodeURIComponent, PHP rawurldecode and Python unquote leave + as it is, while URLSearchParams, PHP urldecode and Python unquote_plus read it as a space. Writing a real plus as %2B and a space as %20 avoids any doubt.

      Why does % turn into %25 and show up as %2520?

      Because text that was already encoded was encoded once more. % marks an encoding, so a literal % becomes %25 and %20 becomes %2520. RFC 3986 also says not to encode or decode the same text twice. If a value pasted into the encoded box shows %25, the 'Decode one more layer' button peels it off one layer at a time.

      The decoded text is garbled or shows �. Why?

      The value was probably made with a character encoding other than UTF-8. Older Western European sites often wrote é as %E9 in Windows-1252, and reading that as UTF-8 gives garbage. When the value is not valid UTF-8, this tool reads it as EUC-KR, Shift_JIS or Windows-1252, whichever fits, and you can also choose the encoding yourself.

      Are international domain names percent-encoded too?

      No. A domain is not percent-encoded; it is converted to Punycode, an ASCII name that starts with xn--. For example, bücher.de becomes xn--bcher-kva.de. The Whole URL rule converts only the domain to Punycode and encodes non-ASCII characters in the path and query as %XX.

      How do I put one URL inside another URL's query?

      Encode the inner URL as a whole with the Single value rule and attach it. https://b.com/?x=1&y=2 becomes https%3A%2F%2Fb.com%2F%3Fx%3D1%26y%3D2, so putting it after redirect= does not make the outer URL read its & ? # as separators. In the URL breakdown you can open a URL found inside a value with 'Decode this URL'.

      Is the URL I enter sent to a server?

      No. Encoding, decoding, the URL breakdown and domain conversion all run inside this browser. The text you enter is neither sent nor stored, and it is not left in the page address. Even if a URL contains a password or token, it does not leave this page.