URL Encoder and Decoder
For one query value or path segment. Encodes everything except letters, digits and - _ . ! ~ * ' ( ), the same as encodeURIComponent.
Paste a URL above. Its parts and parameters show up here, ready to edit.
Query parameters
This URL has no query parameters.
Fragment parameters
Everything runs in your browser and nothing you paste is uploaded. That matters, because URLs often carry tokens and session IDs.
URL encode and decode text online as you type: the tool turns spaces, accented letters and symbols such as & or ? into percent-encoded sequences like %20, and turns them back into readable text. The second tab is a URL parser. It splits any address into protocol, host, path and query parameters that you can edit, switch off or strip of tracking tags, and writes the correctly encoded URL back for you. Everything happens in your browser.
How to URL encode and decode text
- Type or paste into the field on the Encode / Decode tab. The Result updates with every keystroke.
- Pick the Direction. Encode makes text safe for a URL, Decode turns
caf%C3%A9%20au%20laitback intocafé au lait. Paste text with sequences like%20into the empty field and the tool switches to Decode by itself (Encode it instead switches back). Plain text that needs encoding, pasted in Decode mode, switches it to Encode the same way, with Decode it instead. - When encoding, choose under Encode as what the text is (see the next section). The default, Parameter value, is right for a single query value.
- Copy puts the result on the clipboard. Swap moves the result into the input and flips the direction. That is a quick round trip check: decoding what you just encoded must give your original text back.
Every character the tool changed is highlighted in the result. Hover over one to see the character, its Unicode code point and its bytes, for example é U+00E9 %C3%A9. Below the fields you see the number of Characters, UTF-8 bytes and Encoded characters (or Decoded characters). Try an example loads the sentence Price: 50% off, café & crème brûlée? Yes!, which has 41 characters but 45 UTF-8 bytes, because each accented letter takes two bytes.
When encoding, Each line separately encodes every line on its own and keeps the line breaks, which suits a list of values or links. Without it, a line break is encoded too and becomes %0A. When the text is a URL with parameters, the tool offers Split it into parts, which opens the address in the parser tab.
Encode a URL parameter, a whole URL or form data
Not every character has to be encoded everywhere. A slash separates folders in a path but is plain data inside a parameter value, so the right result depends on what you encode. Encode as offers four modes:
- Parameter value works like JavaScript’s
encodeURIComponentand suits one query value or path segment. It encodes everything except letters, digits and- _ . ! ~ * ' ( ), so an&,=,/or?inside the value cannot break the URL. Encodingcafé & crèmegivescaf%C3%A9%20%26%20cr%C3%A8me, ready to go afterq=. - Whole URL is for a complete address that only needs cleaning up. It encodes spaces, non-ASCII characters, control characters, the backtick and
" < > \ ^ { | }, and keeps everything that gives a URL its structure:: / ? # [ ] @ ! $ & ' ( ) * + , ; =. Sohttps://example.com/search?q=café au lait&lang=frbecomeshttps://example.com/search?q=caf%C3%A9%20au%20lait&lang=fr. Sequences that are already encoded stay as they are, and a lone%becomes%25. This is where it differs from JavaScript’sencodeURI, which turns an existing%20into%2520and encodes the brackets of an IPv6 address such ashttp://[2001:db8::1]:8080/. - Form data follows the application/x-www-form-urlencoded format that HTML forms and
URLSearchParamsproduce. A space becomes+, and only letters, digits and* - . _stay unencoded, so! ' ( ) ~are encoded as well. - Strict RFC 3986 leaves only the unreserved characters of RFC 3986 unencoded: letters, digits and
- . _ ~. OAuth 1.0 (RFC 5849) and AWS Signature Version 4 require exactly this form, because a signature only matches when both sides encode!or*the same way.
The same characters in each mode:
| Character | Parameter value | Whole URL | Form data | Strict RFC 3986 |
|---|---|---|---|---|
| space | %20 | %20 | + | %20 |
& | %26 | & | %26 | %26 |
/ | %2F | / | %2F | %2F |
+ | %2B | + | %2B | %2B |
~ | ~ | ~ | %7E | ~ |
! | ! | ! | %21 | %21 |
* | * | * | * | %2A |
é | %C3%A9 | %C3%A9 | %C3%A9 | %C3%A9 |
Text is always encoded as UTF-8 and the hex digits are always uppercase. If the input already contains sequences like %20, a note says so and offers Decode it instead, so you do not encode the text twice by mistake.
To pass JSON in a query parameter, minify it in the JSON formatter and encode it as Parameter value: {"id":7,"tags":["a","b"]} becomes %7B%22id%22%3A7%2C%22tags%22%3A%5B%22a%22%2C%22b%22%5D%7D. It works the other way round too: decode the parameter here, then format it there.
URL decode problems: plus signs, %2520 and broken sequences
Decoding usually just works, but four situations trip people up. The tool handles each of them instead of stopping with an error:
- A plus sign stands for a space in form data and most query strings. Decode + as a space is on by default, so
caf%C3%A9+au+laitdecodes tocafé au lait. In a whole URL only the plus signs after the?count as spaces, because in a path a plus is an ordinary character. Switch the option off when a plus sign is meant literally. A plus that was encoded as%2Balways stays a plus sign. - Double encoding happens when two layers of code each encode the same value, which RFC 3986 explicitly warns against. Each
%becomes%25, so a space turns from%20into%2520. If the decoded result still contains sequences like%20, the tool says the text was probably encoded twice and offers Decode again. - An invalid sequence, a
%that is not followed by two hex digits as in100%or%G1, makes JavaScript’sdecodeURIComponentthrow a URIError. Here such sequences are left as they are, marked in red and counted, and the rest of the text is decoded. - Old Latin-1 links come from the time before UTF-8, when some sites encoded
éas the single byte%E9.caf%E9is not valid UTF-8, sodecodeURIComponentfails and Python’sunquotereturnscaffollowed by the replacement character U+FFFD. The tool reads such bytes as Windows-1252, decodescaf%E9tocaféand adds a note saying so.
Control characters in decoded text, such as a tab or a null byte, are shown as visible symbols like ␉ and ␀, but Copy copies the real text.
URL parser: split a URL and edit its query parameters
Paste an address into the URL field on the Parse & edit URL tab and it is split into Protocol, Host, Port, Path and Fragment, plus Username and Password when the URL contains them. The values are shown decoded, so the tab is also the quickest way to decode URL parameters: you read running shoes instead of running+shoes. Editing works both ways, like the URL bar and the parameter table in Postman. Change a field and the URL is rewritten at once, correctly encoded; change the URL and all parts are read again. Parts you do not touch stay exactly as they were, character for character.
The Query parameters table lists every parameter with its Name and Value. Untick Include in the URL to leave a parameter out without deleting it, which helps when you are looking for the one parameter that breaks a request. Add parameter, Remove parameter and Sort A to Z do what they say. Repeated names like tag=a&tag=b and names without a value like ?debug are kept. Spaces in parameters decides whether spaces are written as %20 or +; by default it follows the URL you pasted.
Login and payment links often carry a second URL inside a parameter, encoded so that its own ? and & do not mix with the outer ones:
https://auth.example.com/authorize?client_id=abc&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback%3Ftab%3D2
A value that is itself a URL, typically in redirect_uri, return, url or next, gets an Edit the URL inside button. The inner address https://app.example.com/callback?tab=2 opens as its own level with its own parts and parameters, a breadcrumb (Main URL › redirect_uri) leads back, and every change is encoded back into the outer URL. Copy main URL copies the result. This works several levels deep.
When the part after # looks like parameters, as in #access_token=...&state=... in the OAuth implicit flow or #/search?q=shoes in the routes of single page apps, a second table, Fragment parameters, lists them too.
The parser also points out problems: a URL without a protocol, which browsers treat as a relative link; a port outside 0 to 65535; and characters that must be encoded, such as spaces, accented letters, " or <, which Encode them fixes in one step. Text without an address, like a=1&b=2, is read as a query string. For an internationalized domain name the tool shows the Punycode form that DNS and browsers use, so münchen.de becomes xn--mnchen-3ya.de, and a domain starting with xn-- gets its readable form.
Copy URL copies the finished address, Open opens it in a new tab (http and https links only), and Copy as JSON gives you the parameters as a JSON object, with repeated names collected into an array.
Remove UTM and other tracking parameters from a URL
Links from newsletters, ads and social networks carry parameters that only tell the site where the visitor came from. The UTM parameters utm_source, utm_medium, utm_campaign, utm_term and utm_content go back to Urchin, the predecessor of Google Analytics. Click IDs such as fbclid (Facebook), gclid (Google Ads) and msclkid (Microsoft Advertising) are appended by the platforms themselves.
The parser marks these with a tracking tag, and Remove tracking (n) deletes all of them at once. Besides any utm_* parameter it recognizes more than 20 others, such as ttclid (TikTok), mc_cid (Mailchimp) and _hsenc (HubSpot). Parameters the page needs stay in place: in the shop link from Try an example, Remove tracking (4) removes utm_source, utm_medium, utm_campaign and fbclid and keeps q, size, return and the #reviews fragment.
A link that is going into a QR code is worth cleaning up here first. Without tracking parameters it is shorter, and a shorter link gives a less dense code that is easier to scan.
What percent encoding is and how characters become %XX
Percent-encoding, also called URL encoding, writes a character as % followed by two hexadecimal digits. A URL may only contain a limited set of ASCII characters, and some of them have a job: ? starts the query, & separates parameters, # starts the fragment. RFC 3986 calls these reserved characters (: / ? # [ ] @ and ! $ & ' ( ) * + , ; =). Letters, digits and - . _ ~ are unreserved and never need encoding. Everything else, and every reserved character used as plain data, gets encoded.
Characters outside ASCII are first turned into UTF-8 bytes, and each byte gets its own %XX:
éis U+00E9, which UTF-8 stores as the two bytes C3 A9, so it becomes%C3%A9.€is U+20AC, three bytes:%E2%82%AC.- An emoji such as U+1F600 (grinning face) takes four bytes:
%F0%9F%98%80.
%c3%a9 and %C3%A9 mean the same, but RFC 3986 recommends uppercase, which is what the tool writes. A percent encoding table of the characters you meet most often:
| Character | Encoded | Character | Encoded |
|---|---|---|---|
| space | %20 | + | %2B |
! | %21 | , | %2C |
" | %22 | / | %2F |
# | %23 | : | %3A |
$ | %24 | ; | %3B |
% | %25 | = | %3D |
& | %26 | ? | %3F |
' | %27 | @ | %40 |
( | %28 | [ | %5B |
) | %29 | ] | %5D |
* | %2A | line break | %0A |
URL encoding in JavaScript, Python and PHP
Every language has functions for this, and they differ mainly in how they treat spaces, slashes and ! ' ( ) * ~.
JavaScript has encodeURIComponent for a value, encodeURI for a whole address and URLSearchParams for form encoding:
encodeURIComponent("café & crème") // "caf%C3%A9%20%26%20cr%C3%A8me"
encodeURI("https://example.com/a b?q=café") // "https://example.com/a%20b?q=caf%C3%A9"
new URLSearchParams({ q: "café & crème" }).toString() // "q=caf%C3%A9+%26+cr%C3%A8me"
decodeURIComponent("caf%C3%A9") // "café"
decodeURIComponent does not turn + into a space, and it throws a URIError on an invalid sequence such as 100%.
In Python the functions live in urllib.parse. quote keeps / by default (safe='/') and otherwise encodes everything except the RFC 3986 unreserved characters. quote_plus writes spaces as + and encodes / too:
from urllib.parse import quote, quote_plus, urlencode, unquote_plus
quote("café & crème/brûlée") # 'caf%C3%A9%20%26%20cr%C3%A8me/br%C3%BBl%C3%A9e'
quote("a b/c", safe="") # 'a%20b%2Fc'
quote_plus("café & crème/brûlée") # 'caf%C3%A9+%26+cr%C3%A8me%2Fbr%C3%BBl%C3%A9e'
urlencode({"q": "café & crème", "page": 2}) # 'q=caf%C3%A9+%26+cr%C3%A8me&page=2'
unquote_plus("caf%C3%A9+au+lait") # 'café au lait'
In PHP, urlencode encodes the way an HTML form does and writes a space as +, while rawurlencode follows RFC 3986 and writes %20:
urlencode("café & crème"); // "caf%C3%A9+%26+cr%C3%A8me"
rawurlencode("café & crème"); // "caf%C3%A9%20%26%20cr%C3%A8me"
rawurlencode gives the same result as Strict RFC 3986. urlencode matches Form data except for *, which it encodes as %2A.
Frequently asked questions
Should a space be encoded as %20 or +?
%20 works everywhere in a URL. A + means a space only in the query string and in form data, the format HTML forms send. In a path, + is an ordinary plus sign, so /a+b stays /a+b. When a query value needs a real plus sign, write it as %2B. In the tool, Form data writes spaces as + and the other three modes as %20.
What do %20, %2F and %3D mean in a URL?
They are encoded characters: %20 is a space, %2F a slash and %3D an equals sign. Others you see often are %26 (&), %3F (?), %3A (:), %2C (comma) and %27 (apostrophe). The two digits are the character's code in hexadecimal. Accented letters and other non-ASCII characters take two to four such pairs, like %C3%A9 for é. Paste the whole string into the decoder to read it.
What is the difference between encodeURI and encodeURIComponent?
encodeURI is meant for a whole address and leaves the characters that structure it, such as : / ? # & =, alone. encodeURIComponent is meant for one part, a parameter value or a path segment, and encodes those characters too, so https://example.com/?a=1&b=2 becomes https%3A%2F%2Fexample.com%2F%3Fa%3D1%26b%3D2. In this tool, Parameter value matches encodeURIComponent, and Whole URL is like encodeURI but keeps existing sequences such as %20 instead of turning them into %2520.
How do I remove UTM parameters from a URL?
Paste the link into the Parse & edit URL tab and press Remove tracking (n). It deletes every utm_* tag and click IDs like fbclid and gclid at once. Then press Copy URL. To drop only some of them, use Remove parameter on the rows you do not want.
Is URL encoding the same as encryption or Base64?
No. URL encoding hides nothing: anyone can decode caf%C3%A9 back to café, so it never protects a password or a token. It only makes characters safe to use in an address. Base64 is a different encoding that turns any data, including binary files, into a string of 64 characters. A Base64 string in a URL still needs its +, / and = encoded, unless you use the URL safe variant, which the Base64 encoder and decoder can produce.
Are the URLs I paste uploaded or stored?
No. Encoding, decoding and parsing run in your browser, and nothing you paste is sent to a server. That matters, because URLs often carry access tokens, session IDs or password reset codes. The browser remembers only your chosen tab and options, never the texts. The only thing that loads the address is Open, which opens it in a new tab just like clicking the link would.
More tools for programmers are in the Developers category, and tools that turn one format into another are collected under Converters. To find what differs between two long URLs, for example a working and a failing API call, paste them into the text compare tool and compare by characters.