# Image upload issue - Python

**URL:** <https://forum.ghost.org/t/image-upload-issue-python/30814>\
**Category:** Developer help\
**Created:** [June 15, 2022, 1:56pm UTC](https://forum.ghost.org/t/image-upload-issue-python/30814 "2022-06-15T13:56:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Benoit\_Baylin](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/benoit_baylin/32/17119_2.png) [@Benoit\_Baylin](https://forum.ghost.org/u/Benoit_Baylin)\
**Post date:** [June 15, 2022, 1:56pm UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/1 "2022-06-15T13:56:47Z")

</div>

Hello,

I am just trying to post an image, and following the documentation available for the admin api:

> **[Ghost Admin API Documentation](https://ghost.org/docs/admin-api/#images)**
>
> Manage content via Ghost's Admin API, with secure role-based authentication. Read more on Ghost Docs 👉

When I see the curl:

```auto
curl -X POST -F 'file=@/path/to/images/my-image.jpg' -F 'ref=path/to/images/my-image.jpg' -H "Authorization: 'Ghost $token'" -H "Accept-Version: $version" https://{admin_domain}/ghost/api/admin/images/upload/

```

It translates to:

```auto
import os

import requests

token' = os.getenv('token'')
version = os.getenv('version')

headers = {
    'Authorization': f"'Ghost {token'}",
    'Accept-Version': f"{version}",
}

files = {
    'file': open('/path/to/images/my-image.jpg', 'rb'),
    'ref': (None, 'path/to/images/my-image.jpg'),
}

response = requests.post('https://{admin_domain}/ghost/api/admin/images/upload/', headers=headers, files=files)

```

In python,  
There is already a difference between the ref in the curl and the one in the documentation.

Whatever I try, my best result is a 415 error code:

```auto
'{"errors":[{"message":"Please select a valid image.","context":null,"type":"UnsupportedMediaTypeError","details":null,"property":null,"help":null,"code":null,"id":"46fff9b0-ecb1-11ec-9c4b-e5f617404273"}]}'

```

I tried both jpg and png. I saw different things online, but I guess they were linked to other version of the api.

**EDIT1:**

I forgot indeed the content-type header.  
If i go with

```auto
    headers = {'Authorization': 'Ghost {}'.format(token),
               'Accept-Version': "v1",
               'Content-Type': 'multipart/form-data;'}

```

I now get a Error code 422:

```auto
{"message":"Please select an image.","context":null,"type":"ValidationError"

```

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![Kevin](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/kevin/32/32_2.png) [@Kevin](https://forum.ghost.org/u/Kevin)\
**Post date:** [June 15, 2022, 4:52pm UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/2 "2022-06-15T16:52:09Z")

</div>

Curl automatically sets the mime type header for some file extensions. If your language/library of choice does not do the same then you’ll need to set the type header manually

Some further info on Curls behaviour can be found in this question [How does `curl` on the command line determine the MIME type of a file being uploaded? - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/396385/how-does-curl-on-the-command-line-determine-the-mime-type-of-a-file-being-uplo)

---

<div class="post-metadata">

**Author:** ![Benoit\_Baylin](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/benoit_baylin/32/17119_2.png) [@Benoit\_Baylin](https://forum.ghost.org/u/Benoit_Baylin)\
**Post date:** [June 15, 2022, 5:09pm UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/3 "2022-06-15T17:09:55Z")

</div>

Thank you for your prompt answer.  
I edited the question with the updated header, as per the documentation indeed, adding the multiform/part-data type.

But I still get another error.

Any idea of the correct way to upload an image using Python?

Thanks

---

<div class="post-metadata">

**Author:** ![themeix](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/themeix/32/4472_2.png) [@themeix](https://forum.ghost.org/u/themeix)\
**Post date:** [May 21, 2023, 11:29am UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/4 "2023-05-21T11:29:02Z")

</div>

@Benoit_Baylin Did you get any solution for that? I am facing a similar issue.

---

<div class="post-metadata">

**Author:** ![Abdul\_Azeem](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/abdul_azeem/32/24508_2.png) [@Abdul\_Azeem](https://forum.ghost.org/u/Abdul_Azeem)\
**Post date:** [May 21, 2023, 11:29am UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/5 "2023-05-21T11:29:25Z")

</div>

Hey did you get any solution?

I am facing the same issue:

{“errors”:[{“message”:“Please select an image.”,“context”:null,“type”:“ValidationError”,“details”:null,“property”:null,“help”:null,“code”:null,“id”:“658e71a0-f7c7-11ed-a43a-35330461017c”,“ghostErrorCode”:null}]}

---

<div class="post-metadata">

**Author:** ![yova](https://avatars.discourse-cdn.com/v4/letter/y/b2d939/32.png) [@yova](https://forum.ghost.org/u/yova)\
**Post date:** [October 22, 2023, 5:44pm UTC](https://forum.ghost.org/t/image-upload-issue-python/30814/6 "2023-10-22T17:44:33Z")

</div>

For future reference, this codes works for me:

```python
import requests # pip install requests
import jwt	# pip install pyjwt
from datetime import datetime as date

# Admin API key goes here
key = ''

# Split the key into ID and SECRET
id, secret = key.split(':')

# Prepare header and payload
iat = int(date.now().timestamp())

header = {'alg': 'HS256', 'typ': 'JWT', 'kid': id}
payload = {
    'iat': iat,
    'exp': iat + 5 * 60,
    'aud': '/admin/'
}

# Create the token (including decoding secret)
token = jwt.encode(payload, bytes.fromhex(secret), algorithm='HS256', headers=header)

# Make an authenticated request to create a post

url = 'https://ghost.test.com/ghost/api/admin/images/upload/'
headers = {'Authorization': 'Ghost {}'.format(token)}

with open("test.jpg", "rb") as file:
	files = {'file': ('test.jpg', file, 'image/jpeg')}
	r = requests.post(url, files=files, headers=headers)

print(r.json())

```

It seems to be important to explicitely set the MIME type, as to `image/jpeg` in this example. I still had to [install the sharp](https://github.com/TryGhost/Ghost/issues/10421#issuecomment-1774154043) image processing library to make upload with python work.
