How to retrieve the skin of a Minecraft User (from Mojang) using Python 3

In this article, we will explain you how to easily retrieve the skin of a Minecraft player by its username using the Mojang API.

Skin Specification

Skins are served in a PNG format from Mojang's servers. The image dimensions may either be 64 by 32 pixels or 64 by 64 pixels. The former was used by Minecraft versions prior to 1.8, while the latter is accepted by Minecraft versions 1.8 and onwards. Positions of elements remain the same in 1.8, however there have been new "overlays" added to the skins file.

In order to retrieve the current skin of an user, you will need to access the Mojang API. In this case, the first request URL will be:

https://api.mojang.com/users/profiles/minecraft/{USERNAME}

You need to replace {USERNAME} with the username that you are looking for, for example https://api.mojang.com/users/profiles/minecraft/elrubius will return the following response:

{
    "name": "elrubius",
    "id": "11f1cc006cc84499a174bc9b7fa1982a"
}

The mentioned request will return the UUID of the Minecraft user. Now, to request the information about the player, you will need to request the following URL:

https://sessionserver.mojang.com/session/minecraft/profile/{USER_UUID}

Using the ID of the player by its username (obtained previously), you should be able to request once again to the API for the information of the textures, for example https://sessionserver.mojang.com/session/minecraft/profile/11f1cc006cc84499a174bc9b7fa1982a will return the following JSON response:

{
    "id": "11f1cc006cc84499a174bc9b7fa1982a",
    "name": "elrubius",
    "properties": [
        {
            "name": "textures",
            "value": "ewogICJ0aW1lc3RhbXAiIDogMTU5NTY0ODQyODczOSwKICAicHJvZmlsZUlkIiA6ICIxMWYxY2MwMDZjYzg0NDk5YTE3NGJjOWI3ZmExOTgyYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJlbHJ1Yml1cyIsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9hYzM3MzU3NTNjNzNjYzYwZWUxMjFkMzIyNGQ2ZDU2NDU5MzNlYWJjYmQzZDUyYzI3ZmZkMjEwNDNmMDQ4OTkyIgogICAgfQogIH0KfQ=="
        }
    ]
}

The first object in the properties array will contain 2 keys that specify the type, in this case the textures and its value, in Base64 format:

ewogICJ0aW1lc3RhbXAiIDogMTU5NTY0NjgzNDMzMSwKICAicHJvZmlsZUlkIiA6ICIxMWYxY2MwMDZjYzg0NDk5YTE3NGJjOWI3ZmExOTgyYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJlbHJ1Yml1cyIsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9hYzM3MzU3NTNjNzNjYzYwZWUxMjFkMzIyNGQ2ZDU2NDU5MzNlYWJjYmQzZDUyYzI3ZmZkMjEwNDNmMDQ4OTkyIgogICAgfQogIH0KfQ==

If you decode the obtained value from the Base64 format, the output will provide the following JSON:

{
    "timestamp": 1595646834331,
    "profileId": "11f1cc006cc84499a174bc9b7fa1982a",
    "profileName": "elrubius",
    "textures": {
        "SKIN": {
            "url": "http://textures.minecraft.net/texture/ac3735753c73cc60ee121d3224d6d5645933eabcbd3d52c27ffd21043f048992"
        }
    }
}

Which contains the skin of the user in the [textures][SKIN][url] property: http://textures.minecraft.net/texture/ac3735753c73cc60ee121d3224d6d5645933eabcbd3d52c27ffd21043f048992 in this case, the following image (which then serves the skin as Content-Type: image/png):

Skin Minecraft File

By simply knowing how this works, you will be able to write your own script to obtain the skin of a user in minecraft, however if you are looking for an easy and straightforward way to do it, the following Python 3 script will help you to understand it better.

Automatization to obtain the skin of a minecraft user

We will use the Requests package for Python, which is an elegant and simple HTTP library for Python. Requests is ready for the demands of building robust and reliable HTTP–speak applications, for the needs of today. You can install it using pip:

pip3 install requests

Once you are sure that the library is installed, you can use the following Script (get_skin.py) to download the skin of an user in Minecraft:

#!/usr/bin/env python3

import io
import sys
import json
import shutil

from base64 import b64decode

import requests

DEBUG = False
SIMULATE = False

userid_url = "https://api.mojang.com/users/profiles/minecraft/{username}"
userinfo_url = "https://sessionserver.mojang.com/session/minecraft/profile/{userid}"

class SimulatedResponse(object):
    def __init__(self, content, is_json, raw=None):
        self.content = content
        self.is_json = is_json
        self.status_code = 200
        self.raw = raw

    def json(self):
        if self.is_json:
            return json.loads(self.content)
        return None

def fail(msg, verbose_msg):
    print(msg, file=sys.stderr)
    if DEBUG:
        print(verbose_msg, file=sys.stderr)
    sys.exit(1)

def find_texture_info(properties):
    for prop in properties:
        if prop['name'] == 'textures':
            return json.loads(b64decode(prop['value'], validate=True).decode('utf-8'))
    return None

def get_url(url, **kwargs):
    if SIMULATE:
        content = None
        is_json = False
        raw = None
        # These files are not provided in the git repo because I consider them
        # kind of sensitive.  Feel free to provide your own in their place.
        if url.startswith('https://api.mojang.com/users/profiles/minecraft/'):
            with open('simulated_userid_response.json', 'r') as f:
                content = f.read()
            is_json = True
        elif url.startswith('https://sessionserver.mojang.com/session/minecraft/profile/'):
            with open('simulated_userinfo_response.json', 'r') as f:
                content = f.read()
            is_json = True
        else:
            with open('simulated_skin_response.png', 'rb') as f:
                content = f.read()
            is_json = False
            raw = io.BytesIO(content)
        return SimulatedResponse(content, is_json, raw)
    else:
        return requests.get(url, **kwargs)

def main():
    if len(sys.argv) < 2:
        print('Please provide a username', file=sys.stderr)
        sys.exit(1)

    username = sys.argv[1]

    r = get_url(userid_url.format(username=username))
    if r.status_code != 200:
        fail("Could not retrieve user ID for {username}".format(username=username),
             "{0} {1}".format(r.status_code, userid_url.format(username=username)))
    if DEBUG:
        print("{0} {1}".format(r.status_code, userid_url.format(username=username)), file=sys.stderr)
    userid = r.json()['id']

    r = get_url(userinfo_url.format(userid=userid))
    if r.status_code != 200:
        fail("Failed to download user info for {username}".format(username=username),
             "{0} {1}".format(r.status_code, userinfo_url.format(userid=userid)))
    if DEBUG:
        print("{0} {1}".format(r.status_code, userinfo_url.format(userid=userid)), file=sys.stderr)
    userinfo = r.json()
    texture_info = find_texture_info(userinfo['properties'])
    if texture_info is None:
        fail("Failed to find texture info for {username}".format(username=username),
             userinfo)

    try:
        skin_url = texture_info['textures']['SKIN']['url']
    except:
        fail("Failed to find texture info for {username}".format(username=username),
             texture_info)
    r = get_url(skin_url, stream=True)
    if r.status_code != 200:
        fail("Could not download skin for {username}".format(username=username),
             "{0} {1}".format(r.status_code, skin_url))
    if DEBUG:
        print("{0} {1}".format(r.status_code, skin_url), file=sys.stderr)

    with open("{username}.png".format(username=sys.argv[1]), 'wb') as f:
        shutil.copyfileobj(r.raw, f)

if __name__ == '__main__':
    main()

You will be able to run this script using:

python get_skin.py {username}

This will download the skin of the given username in the same directory.

Happy coding ❤️!

This could interest you

Become a more social person