Free · Open · Zero config

Identicon generator
for every user.

Free pixel-art avatar API · deterministic · no auth · works in any app

Drop a username into a URL. Get back a pixel-art identicon — unique to that string, reproducible forever. No uploads, no accounts, no fuss.

Unique identicons
4 Pattern styles
No auth Point & render
36 unique identicons — one character apart
Generator

Live identicon generator

Type any username, email, UUID, or string. The same input always produces the same pixel-art identicon. Customize palette, grid density, and shape — then export.

Size previews
Input
Color
Grid5×5
StyleAuto
Seed0
Hash
Grid density
Pattern style
Shape
Palette
Custom colors
Fill
Accent
BG
Preview background
Variation seed
Seed 0
Live API URL — updates as you type
https://icofy.vercel.app/api/icon/icofy?size=256
Keyboard shortcuts
Space Variation → ← Step seed R Random Ctrl D Download S Save Esc Clear
Saved · 0 icons
No saved icons yet. Press ♡ Save to bookmark one.
Gallery

Sample identicons

A selection of generated pixel-art icons. Click any to load it in the generator.

Batch

Generate many at once

Paste a list of usernames, emails, or any strings — one per line. Up to 200 at a time. Download all as individual PNGs.

Uses your current grid and style settings from the generator above.

How it works

Deterministic by design

Every identicon is a pure function of its input. No state, no storage, no randomness — the same string always produces the same pixel-art icon.

01
Hash the input
Your string is run through a djb2 hash function. The 32-bit output seeds everything — color, pattern, style. Any string works: username, email, UUID, or arbitrary text.
hash = djb2("alice") → 0x6D2C3E1A
02
Derive color & pattern
Hue is derived from hash × 137.508 mod 360 — the golden angle — ensuring perceptually distinct colors across similar inputs. A symmetric pixel grid is filled using the hash as a PRNG seed.
hue = (hash × 137.508) % 360
grid = prng(hash, gs=5)
03
Render on demand
Identicons are rendered as PNG on request — no storage, no CDN warming. Because output is deterministic, responses are perfectly cacheable at the edge indefinitely.
Cache-Control: public, max-age=31536000
ETag: derived from input hash
Developer API

One URL. Any app.

No SDK. No auth. Point an <img> tag at the endpoint and you're done. The Live URL in the generator above updates as you type — copy it directly.

Reference
GET https://icofy.vercel.app/api/icon/{input}?size={px}&bg={hex}&grid={4–7}&style={0–3}
Param
Type
Notes
input
string
Any UTF-8 string, URL-encoded. Required. Same input → same identicon, always.
size
integer
Output in px. Default 80. Max 512.
bg
string
Background hex without #. Omit for transparent. Useful for email clients.
grid
integer
Pixel density 47. Default 5. Higher = more detail.
style
integer
Pattern preset: 0=Classic 1=Dense 2=Sparse 3=Border. Omit for auto.
// Paste directly into any <img src> — the Live URL in the generator mirrors this img.src = `https://icofy.vercel.app/api/icon/icofy?size=128`; // Or fetch as blob (canvas, File API, etc.) async function getAvatar(username, size = 80) { const url = `https://icofy.vercel.app/api/icon/${encodeURIComponent(username)}?size=${size}`; return URL.createObjectURL(await (await fetch(url)).blob()); }
<!-- Works in any server-rendered template —> <img src="https://icofy.vercel.app/api/icon/icofy" alt="icofy avatar" width="80" height="80" /> <!-- Email-safe: white background, no transparency —> <img src="https://icofy.vercel.app/api/icon/icofy?size=128&bg=ffffff" width="128" height="128" />
import urllib.parse def icofy_url(username: str, size: int = 80, bg: str = None) -> str: encoded = urllib.parse.quote(username, safe="") url = f"https://icofy.vercel.app/api/icon/{encoded}?size={size}" if bg: url += f"&bg={bg}" return url url = icofy_url("icofy", size=128) url_email = icofy_url("icofy", size=128, bg="ffffff")
export function Avatar({ username, size = 80, className }) { // Fetch 2× for retina; render at display size const src = `https://icofy.vercel.app/api/icon/${encodeURIComponent(username)}?size=${size * 2}`; return ( <img src={src} alt={`${username} avatar`} width={size} height={size} style={{ imageRendering: "pixelated" }} className={className} /> ); } <Avatar username="icofy" size={64} />
# Transparent background curl -o avatar.png "https://icofy.vercel.app/api/icon/icofy?size=256" # White background curl -o avatar.png "https://icofy.vercel.app/api/icon/icofy?size=256&bg=ffffff" # 7×7 grid, Dense style curl -o avatar.png "https://icofy.vercel.app/api/icon/icofy?size=256&grid=7&style=1"
Error responses
400Missing inputNo {input} path segment provided.
400Invalid sizesize must be an integer between 1 and 512.
400Invalid gridgrid must be an integer between 4 and 7.
429Rate limitedSustained high-volume traffic. Use Cache-Control to avoid repeat fetches.
Use case

No more grey blobs.

The moment a user signs up, they already have an identicon — derived from their identifier, consistent everywhere, forever.

Without icofy
alice_dev
Generic placeholder
With icofy
alice_dev
Unique, always theirs
Register — your app
Auto-generated identicon Updates as you type
1

User signs up

You have their username, email, or ID. That's all icofy needs.

2

Construct the URL

No file uploads, no cloud storage. One URL, rendered on demand, cached at the edge indefinitely.

3

It's theirs, always

Same input → same identicon, deterministically. Works in your app, in emails, in PDFs — everywhere.

Next.js / React