I have an input which is a decoded URL, it can contain '+' symbols Here is my code to encode the url safely # Safely encode the path encoded_path = quote(parsed.path) # Safely encode query parameters query_params = parse_qsl(parsed.query, keep_blank_values=True) encoded_query = urlencode(query_params, quote_via=quote, safe='') parse_qsl is converting my '+' to spaces i suspect, but the final encoded query is having %20 instead of %2B. How do I fix this? EDIT: Adding a reproducible script import urllib from urllib.parse import urlparse, urlunparse, quote, urlencode, parse_qsl, quote_plus def safe_presigned_url(raw_url): parsed = urlparse(raw_url) # Safely encode the path encoded_path = quote(parsed.path) # Safely encode query parameters query_params = parse_qsl(parsed.query, keep_blank_values=True) encoded_query = urlencode(query_params, quote_via=quote, safe='') # Rebuild and return the full URL return urlunparse(( parsed.scheme, parsed.netloc, encoded_path, parsed.params, encoded_query, parsed.fragment )) url = 'http://example.com/path/tofile?query=param+with+questionmark' #decoded url print(f'BEFORE {url}') # BEFORE http://example.com/path/tofile?query=param+with+questionmark url = safe_presigned_url(url) print(f'AFTER {url}') # AFTER http://example.com/path/tofile?query=param%20with%20questionmark # EXPECTED http://example.com/path/tofile?query=param%2Bwith%2Bquestionmark Continue reading...