Python request module sends JSON string instead of x-www-form-urlencoded param string
I was under the impression that POSTS using the x-www-form-urlencoded specs should send a URL-encoded string in the body of the post. However, when I do this,
data = json.dumps({'param1': 'value1', 'param2': 'value2'})
Requests.post(url, data=data)
The request body on the receiving end looks like this:
{"param1": "value1", "param2": "value2"}
But I was expecting to get this
param1=value1¶m2=value2
How can I get requests to submit data in the second form?
source to share
The reason you are getting JSON is because you are explicitly calling json.dumps
to generate a JSON string. Just don't do this and you won't get a JSON string. In other words, change your first line to this:
data = {'param1': 'value1', 'param2': 'value2'}
As the docs explain , if you pass a dict as a value data
, it will be encoded in the form, and if you pass in a string, it will be sent as is.
For example, in one terminal window:
$ nc -kl 8765
In another:
$ python3
>>> import requests
>>> d = {'spam': 20, 'eggs': 3}
>>> requests.post("http://localhost:8765", data=d)
^C
>>> import json
>>> j = json.dumps(d)
>>> requests.post("http://localhost:8765", data=j)
^C
In the first terminal, you will see that the first request body is (and Content-Type application/x-www-form-urlencoded
):
spam=20&eggs=3
... while the second is this (and has no Content-Type):
{"spam": 20, "eggs": 3}
source to share
It's important to add that this doesn't work for nested JSON So if you have
# Wrong
data = {'param1': {'a':[100, 200]},
'param2': 'value2',
'param3': False}
# You have to convert values into string:
data = {'param1': json.dumps({'a':[100, 200]}),
'param2': 'value2',
'param3': json.dumps(False)}
source to share