7

When a GitHub user signs up for an account, GitHub provides a default profile picture that looks something like this:

enter image description here

The user can set a custom profile picture based on instructions here.

The way I can think of is to download the current profile picture from the GitHub user, then download his default profile picture from https://github.com/identicons/USERNAME.png . Then compare these two pictures. But this solution is not beautiful.

Is there a beautiful way to determine whether a GitHub user uses the default profile picture or has set a custom profile picture? Like a boolean value I can check or something like this. Thanks.

hsluoyz
  • 2,739
  • 5
  • 35
  • 59

3 Answers3

0

GitHub would use the Gravatar service in order to fetch an image associated to a GitHub user email account.

You can query such an image through the Gravatar API. If there is none, that means a default auto-generated image will be used.

When there is no picture associated to an email, GitHub use the ?d=identicon parameter to generate a geometric pattern based on the email hash:

https://www.gravatar.com/avatar/05b6d7cc7c662bf81e01b39254f88a49?d=identicon

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for the reply. But I still didnget it very clearly. – hsluoyz Mar 06 '18 at 00:37
  • Thanks for the reply. But I still didn't get it very clearly. Take this user for example: https://github.com/abc, how to know it has used a custom avatar? Note: I didn't know his Email if it's hidden. I only know his username. – hsluoyz Mar 06 '18 at 00:55
  • @hsluoyz you do know his email, it is *not* hidden. Take any of his repos: https://github.com/abc/SoyuzRP, get the commit of his master branch (no clone necessary, use https://developer.github.com/v3/repos/commits/#get-a-single-commit, as in https://api.github.com/repos/abc/SoyuzRP/commits/master, and you will get his email. – VonC Mar 06 '18 at 06:59
  • the hash of "alastair.campbell@runbox.no" is 05b6d7cc7c662bf81e01b39254f88a49. Then I used this link to get the profile picture: https://www.gravatar.com/avatar/05b6d7cc7c662bf81e01b39254f88a49. But it doesn't seem to be right.. – hsluoyz Mar 08 '18 at 00:13
  • @hsluoyz that means Alastair has no gravatar asociated to it. Its geometric pattern (used by GitHub) would be: https://www.gravatar.com/avatar/05b6d7cc7c662bf81e01b39254f88a49?d=identicon – VonC Mar 08 '18 at 07:58
  • @hsluoyz Note: https://github.com/abc might be another Alaister Campbell, and his email is chartax@gmail.com, which does work: https://www.gravatar.com/avatar/061052358b0aa897f04d438c38dc475b – VonC Mar 08 '18 at 08:01
  • I don'y want to use Email, can you give a solution based on GitHub login? – hsluoyz May 03 '18 at 12:26
  • @YangLuo No, the Gravatar service seems to exclusively use an email as key. It is not based or is not using a login (like the GitHub login) – VonC May 03 '18 at 12:28
  • It's not robust to rely on user's Email, because it's not always easy to find. If the user has hidden his Email, or use another Email in his repos, or even has no repos, then I cannot get his Email. – hsluoyz May 03 '18 at 12:31
  • @YangLuo I agree, and this is by design: email can be hidden. Plus, I am not even sure that Gravatar is the only service used: https://www.quora.com/Why-does-GitHub-use-Gravatar-and-not-user-profile-picture-uploading – VonC May 03 '18 at 12:33
0

This is possible by specifying the ?size parameter and checking if the returned image's resolution is greater than what was specified.

This is because the ?size parameter is only supported on non-default profile pictures.

For example:

A default profile photo has a size greater than 40: https://github.com/asf.png?size=40

A non-default profile photo has a size of 40: https://github.com/samdenty.png?size=40

Sam Denty
  • 3,693
  • 3
  • 30
  • 43
-1

I needed to do this, and I figured that as a generated image, the pixels would be cleanly coloured in with no dithering.

import requests
from PIL import Image

# image_url = "https://avatars.githubusercontent.com/u/85327959" # a photograph
image_url = "https://avatars.githubusercontent.com/u/85325807?v=4" # a gravatar
img_data = requests.get(image_url).content
with open("avatar.jpg", "wb") as handler:
    handler.write(img_data)

image = Image.open("avatar.jpg")
colour_count = len(set(image.getdata()))

print(image.size, "colours:", colour_count)

if colour_count < 10:
    print("this is a gravatar")

What's going on here?

We download the image, then load it as a PIL Image. Then we make a set of the colours in pixels, so we only get the unique colours. If there are only 2 unique colours, then it's a gravatar, more and it's a photo. (I've set it to 10 to give me some breathing room because I don't want false negatives.)

You can construct the URL for the image using this technique.

https://github.com/twbs.png

or

https://github.com/npm.png?size=200

How I used it IRL

In a first year course, I wanted to check if users have updated their photos so that the tutorial team can match repos to people easily.

def has_real_photo(repo_path):
    repo = git.cmd.Git(repo_path)
    origin_url = get_origin_url(repo)
    owner = origin_url.split("/")[3]
    image_url = f"https://github.com/{owner}.png?size=40"
    img_data = requests.get(image_url).content
    with open("avatar.jpg", "wb") as handler:
        handler.write(img_data)

    image = Image.open("avatar.jpg")
    colour_count = len(set(image.getdata()))

    if colour_count > 10:
        block_image = blocky_photo(image)
        print(block_image)
        return True
    else:
        block_image = blocky_photo(image)
        print(
            f"Your GitHub profile picture only has {colour_count} colours.\n"
            "This makes me think it's the default avatar.\n"
            "Not like this:\n",
            block_image,
            """Like this:
            ╭───────────╮
            │  !!!!!!!  │
            │ /       \ │
            │ │  O  O │ │
            │<│    v  │>│
            │  \  ─── / │
            │   \____/  │
            ╰───────────╯\n"""
            "Go to https://github.com/settings/profile and upload a photo of your face.\n"
            "This really helps us understand who's who and be more useful in tutorials.",
        )
        return False


def blocky_photo(image):
    colour_map_list = list(
        zip(
            list(set(image.getdata())),
            ["█", "░", "▒", "▓", "X", "#", "%", "/", ":", "*"],
        )
    )
    colour_map = {x[0]: x[1] for x in colour_map_list}
    image = image.resize((20, 10), Image.NEAREST)
    pixels = list(image.getdata())
    width, height = image.size
    block_image = ""
    for i in range(len(pixels)):
        block_image += colour_map[pixels[i]]
        if (i + 1) % (width) == 0:
            block_image += "\n "
    return block_image

They have a set of tests that they run themselves, and that will print:

Your GitHub profile picture only has 2 colours.
This makes me think it's the default avatar.
Not like this:
 ████████████████████
 █████░░░░░░░░░░█████
 █████░░░░░░░░░░█████
 █████░░░████░░░█████
 █████░░░████░░░█████
 █████░░░████░░░█████
 ██░░░░░░░░░░░░░░░░██
 ██░░░░░░░░░░░░░░░░██
 ██░░░░░░████░░░░░░██
 ████████████████████
  Like this:
            ╭───────────╮
            │  !!!!!!!  │
            │ /       \ │
            │ │  O  O │ │
            │<│    v  │>│
            │  \  ─── / │
            │   \____/  │
            ╰───────────╯
Go to https://github.com/settings/profile and upload a photo of your face.
This really helps us understand who's who and be more useful in tutorials.
✘ You've got a photo for your GitHub account
Ben
  • 12,614
  • 4
  • 37
  • 69