After using cgi.parse_qs()
, how to convert the result (dictionary) back to query string? Looking for something similar to urllib.urlencode()
.
-
7N.B: [`cgi.parse_qs()` is deprecated. Use urlparse.parse_qs() instead.](http://docs.python.org/library/cgi.html#cgi.parse_qs) – johnsyweb Oct 18 '11 at 04:53
-
1**See also:** https://stackoverflow.com/questions/5607551/how-to-urlencode-a-querystring-in-python – dreftymac Jul 13 '17 at 19:59
4 Answers
Python 3
urllib.parse.urlencode(query, doseq=False, [...])
Convert a mapping object or a sequence of two-element tuples, which may contain str or bytes objects, to a percent-encoded ASCII text string.
A dict
is a mapping.
Legacy Python
urllib.urlencode
(query
[,doseq
])
Convert a mapping object or a sequence of two-element tuples to a “percent-encoded” string... a series ofkey=value
pairs separated by'&'
characters...

- 7,038
- 2
- 47
- 66

- 776,304
- 153
- 1,341
- 1,358
-
1This is true, but the `dict` returned by `cgi.parse_qs()` actually has `list`s as its "values". Passing these straight in will result in very odd looking query strings. – johnsyweb Oct 18 '11 at 04:50
-
-
18[urllib.parse.urlencode](https://docs.python.org/3.3/library/urllib.parse.html#urllib.parse.urlencode) in Python 3. – Denilson Sá Maia Oct 17 '14 at 21:41
-
1The problem is that urlencode will convert space into +, which is not recommended. – user1633272 May 17 '17 at 06:46
-
3
-
is there a way that I can use `urlencode()` just to make use of `doseq` param. i.e. I do not want any of the characters to be encoded. I know there is a `safe` param, but that would require me to list out each character. I am looking for a wild-card character for `safe` param so that it understands that it has to encode nothing. – Vikas Prasad Sep 09 '20 at 06:35
-
Based on my findings, I do not think anything like such^ exists. And thus, I am exploring the option to first let it get encode and then decode. I know its a round-trip, but I couldn't think of any other alternative except writing the logic of `doseq` on my own in my codebase. – Vikas Prasad Sep 09 '20 at 06:40
-
I realised I can achieve this^^ by passing my own `quote_via` function. Something like: `urlencode(params, doseq=True, quote_via=lambda a, b, c, d : a)` – Vikas Prasad Sep 10 '20 at 04:33
-
In python3, slightly different:
from urllib.parse import urlencode
urlencode({'pram1': 'foo', 'param2': 'bar'})
output: 'pram1=foo¶m2=bar'
for python2 and python3 compatibility, try this:
try:
#python2
from urllib import urlencode
except ImportError:
#python3
from urllib.parse import urlencode

- 21,897
- 23
- 83
- 145

- 2,858
- 2
- 29
- 26
You're looking for something exactly like urllib.urlencode()
!
However, when you call parse_qs()
(distinct from parse_qsl()
), the dictionary keys are the unique query variable names and the values are lists of values for each name.
In order to pass this information into urllib.urlencode()
, you must "flatten" these lists. Here is how you can do it with a list comprehenshion of tuples:
query_pairs = [(k,v) for k,vlist in d.iteritems() for v in vlist]
urllib.urlencode(query_pairs)

- 136,902
- 23
- 188
- 247
-
19
-
@downvoter: How could I improve this answer? It has been six years since I wrote it! – johnsyweb Oct 27 '17 at 09:28
Maybe you're looking for something like this:
def dictToQuery(d):
query = ''
for key in d.keys():
query += str(key) + '=' + str(d[key]) + "&"
return query
It takes a dictionary and convert it to a query string, just like urlencode. It'll append a final "&" to the query string, but return query[:-1]
fixes that, if it's an issue.

- 885
- 5
- 21
-
4Have you met `str.join()` yet? How about `urllib.quote_plus()`? – Ignacio Vazquez-Abrams Oct 18 '11 at 04:34
-
1@garbados Your solution should work in simple cases. However, have a look `urlencode` in `urllib.py` (it should by in your Python install) to see why creating a query string is sometimes not quite as simple as your answer implies (in particular the need to 'quote' certain characters that aren't valid in a URL). @Ignacio has also referenced two functions that would clean up your implementation and make it correct. – Anthony Cramp Oct 18 '11 at 04:57
-
Ah, indeed. Sorry for the cruddy implementation. Goes to show I should be more careful answering questions I've never faced myself. – garbados Oct 20 '11 at 06:29
-
While this may not be the best answer, it is exactly what I wanted to see when I clicked on this question's title. I have only 4 items in a dict that I need to turn into a name=value pair separated by an '&'. My values are controlled. The str.join() is handy in my case but I have no need for quote_plus(), again, because it's not public-facing code :) Thanks! – harperville Apr 09 '14 at 16:55
-
1@harperville but the more correct way (`from urllib.parse import urlencode; urlencode(your_dict)`) is shorter and easier than this! I'll grant that it's sometimes smart to reinvent the wheel, even shoddily, when it's expensive or inconvenient to access existing, well-designed wheels, but here using the off-the-shelf wheel is easier and quicker than rolling your own inferior one. – Mark Amery Jun 21 '16 at 22:57