How to display user's image in Microsoft Graph using python

Question:

I tried using
GET https://graph.microsoft.com/v1.0/me/photo/$value to get the user’s image/photo but it only returns an HTTP 200 status code. How can I get the binary data?

I’ve also tried using the content.property as suggested in a similar post but get a .format is not an attribute of the dict.

@app.route("/photo")
def get_photo():
    token = _get_token_from_cache(app_config.SCOPE)
    if not token:
        return redirect(url_for("login"))
    photo = requests.get(app_config.PHOTO_ENDPOINT,  
            headers={'Authorization': 'Bearer ' + token['access_token']})
    print(photo.status_code)
    return photo
Asked By: jgtrz

||

Answers:

Gets a profile photo, and optionally saves a local copy. Returns a tuple of the raw photo data, HTTP status code, content type, and saved filename. Refer to this sample.

def profile_photo(session, *, user_id='me', save_as=None):
    """Get profile photo, and optionally save a local copy.
    session = requests.Session() instance with Graph access token
    user_id = Graph id value for the user, or 'me' (default) for current user
    save_as = optional filename to save the photo locally. Should not include an
              extension - the extension is determined by photo's content type.
    Returns a tuple of the photo (raw data), HTTP status code, content type, saved filename.
    """

    endpoint = 'me/photo/$value' if user_id == 'me' else f'users/{user_id}/$value'
    photo_response = session.get(api_endpoint(endpoint),
                                 stream=True)
    photo_status_code = photo_response.status_code
    if photo_response.ok:
        photo = photo_response.raw.read()
        # note we remove /$value from endpoint to get metadata endpoint
        metadata_response = session.get(api_endpoint(endpoint[:-7]))
        content_type = metadata_response.json().get('@odata.mediaContentType', '')
    else:
        photo = ''
        content_type = ''

    if photo and save_as:
        extension = content_type.split('/')[1]
        filename = save_as + '.' + extension
        with open(filename, 'wb') as fhandle:
            fhandle.write(photo)
    else:
        filename = ''

    return (photo, photo_status_code, content_type, filename)
Answered By: Joey Cai

Alternate approach, based on the original question’s code, if you want to display the resulting image on a web page.

from base64 import b64encode

@app.route("/photo")
def get_photo():
    token = _get_token_from_cache(app_config.SCOPE)
    if not token:
        return redirect(url_for("login"))
    response = requests.get(
        app_config.PHOTO_ENDPOINT,  
        headers={'Authorization': 'Bearer ' + token['access_token']}
    )
    content_type = response.raw.getheader('Content-Type')
    return render_template('index.html',
                           photo_data=b64encode(response.content),
                           photo_content_type=content_type)

Then in the index.html template you can display the photo like so:

<html>
  <body>
    <img src="data:{{ photo_content_type }};base64,{{ photo_data }}" />
  </body>
</html>
Answered By: PaulR
Call Api: - 

    Axios.get('https://graph.microsoft.com/v1.0/me/photo/$value', {
                  headers: { 'Authorization': 'Bearer '+AccessToken },
                  responseType: 'blob'
                }).then(o => {
                  const url = window.URL || window.webkitURL;
                  const blobUrl = url.createObjectURL(o.data);
                  
                    self.setState({ imageUrl: blobUrl });
                })

JSX: -
 <img alt="image" src={this.state.imageUrl} />
Answered By: Asheesh Thakur

Here is what worked for me:

from base64 import b64encode

token = _get_token_from_cache(app_config.graphSCOPE)
aadPhotoURI = "https://graph.microsoft.com/v1.0/me/photo/$value"
response = requests.get(aadPhotoURI, headers={'Authorization': 'Bearer ' + 
    token['access_token']},)
content_type = response.raw.getheader('Content-Type')

return render_template(
    'usersettings.html',
    photo_data = b64encode(response.content).decode(),
    photo_content_type = content_type)

then in the .html page added:

<img class="account-img" alt="" src="data:{{ photo_content_type }};base64,{{ photo_data }}"/>

CSS for account-img:

.account-img {
    width: 40px;
    float: right;
    border-radius: 50%;
  }
Answered By: PCfromDC