JSONDecoder Error – While accessing Google Translate API with Python
I am learning to use HTTP requests in Python, using this HTTP request provided by a TopCoder training challenge (learning purposes only! no compensation of any sort) in which you have to access the Google Translate API:
curl --location --request POST 'https://translate.google.com/translate_a/single?client=at&dt=t&dt=ld&dt=qca&dt=rm&dt=bd&dj=1&hl=%25s&ie=UTF-8&oe=UTF-8&inputm=2&otf=2&iid=1dd3b944-fa62-4b55-b330-74909a99969e&' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --header 'User-Agent: AndroidTranslate/5.3.0.RC02.130475354-53000263 5.1 phone TRANSLATE_OPM5_TEST_1' \ --data-urlencode 'sl=de' \ --data-urlencode 'tl=en' \ --data-urlencode 'q=Hallo'
and I’m wondering how to make the equivalent request in my Python application? Any help is appreciated.
So far I have:
- installed and imported
requests
- understood that I need to store my POST request in a variable and parse it with JSON.
The issue is that I get a JSONDecoder error
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\myname\Documents\Code\GoogleTranslateApiPy\env\lib\site-packages\requests\models.py", line 898, in json return complexjson.loads(self.text, **kwargs) File "c:\users\myname\appdata\local\programs\python\python38-32\lib\json\__init__.py", line 357, in loads return _default_decoder.decode(s) File "c:\users\myname\appdata\local\programs\python\python38-32\lib\json\decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "c:\users\myname\appdata\local\programs\python\python38-32\lib\json\decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
with this Python request (I tried to translate the curl request as best as I could):
import requests headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'AndroidTranslate/5.3.0.RC02.130475354-53000263 5.1 phone TRANSLATE_OPM5_TEST_1', } params = ( ('client', 'at'), ('dt', ['t', 'ld', 'qca', 'rm', 'bd']), ('dj', '1'), ('hl', '%s'), ('ie', 'UTF-8'), ('oe', 'UTF-8'), ('inputm', '2'), ('otf', '2'), ('iid', '1dd3b944-fa62-4b55-b330-74909a99969e'), ('', ''), ) response = requests.get('https://translate.google.com/translate_a/single', headers=headers, params=params)
I feel that there’s something fundamental I’m missing here. The request in the current documentation by Google for Translate differs from this provided request, but I’d like to know how I could get this way to work, in case I’m ever provided with a curl command like this in the future.
Two things:
- You must do a POST request (currently you are doing a get request)
- You are not including the body of the request. For example, the curl call includes url encoded data like this: data-urlencode ‘q=Hallo’. You must include this parameters in your post request too, the provided link shows you how. This are key values that will go inside a dictionary, for example {q: ‘Hallo’, …}
PS: I’m 90% sure that you should also convert to a dictionary the query params you currently have inside tuples. So, you’d have post with headers, params and data.
It’s not clear if you’re trying to use Google Translate API or scraping from the website.
If you’re using Google API, then have a look at their documentation cloud.google.com/translate/docs/reference/rest/v2/translate. Note this requires signing up and getting a free key.
Your code is specifying the content type as application/x-www-form-urlencoded
. However they return application-json
. You don’t need to specify content-type, and you don’t need to send a fake user-agent
.
Here is a working example:
import requests params = { 'key': 'ABCDED1234' # TODO This is a 41 characters API Key. You'll need to generate one (it's not part of the json certificate) 'q': 'cheese', # TODO supply the phraze you to transalte 'target': 'fr' } response = requests.get('https://translation.googleapis.com/language/translate/v2', params=params) response.raise_for_status() # this throws error if status is 4xx or 5xx results = response.json() translatedPhraze = results['data']['translations'][0]['translatedText'] print(translatedPhraze)
Output:
fromage
Also Google have produced their own set of APIs in python. This is generally the recommended approach (but I can see this is just a learning exercise). See pypi.org/project/google-cloud-translate/.