Maintained by Rep Graphics.
Crafatar serves Minecraft avatars based on the skin for use in external applications. Inspired by Gravatar (hence the name) and Minotar.
Image manipulation is done with pngjs (pure JavaScript PNG processing). 3D renders are created with node-canvas / cairo.
Please visit the website for details.
Our Main Site with docs for all our products.
Set EXTERNAL_URL in your .env if you are self-hosting under a different domain.
- Website: crafatar.euphoriadevelopment.uk
- Docs: euphoriadevelopment.uk/docs
- Join our Discord
- Open an issue on GitHub
Choose one setup path below.
Uses the provided docker-compose.yml with Redis and persistent volumes.
cp .env.example .env
docker compose up -dThen open http://localhost:3000.
- Use Docker Desktop with Linux containers enabled (WSL2 backend recommended).
- This image is Linux-based and is not a Windows container image.
PowerShell quick start:
Copy-Item .env.example .env
docker compose up -ddocker network create crafatar
docker run --net crafatar -d --name redis redis:7-alpine
docker run --net crafatar -v crafatar-images:/home/app/crafatar/images -e REDIS_URL=redis://redis:6379 -e CACHE_BACKEND=redis -p 3000:3000 docker.io/repgraphics/crafatar:latestIf you do not want Redis, use memory cache:
docker run -v crafatar-images:/home/app/crafatar/images -e CACHE_BACKEND=memory -p 3000:3000 docker.io/repgraphics/crafatar:latest- Install nodejs 24 (LTS).
- Install
redis-server(optional if usingCACHE_BACKEND=memory). - Run
npm ci. If that fails, it is usually due tonode-canvasdependencies. Follow this guide. - Copy
.env.exampleto.envand adjust values. - Run
npm start.
Crafatar is now available at http://0.0.0.0:3000.
- Import
pterodactyl egg/egg-crafatar.jsoninto your panel. - In the egg Docker Images field use either:
docker.io/repgraphics/crafatar:latestDocker Hub Crafatar|docker.io/repgraphics/crafatar:latest
- Configure the install variables:
SOURCE_REPO(defaultEuphoriaTheme/crafatar)SOURCE_REF(defaultmaster, can also be a tag likev2.3.2)
- Reinstall the server after importing/updating the egg so install scripts run and source files are placed in
/home/container. - Set
REDIS_URLto an external Redis endpoint if usingCACHE_BACKEND=redis.
By default, Docker builds skip tests for faster production builds. To run tests during build:
docker build --build-arg RUN_TESTS=true -t crafatar .This repository includes workers in .github/workflows:
ci.yml: runs tests on pushes and pull requests.release.yml: on tag push (for examplev2.3.0) it builds/pushes Docker image toghcr.io/<owner>/<repo>and creates a GitHub Release.integration.yml: optional full integration suite (manual trigger + daily schedule).
Create a release:
git tag v2.3.0
git push origin v2.3.0The release worker will publish the image tag and generate release notes automatically.
Run full integration tests manually from GitHub Actions (workflow_dispatch) or locally:
npm run test:integrationConfiguration is loaded from .env automatically (via dotenv) and falls back to defaults from config.js.
cp .env.example .envAVATAR_MIN,AVATAR_MAX,AVATAR_DEFAULT: avatar size bounds and default size in pixels.RENDER_MIN,RENDER_MAX,RENDER_DEFAULT: 3D render scale bounds and default scale.CACHE_LOCAL: how long cached profile/skin metadata is considered fresh (seconds).CACHE_BROWSER: HTTP cache max-age sent to clients (seconds).RETENTION_ENABLED: whentrue, periodically clears stale Redis keys and old image files.RETENTION_DAYS: maximum age (in days) before cached data/images are deleted.RETENTION_INTERVAL_HOURS: how often the cleanup job runs.CACHE_BACKEND: metadata cache backend (redis,memory, ornone).EPHEMERAL_STORAGE: whentrue, Redis is flushed on startup.CLOUDFLARE: toggles Cloudflare status hints on the index page.REDIS_URL: Redis connection string.- Example with password:
redis://:password@host:port - Example with TLS:
rediss://:password@host:port - Only
redis://andrediss://are accepted. If another scheme is provided (for examplehttp://), Redis caching is disabled at startup. - In containerized setups (e.g. Pterodactyl), avoid
localhostunless Redis runs in the same container.
- Example with password:
PORT,BIND: server listen port and bind address.EXTERNAL_URL: optional public base URL used in homepage/docs examples (e.g.https://crafatar.example.com). If empty, the URL is inferred from request/forwarded headers.EXTERNAL_HTTP_TIMEOUT: timeout for Mojang/external HTTP requests in milliseconds.DEBUG: whentrue, enables debug behavior and extra error details.LOG_TIME: whether log timestamps are enabled.SESSIONS_RATE_LIMIT: outgoing Mojang session requests allowed per second; empty disables this limiter.SOURCE_REPO: GitHub repo path used by the Pterodactyl egg installer when bootstrapping source files (formatowner/repo).SOURCE_REF: branch or tag used by the Pterodactyl egg installer (for examplemasterorv2.3.2).FACE_DIR,HELM_DIR,SKIN_DIR,RENDER_DIR,CAPE_DIR: optional custom storage directories (must end with/).
CACHE_BACKEND=redis(default): uses Redis for metadata cache.CACHE_BACKEND=memory: uses in-process memory cache (no Redis required; cache resets on restart).CACHE_BACKEND=none: disables metadata caching entirely.
- Redis is used as a cache layer; image generation still works when Redis is unavailable.
- Invalid
REDIS_URLvalues (wrong protocol/format) fall back to memory cache unlessCACHE_BACKEND=none. - A broken Redis endpoint will reduce cache efficiency and may increase upstream Mojang requests.
- Set
BIND=0.0.0.0when running behind panel/reverse proxies. - Use an external Redis service or separate Redis node and point
REDIS_URLto it (avoidlocalhostunless Redis is in the same container). CLOUDFLARE=trueis appropriate when traffic is proxied through Cloudflare.SOURCE_REPOandSOURCE_REFcontrol which source tree the egg installer downloads to/home/container.- After egg import/changes, run a server reinstall so the installation script is applied.
npm run audit
npm run audit:fixThese commands use lockfile-based auditing and safe remediation where possible.
Crafatar stores a lot of images on disk. For avatars, these are 8×8 px PNG images with an average file size of ~90 bytes. This can lead to issues on file systems such as ext4, which (by default) has a bytes-per-inode ratio of 16Kb. With thousands of files with an average file size below this ratio, you will run out of available inodes before running out of disk space. (Note that this will still be reported as ENOSPC: no space left on device).
Consider using a different file system, changing the inode ratio, or deleting files before the inode limit is reached.
Eventually you will run out of disk space and/or redis will be out of memory. Make sure to delete image files and/or flush redis before this happens.
npm testIf you want to debug failing tests:
# show logs during tests
env VERBOSE_TEST=true npm testIt can be helpful to monitor redis commands to debug caching errors:
redis-cli monitor