Which characters each style leaves alone
- A single value keeps letters, digits and
- _ . ! ~ * ' ( ). Everything else, including/ ? # & = + :and spaces, is encoded. - A whole URL keeps all of those plus
; , / ? : @ & = + $ #, so the structure of the address survives. - Form style keeps letters, digits and
- _ . *. A space becomes+, and~ ! ' ( )are encoded. This is what an HTML form orURLSearchParamsproduces.
Everything outside ASCII is converted to UTF-8 first. A lone half of an emoji, which cannot be written in UTF-8, is replaced and you are warned.
Putting one URL inside another
Login and redirect flows often carry a URL as a parameter, such as ?next=.... If that value is not encoded, its own ? and & are read as part of the outer URL. With https://example.org/a?x=1&y=2 as the value, the raw version would hand the server next=https://example.org/a?x=1 and a separate parameter y=2.
Encoded with the single value style, it becomes https%3A%2F%2Fexample.org%2Fa%3Fx%3D1%26y%3D2, and the server receives the whole address as one value.
Common mistakes
- Encoding a whole URL as a single value, which turns
https://intohttps%3A%2F%2Fand stops it working as a link. - Encoding twice, which turns
%20into%2520. Encode raw text exactly once. - Leaving
+and&raw in a value. In a query string+is read as a space and&starts a new parameter. Encode values before joining them with&.
In code, the equivalents are encodeURIComponent(value) in JavaScript, urllib.parse.quote(value, safe="") in Python and rawurlencode($value) in PHP. In Python and PHP, quote_plus and urlencode give the form style with + for spaces.