HTTP Error 422: Unprocessable Entity - when calling API from Python (but curl works)

16,935

Solution 1

Why are you url-encoding the data? That's not what the curl version is doing. Dump it to JSON instead:

data = json.dumps(json_values)
req = urllib.request.Request(create_droplets_url, data)

Solution 2

I have received the same error and realized it has occurred due to the server side validation failed with your post data.

Solution:

use requests.post instead of urllib.request.Request then you could get the accurate error message for that serverside 422 error code.

Sample code:

import requests

API_URL = "***"
TOKEN = "***"
HEADERS = {
  "User-Agent": "Python API Sample",
  "Authorization": "Bearer " + TOKEN,
  "Content-Type": "application/json"
}
data = {
        "user_id": "***",
        "project_id": "***"
       }
json_data = json.dumps(data).encode('utf8')
response = requests.post(url=API_URL, headers=HEADERS, data=json_data)
print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))

Thanks :)

Share:
16,935
binaryanomaly
Author by

binaryanomaly

I am a binary anomaly

Updated on August 23, 2022

Comments

  • binaryanomaly
    binaryanomaly over 1 year

    When trying out the digitalocean v2 api I come across the following behaviour:

    curl -X POST "https://api.digitalocean.com/v2/droplets" \
        -d'{"name":"t002","region":"ams3","size":"512mb","image":"debian-7-0-x64","ssh_keys":[123]}' \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json"
    

    Works fine and the droplet gets created.


    Now when I do call it from python with:

    json_values = {'name': 's002', 'region': 'ams3', 'size': '512mb', 'image': 'debian-7-0-x64', 'ssh_keys': [123]}
    
    data = urllib.parse.urlencode(json_values)
    data = data.encode("utf-8")
    
    try:
        req = urllib.request.Request(create_droplets_url, data)
        req.add_header("User-Agent", uagent)  # set custom user agent
        req.add_header("Authorization", BearerToken)  # set custom user agent
    
        response = urllib.request.urlopen(req)
    

    I get back: HTTP Error 422: Unprocessable Entity with no further information. Am i doing something wrong on the python side? Thx


    Additional Info: I figured out that the problem must be with ssh_keys. If I remove that element everything works fine.

  • binaryanomaly
    binaryanomaly over 9 years
    Then I end up with: TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.