Developers
Avatars for every user, from one image URL
Turn an email address into a picture without storing a single image. Hash the address, drop the link into an img tag, and Visage handles sizes, fallbacks and ratings.
<img src="https://your-visage-address/avatar/HASH?s=80&d=identicon" width="80" height="80" alt="">1. Hash the email address
Trim any spaces around the address, lowercase it, then take its SHA-256 hash as 64 hexadecimal characters. The hash identifies the person without revealing the address. Older MD5 hashes are accepted too.
async function avatarUrl(email, size = 80) {
const data = new TextEncoder().encode(email.trim().toLowerCase())
const digest = await crypto.subtle.digest('SHA-256', data)
const hash = Array.from(new Uint8Array(digest))
.map(byte => byte.toString(16).padStart(2, '0'))
.join('')
return `https://your-visage-address/avatar/${hash}?s=${size}&d=identicon`
}2. Request the image
Add the hash to the avatar address. When someone has linked a picture to that email, you get their picture. When they have not, you get the fallback you ask for.
https://your-visage-address/avatar/HASHhttps://your-visage-address/avatar/HASH?s=200&d=robohash&r=gParameters
Every parameter is optional and has a short and a long name. You can also add a .jpg or .png to the hash if your platform expects a file extension.
| Parameter | Values | Default | What it does |
|---|---|---|---|
| s or size | 1 to 2048 | 80 | Width and height of the image in pixels. Avatars are always square. |
| d or default | mp, identicon, monsterid, wavatar, retro, robohash, initials, color, blank, 404, or an image URL | Visage logo | What to show when the hash has no avatar, or when the avatar is rated above r. A custom URL must be public, use http or https, end in an image extension and have no query string. |
| r or rating | g, pg, r, x | g | The highest rating your site allows. Pictures rated above it are replaced by the fallback. |
| f or forcedefault | y | off | Always return the fallback, even when an avatar exists. Useful for testing styles. |
| name | Any text | Profile name | Used by the initials style. Without it, Visage uses the public display name when there is one. |
| initials | 1 to 3 characters | None | Exact initials for the initials style. Takes priority over name. |
Fallback styles
Generated styles are drawn from the hash, so the same address always gets the same picture. They come back as crisp SVG images that scale to any size.
Mystery person
d=mpA calm, neutral silhouette that looks the same for everyone.
Identicon
d=identiconA geometric quilt pattern unique to every email.
Monster
d=monsteridA friendly little monster with its own colors, eyes and horns.
Wavatar
d=wavatarA cartoon face with its own expression and color scheme.
Retro
d=retroAn 8-bit, arcade-style pixel pattern.
Robot
d=robohashA robot assembled from heads, eyes, antennas and grills.
Initials
d=initialsInitials from a name, set on a color picked from the hash.
Color
d=colorA single solid color picked from the hash.
Blank
d=blankA fully transparent image.
URL builder
Try any address and options. The hash is computed right here in your browser, and the email never leaves this page.
SHA-256: hashing
Handy for previewing styles for a real address.
Preparing preview
https://your-visage-address<img src="https://your-visage-address" width="160" height="160" alt="" loading="lazy">Profile API
Read a public profile by email hash or username. Responses are JSON, can be called from any website, and never include the email address. Hidden profiles and unknown hashes return a 404.
GET https://your-visage-address/api/profiles/{hash or username}const response = await fetch(`https://your-visage-address/api/profiles/${hash}`)
if (response.ok) {
const profile = await response.json()
console.log(profile.display_name, profile.avatar_url)
}{
"hash": "b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514",
"username": "maya-torres",
"display_name": "Maya Torres",
"profile_url": "https://your-visage-address/maya-torres",
"avatar_url": "https://your-visage-address/avatar/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514",
"avatar_alt_text": "Maya smiling in front of a white wall",
"pronouns": "she/her",
"job_title": "Product designer",
"company": "Northwind Studio",
"location": "Lisbon, Portugal",
"description": "I design calm, accessible interfaces.",
"links": [
{ "label": "Portfolio", "url": "https://example.com/maya" }
]
}Caching and privacy
Five minute cache
Responses can be cached for five minutes, so a new picture reaches every site shortly after it is chosen.
Served from a CDN
Uploaded pictures are stored in sizes from 64 to 1024 pixels and delivered from a global CDN. The closest larger size is returned.
Hashes, never emails
Avatar and profile links only carry the hash. Pictures go live only after the owner confirms the address with a code.
See it with your own email
Create an avatar, then paste your hash into the builder above.