Try it Live
Features
🎲 Deterministic
Same input always generates the same avatar. Perfect for user profiles.
⚡ Fast
File-based caching ensures instant delivery for previously generated avatars.
🎨 Unique
1.27 billion possible combinations ensure collision-resistant generation for ~1M users.
📦 Simple
Just hit a URL with any string. No API keys, no auth, no hassle.
API Documentation
curl https://avatar.2389.dev/avatar/test@example.com.svg
curl https://avatar.2389.dev/avatar/test@example.com.svg/info
curl https://avatar.2389.dev/avatar/user@example.com/bundle \
--output avatar_bundle.zip
# Optional: specify which animations to include
curl "https://avatar.2389.dev/avatar/user@example.com/bundle?animations=idle,emotes" \
--output avatar_bundle.zip
idle- 4 frames (idle_0, idle_1, idle_2, idle_3)emotes- 5 frames (happy, sad, surprised, angry, bored)vowels- 5 frames (vowel_A, vowel_E, vowel_I, vowel_O, vowel_U)
Usage Examples
HTML Image Tag
<img src="https://avatar.2389.dev/avatar/user@email.com.svg" width="60" height="60" />
Markdown

Random String
<img src="https://avatar.2389.dev/avatar/x7k9m2p5q8.svg" width="60" height="60" />
CSS Background
.profile {
background-image: url('https://avatar.2389.dev/avatar/user123.svg');
background-size: cover;
}
JavaScript Fetch
const response = await fetch('/avatar/user@example.com.svg/info');
const config = await response.json();
console.log(config); // Avatar configuration details
🎬 Animations
Avatars support 19 animation frames for games and interactive applications:
- Emotes: happy, sad, surprised, angry, bored, neutral
- Idle animation: 4 frames for breathing/bobbing
- Lip-sync: 5 vowel mouth shapes (A, E, I, O, U)
CSS State Control (Universal SVG)
Universal SVG avatars contain all animation states in a single file (~3.8 KB gzipped). Switch between states instantly using CSS classes - no additional HTTP requests needed. The "idle" state automatically animates through 10 frames.
Interactive Demo
Select a state to see the avatar change in real-time (idle animates automatically):
agent
Code Example
Switching states is as simple as changing the SVG's CSS class:
// Fetch the universal SVG once
const response = await fetch('/avatar/user@example.com.svg');
const svgText = await response.text();
// Parse and insert into DOM (use DOMParser to preserve CSS selectors)
const parser = new DOMParser();
const svgDoc = parser.parseFromString(svgText, 'image/svg+xml');
const svgElement = svgDoc.documentElement;
document.getElementById('container').appendChild(svgElement);
// Switch states instantly by changing the class
svgElement.className.baseVal = 'agent happy'; // Show happy emote
svgElement.className.baseVal = 'agent idle_0'; // Back to idle
svgElement.className.baseVal = 'agent vowel_a'; // Lip-sync to 'ah' sound
// Idle animation loop (breathing/bobbing effect)
const idleFrames = ['idle_0', 'idle_1', 'idle_2', 'idle_3', 'idle_2', 'idle_1'];
let frameIndex = 0;
setInterval(() => {
svgElement.className.baseVal = `agent ${idleFrames[frameIndex]}`;
frameIndex = (frameIndex + 1) % idleFrames.length;
}, 150); // ~6.7 FPS for smooth breathing
// Shadow visibility control
svgElement.classList.add('no-shadow'); // Hide shadow
svgElement.classList.remove('no-shadow'); // Show shadow
Shadow Control
Avatars include a ground shadow by default. You can hide it using the no-shadow CSS class or the shadow URL parameter:
// Via CSS class (client-side)
svgElement.classList.add('no-shadow'); // Hide shadow
svgElement.classList.remove('no-shadow'); // Show shadow
// Via URL parameter (server-side)
/avatar/user@example.com.svg // Shadow visible (default)
/avatar/user@example.com.svg?shadow=false // Shadow hidden
/avatar/user@example.com.svg?frame=happy&shadow=false // Combined params
Performance Benefits
📦 Single File
All 20 states in one SVG (~3.8 KB gzipped) vs 20 separate files (92.3 KB total uncompressed)
⚡ Instant Switching
Zero latency state changes - just CSS class manipulation, no network requests
🎯 Better Caching
Single immutable resource means perfect browser cache hit rate
🚀 95% Fewer Requests
Load 1 file instead of 20 for complete animation support
Available States
- Idle frames (10):
idle_0throughidle_9- Independent eye/mouth combinations for natural idle animation - Emotes (5):
happy,sad,surprised,angry,bored- Matching eye/mouth pairs for expressions - Vowels (5):
vowel_a,vowel_e,vowel_i,vowel_o,vowel_u- Open eyes with vowel mouths for lip-sync
All states use the format agent [state_name] as the CSS class on the root <svg> element.