Explainer 5 min read

%20 vs + in URLs: How Spaces Are Encoded (and When Each Breaks)

Why spaces in URLs appear as %20 in some places and + in others, which one to use in paths and query strings, and how to fix a + that turns into a space.

%20 vs + in urlurl encode spaceplus sign in url query stringspace in urlencodeuricomponent vs urlsearchparamsurl encoding plus sign

The short answer

Both %20 and + can represent a space, but in different places. %20 is the general percent-encoding for a space and is safe everywhere in a URL. + means a space only inside a query string that uses the HTML form format (application/x-www-form-urlencoded); in a URL path, a + is just a plus sign. When in doubt, use %20, and always encode a real plus sign as %2B. The free URL Encoder/Decoder produces %20 for spaces and %2B for plus signs, so its output is safe in both places.

Where the two formats come from

There are two related but different encoding rules on the web:

  • Percent-encoding for URLs. Any character that is not allowed, or has a special meaning, is written as % followed by its byte value in hex. A space is byte 32, which is 20 in hex, so it becomes %20.
  • HTML form encoding. When a browser submits a form with method GET, it builds the query string using form encoding, where a space is written as + to keep URLs short and readable. A real plus sign then has to be written as %2B.
  • Both systems agree that %20 is a space. They disagree about what a bare + means.

    What each encoding function produces

    Different languages and functions pick different rules. These outputs were produced by running the functions on the text hello world & more+1:

    FunctionOutputSpace becomesPlus becomes
    JavaScript encodeURIComponenthello%20world%20%26%20more%2B1%20%2B
    JavaScript URLSearchParamshello+world+%26+more%2B1+%2B
    Python urllib.parse.quotehello%20world%20%26%20more%2B1%20%2B
    Python urllib.parse.quote_plushello+world+%26+more%2B1+%2B

    All four are valid in a query string. Only the %20 versions are also safe in a path.

    Decoding is where the bugs appear

    Encoding rarely goes wrong. Decoding with the wrong rule does. Look at what happens to the string a+b%20c:

    • JavaScript decodeURIComponent gives a+b c. It decodes %20 but leaves + as a plus sign.
    • Python unquote also gives a+b c.
    • Python unquote_plus gives a b c. It treats + as a space.
    • URLSearchParams in JavaScript also treats + as a space when it reads a query string.

    So the same URL can produce different values depending on which function your server or script uses.

    The classic bug: a phone number or email loses its plus sign

    Suppose a link is built by hand as /search?phone=+919876543210. A server that reads query strings with form decoding sees + as a space and receives 919876543210, with a leading space and no plus. The same happens with email addresses that use plus addressing, such as name+news@example.com.

    Fix: encode the value before putting it in the URL. With encodeURIComponent, the plus becomes %2B and every decoder turns it back into +.

    The opposite bug: a + shows up where a space should be

    If a query string was built with form encoding (q=hello+world) but your code reads it with decodeURIComponent, you get hello+world with a literal plus. Either read query strings with a form-aware parser (URLSearchParams in JavaScript, parse_qs or unquote_plus in Python), or replace + with a space before decoding a value you know came from a form.

    How to use the URL Encoder for this

  • Open the URL Encoder/Decoder and choose Encode URL.
  • Paste only the value you want to put in the URL, for example +91 98765 43210, not the whole address.
  • Copy the result: %2B91%2098765%2043210. Paste it after = in your query string.
  • To check a link you received, switch to Decode URL and paste the encoded part.
  • Two things to know about this tool, because it uses the browser's encodeURIComponent and decodeURIComponent functions:

    • It encodes every reserved character, including /, ?, &, = and :. That is what you want for a single value. If you paste a whole URL, the result will be one long encoded string that no longer works as a link. Encode the parts, then assemble the URL.
    • Decode mode leaves + as a plus sign. If you are decoding a query string that came from an HTML form, replace each + with a space first.

    For a step-by-step guide to encoding a single parameter, see how to URL-encode a query parameter.

    Which should you use?

    SituationUse
    A space in a URL path, such as a file name%20
    A space in a query string value you build yourself%20 (always works)
    Reading a query string sent by an HTML formExpect + and decode it as a space
    A real plus sign anywhere in a value%2B
    Building a whole query string in JavaScriptURLSearchParams (it handles the + rule both ways)

    Common mistakes

    • Encoding a URL twice. %20 encoded again becomes %2520, because % itself is encoded as %25. If you see %25 in a link, something encoded an already-encoded value.
    • Encoding the whole URL with encodeURIComponent. The :// and / separators get encoded too and the link breaks. Use it on values only.
    • Replacing spaces with + in file paths. A file called my file.pdf must be my%20file.pdf in the path. my+file.pdf asks the server for a file with a plus in its name.
    • Pasting a stray % sign. A value like 100% is not valid encoded text. Encode it first: 100%25.

    Quick test

    Paste café & crème into the encoder. You should get caf%C3%A9%20%26%20cr%C3%A8me. The accented letters become two bytes each because the encoder uses UTF-8, and the space is %20, never +.

    For the bigger picture of why URLs need encoding at all, read URL encoding and decoding explained. If you are also passing binary data in a URL, the Base64 encoder is the usual next step, but remember that standard Base64 output can itself contain + and /.

    Frequently asked questions

    Is %20 or + correct for a space in a URL?

    %20 is correct everywhere in a URL. A plus sign means a space only in query strings that use HTML form encoding. In a URL path, + is a literal plus sign, so use %20 for spaces in paths.

    Why does a plus sign in my query string turn into a space?

    The server decodes the query string with form rules, where + means space. Encode a real plus sign as %2B before adding it to the URL, for example with encodeURIComponent or a URL encoder tool.

    Does encodeURIComponent turn spaces into + or %20?

    It turns spaces into %20 and plus signs into %2B. URLSearchParams and Python quote_plus use + for spaces instead.

    What does %2520 mean in a URL?

    It means the URL was encoded twice. %25 is the encoding of the % sign, so %20 encoded again becomes %2520. Decode once to get back %20, then fix the code that encodes twice.

    Try this tool on Lazyblink

    Put this guide into practice with our free online tool — no signup required.

    Open tool