You have an @handle and want the profile picture in an <img>. On X that used to be one unauthenticated URL. It no longer is. Here are the options as of October 2026.
1. The official X API
The X API returns profile_image_url on the user object (GET /2/users/by/username/:username?user.fields=profile_image_url). It works, but:
- you need a developer account and a bearer token, so it cannot run in a browser
- API access is paid, and the free tier is very limited
- the URL it returns is a
_normal48×48 image; you replace_normalwith_400x400or remove it for the original size
Fine if you already pay for X API access. Overkill for showing an avatar.
2. Hotlinking pbs.twimg.com
The image itself lives at a URL like https://pbs.twimg.com/profile_images/<id>/<hash>_400x400.jpg. You cannot build that URL from the handle: the id and hash change every time the user uploads a new picture. You need to fetch it from somewhere first, then it goes stale the next time they change their photo.
3. An avatar URL that takes the handle
<img src="https://avatarsapi.com/x/jack" alt="@jack">
avatarapi resolves the handle on each cache miss, validates that the result is a real image, and serves the bytes from the same URL. No key, no token, nothing on your server. When the user changes their picture, it shows up after the cache lifetime: 7 days by default, or anything from 1 hour to 28 days with ?ttl= on a Starter Project. ?size= sets the square size:
<img src="https://avatarsapi.com/x/jack?size=96" alt="@jack">
If the account does not exist or has no picture, you get a 404 with a JSON body whose code is ENOTFOUND, so onerror can swap in a placeholder:
<img
src="https://avatarsapi.com/x/jack"
onerror="this.onerror=null; this.src='/default-avatar.svg'"
alt="">
Want the underlying URL instead of the bytes? Add ?json:
curl "https://avatarsapi.com/x/jack?json"
{
"version": 1,
"data": { "url": "https://…", "source": "x", "kind": "username" }
}
unavatar offers the same idea at unavatar.io/x/:handle; we compare the two here.
Same pattern, other platforms
The URL shape is the same for the other 71 Sources: /github/:user, /twitch/:user, /bluesky/:handle, /youtube/:handle, /tiktok/:user, and more. The full list is at avatarsapi.com/sources.
Which to use
Use the X API if you already have paid access and need other profile fields. Use an avatar URL if all you need is the picture in a UI.
https://avatarsapi.com/github/torvalds in an <img src>. No key, no signup. Read the docs or create a Project.