urllib.parse.unquote
The reverse of quote. unquote decodes %XX escapes and leaves + alone; unquote_plus decodes form data, where + means a space. Invalid UTF-8 never raises by default — errors='replace' turns it into the U+FFFD replacement character.
Demo
from urllib.parse import unquote, unquote_plus (unquote('rock+%26+roll'), unquote_plus('rock+%26+roll'))
unquote decodes the %XX escapes as one block of bytes and then decodes those bytes as UTF-8, so %C3%A9 is a single é. A % that is not followed by two hex digits — '100% sure', '%zz' — is left exactly as it is, never an error. When the bytes are not valid UTF-8 (%E9 alone is Latin-1 é), the default errors='replace' puts U+FFFD in their place.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| string | str | bytes | yes | Percent-encoded text. bytes are accepted by unquote since 3.9 (not by unquote_plus). A % that is not followed by two hex digits is kept as it is. |
| encoding | str | no ('utf-8') | How the decoded bytes are turned into characters. |
| errors | str | no ('replace') | What to do with bytes that are not valid in that encoding: 'replace' (U+FFFD), 'strict' (raise UnicodeDecodeError), 'ignore', … |
Return value
str — The text with every valid %XX escape decoded. unquote_to_bytes returns bytes instead.
Common patterns
from urllib.parse import unquote_plus name = unquote_plus(raw_value)
from urllib.parse import unquote, urlsplit segments = [unquote(s) for s in urlsplit(url).path.split('/')]
from urllib.parse import unquote text = unquote(value, errors='strict')
Examples
Pitfalls
from urllib.parse import unquote unquote('Ada+Lovelace')
from urllib.parse import unquote_plus unquote_plus('Ada+Lovelace')
from urllib.parse import unquote unquote('caf%E9')
from urllib.parse import unquote unquote('caf%E9', encoding='latin-1')
from urllib.parse import unquote_plus unquote_plus(b'a+b')
from urllib.parse import unquote unquote(b'a+b'.replace(b'+', b' '))
When to use
- Reading a percent-encoded path segment or value: unquote
- Reading form data or a query value by hand: unquote_plus
- Binary data in a URL: unquote_to_bytes
- A whole query string → parse_qs / parse_qsl (they decode with unquote_plus)
- Decoding a full URL before splitting it → urlsplit first, then decode the parts
Notes
FAQ
urllib.parse.unquote('caf%C3%A9') returns 'café'. For form data or query values, where + means a space, use unquote_plus.