Discussions

python - Converting x-www-form-urlencoded query string to a dict - Stack Overflow
Given a query string from x-www-form-urlencoded form data. ... Or something close to that. Basically, something akin to the way this form data would be handled in PHP's $_POST variable: Array ( [data] => Array ( [foo] => bar [bar] => baz ) ) ... It's not the end of the world. I can easily call the values from the dict ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
web - How to convert python dict to raw url-encoded form data? - Stack Overflow
You need to tell python to make it UTF-8, and you need to ensure the content-type is set in the headers. headers: 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' More on stackoverflow.com
๐ŸŒ stackoverflow.com
Converting dictionary to url encoded data for passing application/x-www-form-urlencoded in python - Stack Overflow
@TarequzzamanKhan If that is a ... the urlencode line. Then the query string should be equal to the payload you specified. 2022-06-22T12:44:22.587Z+00:00 ... @ ้€†ใ•ใพ finally I got a solution and it works for me perfectly. I will add the answer later 2022-06-23T07:58:23.607Z+00:00 ... Find the answer to your question by asking. Ask question ... See similar questions with these tags. ... 13 Transform a python dict into string compatible with Content-Type:"application/x-www-form-urlen... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python requests dict as form-data - Stack Overflow
application/x-www-form-urlencoded doesn't say anything on nested data which is what the OP wants to pack (so that Pythons x["data"]["param1"] = "foo" becomes data[param1]=foo when POSTed). The single-level packing part will be dealt by the requests module properly, but the OP will need to flatten ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
June 8, 2017
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 6877497 โ€บ converting-x-www-form-urlencoded-query-string-to-a-dict
python - Converting x-www-form-urlencoded query string to a dict - Stack Overflow
Currently using this to manually converting it into 'real' python dict. However, there still might be unknown problems that I haven't met yet. from urllib.parse import parse_qs str_raw_data = str(bytes_raw_data, 'utf-8') # bytes to string formatted_data_dict = parse_qs(str_raw_data) data = {} for k, v in formatted_data_dict.items(): if len(v) == 1: data[k] = v[0] else: data[k] = v return data
Top answer
1 of 1
1

Your challenge is the encoding of the Chinese characters in python.

Doing some research around it, it seems that behind the scenes there is some fun going on with unicode and ascii.

You can see this - Try this as a debug line:

rawjson = {'toDate2': '08ๆœˆ26ๆ—ฅ', 'toWeek': 'END'}
encodedjson = urllib.parse.quote(json.dumps(rawjson))
print (encodedjson)

output is:

%7B%22toDate2%22%3A%20%2208%5Cu670826%5Cu65e5%22%2C%20%22toWeek%22%3A%20%22END%22%7D

Stick that in a URLdecoder = and you get:

{"toDate2": "08\u670826\u65e5", "toWeek": "END"}

The chinese characters have gone. You've now got \u6708 and \u65e5. It's not the expected format on the server so no wonder the server gives you a 500.

You need to tell python to make it UTF-8, and you need to ensure the content-type is set in the headers.

  • headers: 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
  • a UTF-8 string: json.dumps(payload, ensure_ascii=False).encode('utf-8')

This is a working script which returns a 200:


import requests
import urllib.parse
import json

#for copying simplicity from chrome devtools
null = None
false = False

#the json
payload = {
    "userType":"LTP001","startSite":"SK","endSite":"HKM","toDate":"2021-08-26","toDate2":"08ๆœˆ26ๆ—ฅ","toWeek":"ๅ‘จๅ››","backDate":"","backDate2":"","backWeek":"","endSiteName":"Hong+Kong,+Hong+KongMacau","startSiteName":"Shekou,+shenzhen","sailingType":"0","lineId":"SK-HKM","airportTime":null,"lineType":null,"toTime":null,"flightCode":null,"flightName":null,"flightNo":null,"flightId":null,"flightDate":null,"flightHours":null,"flightMinute":null,"chanId":"1","isSeckill":false,"isSeckills":false,"nightFlight":0,"batchNo":null,"hsyLineId":null,"memberId":null,
}

payload = urllib.parse.quote(json.dumps(payload, ensure_ascii=False).encode('utf-8'))
payload = payload.replace('%20','')
payload = 'siteResJson=' + payload

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-GB,en;q=0.9',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
Res_post = requests.post("https://www.cmskchp.com/sailingsJson", data=payload, headers=headers)

This is the response:

Top answer
1 of 1
1

The normal call to urllib.parse.urlencode should give you a string that's correct for sending as x-www-form-urlencoded data. However, to answer your question about the resulting string formatting...

urllib.parse.urlencode has a keyword argument called quote_via, which allows you to specify a method for how some characters like spaces or slashes are encoded, and by default they are done with urllib.parse.quote_plus where spaces are substituted with +. You can use urllib.parse.quote instead, which will get you a string like what you want.

The resulting string is a series of key=value pairs separated by '&' characters, where both key and value are quoted using the quote_via function. By default, quote_plus() is used to quote the values, which means spaces are quoted as a '+' character and โ€˜/โ€™ characters are encoded as %2F, which follows the standard for GET requests (application/x-www-form-urlencoded). An alternate function that can be passed as quote_via is quote(), which will encode spaces as %20 and not encode โ€˜/โ€™ characters. For maximum control of what is quoted, use quote and specify a value for safe.

import urllib.parse

data = {
   "name":"test name",
   "file_urls":[
      "/Users/tarequzzamankhan/Desktop/instagram.webp",
      "/Users/tarequzzamankhan/Desktop/instagram.webp"
   ],
   "file_type":"pdf",
   "user_name":"Tareq",
   "mobile":"018xxxxxxxxx",
   "address":"Dhaka",
   "email":"[email protected]"
}

# I didn't use doseq=True because you seem to want all the `file_urls` as a single argument
qs = urllib.parse.urlencode(data, quote_via=urllib.parse.quote)

print(qs)

Output:

In [24]: print(qs)
name=test%20name&file_urls=%5B%27%2FUsers%2Ftarequzzamankhan%2FDesktop%2Finstagram.webp%27%2C%20%27%2FUsers%2Ftarequzzamankhan%2FDesktop%2Finstagram.webp%27%5D&file_type=pdf&user_name=Tareq&mobile=018xxxxxxxxx&address=Dhaka&email=example%40mail.com
๐ŸŒ
Google Groups
groups.google.com โ€บ g โ€บ montrealpython โ€บ c โ€บ _vgurXuZu60
urllib: parsing multidimensional dictionaries
The API I need to do a POST to only accepts application/x-www-form-urlencoded Any ideas on how to solve this problem? My request is basically done like this: http://pastebin.com/KT0TywVP ยท `urllib.urlencode({'foo': 'bar', 'baz': 'bing'})` produces 'foo=bar&baz=bing', which all webservers will understand as being the keys 'foo' and 'baz' with the values 'bar' and 'bing', respectively. What you're trying to do with nested dictionaries doesn't make sense if you're forced to post to x-www-form-urlencoded - there is no "standard" for nested keys in URL parameters.
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 44436573 โ€บ python-requests-dict-as-form-data
Python requests dict as form-data - Stack Overflow
June 8, 2017 - requestsโ€‹.post(url, data=x['data'], headers={'content-type': 'application/x-www-form-urlencoded'}) Or better way would be to remove the data key from your dict and directly create dict as
Find elsewhere
๐ŸŒ
URL Encoder
urlencoder.io โ€บ python
How to encode URLs in Python | URLEncoder
This is a convenience function which takes a dictionary of key value pairs or a sequence of two-element tuples and uses the quote_plus() function to encode every value. The resulting string is a series of key=value pairs separated by & character. ... >>> import urllib.parse >>> params = {'q': ...
๐ŸŒ
URLDecoder
urldecoder.io โ€บ python
URL Decoding query strings or form parameters in Python | URLDecoder
>>> import urllib.parse >>> encodedStr ... application/x-www-form-urlencoded (e.g 'name=John+Doe&phone=+919999999999'), then you can use parse_qs or parse_qsl functions provided by urllib.parse package....
Top answer
1 of 3
200

The reason you're getting JSON is because you're explicitly calling json.dumps to generate a JSON string. Just don't do that, 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 the data value, it will be form-encoded, while if you pass 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'll see that the first request body is this (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}
2 of 3
17

Short answer with example:

import requests

the_data = {"aaa": 1, "bbb": 2, "ccc": "yeah"}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
# Execute the post
requests.post("http://bla.bla.example.com", data=the_data, headers=headers)
# You have POSTed this HTTP body: aaa=1&bbb=2&ccc=yeah (note, although the content-type is called urlencoded the data is not in the URL but in the http body)
# to this url: "http://bla.bla.example.com"

Requests library does all the JSON to urlencoded string conversion for you

References:

MDN Web docs, Requests lib post url-encoded form

๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 67810718 โ€บ how-to-convert-x-www-form-urlencoded-to-json-with-python-django
How to convert x-www-form-urlencoded to json with Python (Django) - Stack Overflow
From api i recive x-www-form-urlencoded data. data = 'leads[status][0][id]=29078079' when i try to convert it with urllib.parse.parse_qs or urllib.parse.unquote i got a dict like { ...
๐ŸŒ
YouTube
youtube.com โ€บ codelines
python requests post application x www form urlencoded - YouTube
Instantly Download or Run the code at https://codegive.com sure, i'd be happy to provide a tutorial on using python requests to make a post request with the...
Published ย  February 20, 2024
Views ย  745
๐ŸŒ
Python
bugs.python.org โ€บ issue24460
Issue 24460: urlencode() of dictionary not as expected - Python tracker
June 17, 2015 - This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide ยท This issue has been migrated to GitHub: https://github.com/python/cpython/issues/68648
๐ŸŒ
Python
docs.python.org โ€บ 3 โ€บ library โ€บ urllib.parse.html
urllib.parse โ€” Parse URLs into components โ€” Python 3.14.3 ...
Parse a query string given as a string argument (data of type application/x-www-form-urlencoded). Data are returned as a dictionary.