GitHub serves every avatar through avatars.githubusercontent.com with a size parameter stuck on the end. You've seen these URLs if you've ever opened devtools on a PR page:
https://avatars.githubusercontent.com/u/1?s=40&v=4
I was curious what s actually does, so I pulled the same avatar at seven different values and measured the bytes that came back.
s=40 3,144 bytes
s=80 10,710 bytes
s=128 25,298 bytes
s=260 94,255 bytes
s=400 215,383 bytes
s=460 282,530 bytes
s=1000 282,530 bytes
Two things fall out of that.
460 is the ceiling. Ask for 1000 and you get the 460 file back, byte for byte. GitHub stores your avatar at 460x460 and throws away everything above it, whatever you uploaded.
Then look at the top row again. The avatar next to your name on every issue comment, every review, every commit in the timeline, is 3,144 bytes. That's 1.1% of the file GitHub is holding for you.
Nobody sees your profile page
Think about where your face actually appears on GitHub.
Your profile page renders it at 260px. That page gets visited when someone is deliberately looking you up, which is rare.
Everywhere else it's 40px. Comment threads, review requests, the contributors list, the commit history. 40 pixels, on a screen, next to a username.
So the picture you agonised over is being judged at roughly the size of this: ●
At 40px you have about 1,600 pixels to work with. A face fills maybe half of that. You're not communicating an expression at that resolution. You're communicating a shape and two or three colours.
The bit that surprised me
I assumed the small sizes were just the big file scaled down in the browser. They're not. GitHub is generating and caching a separate encode at each size, and the compression at 40px is aggressive enough that fine detail is gone before it reaches the client.
Which means the usual advice, upload the highest resolution you have, is only half right. Resolution above 460 does nothing on GitHub. What matters is whether the image still reads when a JPEG encoder has 3KB to describe it.
Two things survive that budget: contrast between the subject and the background, and how much of the frame the face occupies. Everything else, the texture in your jumper, the bookshelf behind you, the lanyard, turns into mush.
Every platform disagrees with every other platform
This is where it gets annoying if you keep one photo across your accounts.
| Platform | Stored | Rendered small | File cap |
|---|---|---|---|
| GitHub | 460x460 | 40px in threads | 1MB |
| up to 7680px wide | ~48px in feed | 8MB | |
| Slack | 512 to 1024 | 24px in message list | 1MB |
| Discord | 512 recommended | 128px, often 32px in member list | 8MB |
I've checked GitHub myself. The others come from each platform's own documentation, so treat them as roughly right rather than gospel, and note that Slack's 1MB cap is a lot tighter than people expect.
The practical version: export one square at 512x512, keep it under 1MB, and every platform in that table will take it and scale down cleanly. 512 divides evenly into 256, 128, 64 and 32, which means fewer resampling artefacts on the small renders than you'd get from, say, 460 or 400.
If you want to check the crop at several sizes before you commit, a free profile picture editor will do the square crop and the export without opening anything heavier.
What this changes about the photo itself
I went back through my own avatars with the 40px test in mind and the pattern was pretty clear.
The ones that worked had the face taking up most of the frame and a background that was one flat tone away from my skin and hair. The ones that didn't were technically better photographs. Nice depth of field, interesting environment, more of my shoulders in shot. At 40px they read as a grey smudge.
So the checklist is short:
- Crop tighter than feels right. Chin to just above the hairline.
- Pick a background that contrasts with your hair, not with your shirt.
- Look at it at 40px before you upload. Zoom out in your image viewer until it's the size of a favicon. If you can't tell it's you, nobody else can either.
- Skip the sunglasses, the hat brim shadow, and the busy patterned shirt. All three vanish or turn to noise.
Step 3 is the one people skip and it's the only one that actually tests anything.
If you don't have a usable photo
Plenty of us don't. I went about four years with a photo my flatmate took in a kitchen because the alternative was booking a studio.
The generated options have got good enough to be worth a look. You can run a free AI headshot generator on a handful of selfies and see what comes out before paying for anything.
One thing that carries over from the 40px problem: the prompt controls framing and background separation, which are exactly the two variables that decide whether the result survives being shrunk. Tight crop and flat background beat cinematic lighting every time at this size. There's a decent breakdown of prompt patterns that survive a diffusion model if you want to skip the trial and error.
Try it on your own
for s in 40 80 128 260 460 1000; do
echo -n "s=$s "
curl -sL "https://avatars.githubusercontent.com/u/YOUR_ID?s=$s&v=4" \
-o /dev/null -w '%{size_download} bytes\n'
done
Swap YOUR_ID for your numeric GitHub user ID, which you can get from https://api.github.com/users/YOUR_USERNAME.
If your 460 number is close to 1MB you're near GitHub's upload cap and the smaller encodes are working harder than they need to. Re-export at 512 and it'll come down a lot.
Disclosure: I work on BetterPic, one of the tools linked above.
Top comments (0)