Skip to content

URL Encode & Decode Online Free

Percent-encode any string for safe inclusion in a URL, or decode an encoded one back to its readable form.

In your browseryour files never leave your device.

Learn more
⌘Enter run · ⌘B swap

encodeURIComponent — encodes EVERY character except A-Z a-z 0-9 - _ . ~. Use for single query-string values or path segments where reserved chars (/:?#&) must be escaped.

Encoded URL will appear here…

About this tool

URL encoding is the rule that says "anything that is not a letter, digit, hyphen, period, underscore, or tilde gets replaced with %HH where HH is the byte in hex." RFC 3986 defines the reserved set, and your stack normally handles it for you — until you are building a URL by hand, debugging a request that is mangled in transit, or comparing what one library produces against another. The classic case is a query parameter that contains an ampersand or a hash sign and breaks the URL when written raw. This tool uses encodeURIComponent for encoding and decodeURIComponent for decoding, both standard JavaScript built-ins, so the output matches what your fetch call would produce at runtime. Non-ASCII input gets the multi-byte UTF-8 percent-sequence that any RFC 3986 parser expects.

How to url encode & decode online free

  1. Pick a direction

    Encode turns text into percent-encoded form. Decode does the reverse, turning %20 back into a space and %3D back into an equals sign. Toggle at the top; switching clears the input so you do not run on stale text.

  2. Paste your string

    A full URL, a single parameter value, or any text — the tool processes whatever you paste without assuming the input is a complete URL. So you can encode just "hello world & friends" to get "hello%20world%20%26%20friends" without worrying about scheme or domain.

  3. Read the output

    Encoded or decoded result appears below the input as soon as it parses. Spaces become %20, ampersands become %26, slashes become %2F, et cetera. For decode, you get readable text. If decoding fails (malformed input) the message tells you so.

  4. Copy and paste it where you need it

    The copy button puts the result on your clipboard, ready for a curl command, a config file, a redirect URI registration, or wherever you are constructing URLs by hand. The Clipboard API works on all modern browsers including mobile.

Why use this tool

OAuth callback URLs are where I hit URL encoding most. The provider tells you to register a redirect URI that includes query parameters, and getting the encoding wrong gives you a redirect_uri_mismatch error that takes ten minutes to figure out because the page just says "no". Pasting both forms into this tool side by side ends the guessing in five seconds. The other case is debugging webhooks: a vendor sends a POST whose body or headers include a percent-encoded JSON blob, and you need to crack it open to see what the payload actually was. Decoding directly in a browser tab beats spinning up a Node REPL for one string. The third case is search engine results — querystrings with %20 and %3D everywhere — when I want to see what was actually searched. The fourth is building API URLs in shell scripts where bash variable interpolation has no idea about URL safety. The fifth is debugging mobile deep links and Android intents, which carry encoded payloads in their data URIs.

Features

encodeURIComponent under the hood

Encoding uses the standard browser function, the one MDN tells you to use for query parameter values. Output is byte-for-byte identical to what your fetch() or axios call produces at runtime. Letters, digits, and -_.~ pass through unchanged; everything else, including spaces, slashes, colons, and ampersands, becomes %HH where HH is the UTF-8 byte in two hex characters. The result is safe to drop into any URL component.

Both directions, one box

Toggle between encode and decode without retyping the input — the same field works both ways, and switching clears the box so you do not run the wrong direction by accident. Output updates as soon as the input is parsed, with no submit button to press. Useful when you want to verify a round-trip: encode, copy, paste back, decode, confirm you get the original.

Handles non-ASCII correctly

Encoding an em-dash, a CJK character, or an emoji produces the multi-byte UTF-8 percent-sequence that any RFC 3986 parser expects. Some older tools encode each Unicode codepoint as a single byte, which gives wrong results above U+007F and breaks compatibility with anything that follows the standard. This tool gets it right by relying on the built-in encodeURIComponent, which is mandated to do UTF-8 by the ECMAScript spec.

Decoder catches malformed input

A stray % followed by a non-hex character is a URI malformed error in decodeURIComponent — for example, "100% complete" cannot be decoded because the % is not followed by two hex digits. Instead of crashing or producing silently wrong output, the tool tells you the input was not valid percent-encoded text so you can fix it. Saves the case where you double-decode something and end up scratching your head.

Tells you which encoding family applies

There are actually three encoding contexts in browser-land: encodeURI for whole URLs (leaves structural punctuation alone), encodeURIComponent for parts of URLs (encodes everything), and the form-data path used by FormData and URLSearchParams (which is encodeURIComponent plus the +-for-space substitution). This tool encodes with the middle one — the right default for query parameter values, path segments, and JSON-in-URL payloads. If your destination needs the form-data variant with + instead of %20, do one find-and-replace on the output. If your destination needs the URL-shell-leave-it-alone variant, copy only the parts you actually need encoded.

Privacy & security

encodeURIComponent and decodeURIComponent are part of the JavaScript engine; they ship with your browser and do not call out to anything. Paste a presigned S3 URL with a signature in it, paste a session cookie value, paste a password-reset token — none of those ever leave your tab. The output box updates as fast as you type and the only network activity you will see in DevTools is the initial page load.

Frequently asked questions

encodeURI versus encodeURIComponent — which one does this use?
encodeURIComponent. The difference: encodeURI leaves the structural characters :/?&=#+ alone because it is meant for encoding a whole URL where those characters have meaning. encodeURIComponent encodes them too, because it assumes you are encoding a single component that will be slotted between & and = in a querystring. For query parameter values, you almost always want encodeURIComponent — encoding the whole URL with encodeURI breaks every parameter separator and silently corrupts requests. If you have an entire URL where you only want to encode the special characters within parameter values, you have to encode each component separately.
Spaces become %20 or +?
This tool emits %20, which is correct for both URLs and form data per RFC 3986. The + convention is from application/x-www-form-urlencoded, the older HTML form encoding, and it only applies to the body of POST requests sent with that content type. If a server insists on + (some older Java servers do), do a single-character replacement after encoding — replace %20 with + everywhere. Most modern servers accept either form; the spec actually requires servers to decode + as space within form-urlencoded but not within URL components, so the contexts matter.
Which characters actually need encoding?
Anything outside the unreserved set: letters A-Z and a-z, digits 0-9, and the four characters - _ . ~ are safe everywhere. Everything else — spaces, &, ?, =, #, /, +, %, plus signs, semicolons, and any non-ASCII byte — gets percent-encoded when used inside a query parameter value or path segment. The exact list of "reserved" characters per RFC 3986 is :/?#[]@!$&'()*+,;= but you can encode any of them anyway without changing meaning. When in doubt, encode.
Is this safe for URLs with passwords or tokens?
Yes. The encoding and decoding happen in your browser via built-in JavaScript functions. Nothing is sent over the network. You can verify this in DevTools — no fetch, no XHR, no beacon. Important if you are encoding a session cookie, a presigned S3 URL with a sensitive signature, a one-time login link, or any credential-carrying parameter. The local-only design is the reason this matters more for dev tools than for, say, a calculator.
Why does my URL look fine in the browser bar but break in code?
Browsers display URLs decoded for readability but send them encoded over the wire. Copy from the address bar and you usually get the encoded form, but some browsers (Firefox in particular) decode Unicode characters for display, so what you see is not what the server sees. Always encode programmatically rather than trusting copy-paste. The reverse is also true — pasting a URL with a Chinese character into a curl command may or may not work depending on your terminal's encoding handling.
Maximum URL length?
No tool-side limit on encoding. In practice browsers cap URLs at around 2,000 to 8,000 characters depending on the engine (Chrome accepts longer than Edge in some configurations), and many servers reject longer ones with HTTP 414 Request-URI Too Long. CDNs and proxies have their own limits, often stricter than the origin. If you are pushing past that, you are probably encoding too much in the URL and should move the payload into the request body — or use a short-lived token that references the data server-side.
What about double-encoding?
Re-encoding an already-encoded string is a common bug. "hello world" becomes "hello%20world" once, then "hello%2520world" if encoded again — the % itself gets encoded as %25. Decoding once gives you "hello%20world" instead of the original. Watch out for stacks where a middleware encodes the URL on its way to your handler and your code encodes it again. Pasting the result here and decoding tells you how many layers deep the encoding goes.
Offline?
Yes. Once the page loads, the encoding logic runs locally and needs no network. The functions are built into the JavaScript engine — there is no library to fetch, no service to call. You can work on a plane, in a Faraday cage, anywhere that has a powered browser.
What are the reserved and unreserved character sets in RFC 3986?
Two groups matter. Unreserved characters never need encoding anywhere in a URI: A-Z, a-z, 0-9, and the four marks - . _ ~. Reserved characters have grammatical meaning in URIs and must be encoded when they appear in data: gen-delims are :/?#[]@ and sub-delims are !$&'()*+,;=. The gen-delims separate the major parts of a URI (scheme, authority, path, query, fragment). The sub-delims have meaning in specific components — & and = inside a querystring, ; inside a path parameter, etc. Anything outside both groups, including spaces, control characters, and any non-ASCII byte, must be percent-encoded. The practical rule for any value going into a URL: if it is not a letter, digit, hyphen, dot, underscore, or tilde, encode it.
When does the same string get encoded differently as a path segment vs a query value?
In practice, encodeURIComponent treats them the same — it encodes everything outside the unreserved set. But the URI specs draw a subtle distinction. A path segment can legally contain sub-delims and the @ : characters unencoded, while a query value technically permits even more (slashes and question marks are sometimes left as-is inside a query string). Most APIs and routing libraries do not care about these edge cases and accept either form, so the safe default is to over-encode rather than under-encode. The two places where it matters: matrix parameters in REST URLs (path segments with ;key=value syntax) and OAuth signature base strings, where the spec requires very specific percent-encoding of exactly the right characters and nothing more.
Why does my OAuth signature fail even though the URL works in the browser?
OAuth 1.0a and AWS SigV4 require canonical percent-encoding that does not match what browsers produce. The OAuth 1.0a spec requires uppercase hex (%2F not %2f), encoding of every reserved character (including the tilde, which is normally unreserved), and a specific parameter sorting order. JavaScript encodeURIComponent emits uppercase hex by default — but does not encode the tilde, the apostrophe, the asterisk, the open and close parentheses, or the exclamation mark. So building an OAuth signature input with bare encodeURIComponent produces a string that does not match what the server computes, and the signature verification fails with an unhelpful "invalid signature" error. The fix is a custom encoder that wraps encodeURIComponent and adds replacements for those five characters. Painful, but a one-line utility solves it.
What does "double-encoding" look like and how do I detect it?
A double-encoded string has %25 where you expected % alone. Decode "hello%2520world" once and you get "hello%20world"; decode again and you get "hello world". The %25 is the percent sign itself encoded, which means somewhere in your pipeline a string got encoded that was already encoded. Three common causes: an HTTP client that auto-encodes parameter values you already encoded by hand; a server-side framework that decodes once on the way in and your handler decodes again; a query string built from URLSearchParams.toString() which already encodes, then passed to a fetch call with an encoded URL. The fix is to inspect the request as it leaves the client (with curl --trace or a proxy like mitmproxy) and identify which layer is encoding what.
Should I encode the slashes in a path like /users/alice?
Generally no. The slashes separate path segments and are part of the URL structure, so encoding them as %2F changes the semantics — a single segment named "users/alice" is different from the path "users" then "alice". Some routing libraries refuse to decode %2F in paths because of this ambiguity (Express, ASP.NET Core, and several others reject or 404 on encoded slashes by default for security reasons related to path traversal). If you have a user input that legitimately contains a slash and needs to ride in a path, encode it to %2F and configure the receiving server to accept it (in Express, app.set("strict routing", false) and a custom middleware to decode; in nginx, the merge_slashes directive). Better solution: put the value in a query parameter or POST body instead of the path.