Free and self-hostable API to fetch favicons from any website.
See the codeA free & self-hostable favicon API service built with TypeScript, Hono, and Bun. Fetch and serve website favicons with multiple format options, intelligent fallbacks, and proper HTTP caching.
Powered by Vemetric
# Install dependencies
bun install
# Start development server (with hot reload)
bun run dev
# The server will start on http://localhost:3000
Option 1: Use Pre-built Image from Docker Hub
# Run with default settings
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
vemetric/favicon-api
# Or run with custom configuration
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
-e PORT=3000 \
-e DEFAULT_IMAGE_URL=https://example.com/default-favicon.png \
-e USE_FALLBACK_API=true \
-e CACHE_CONTROL_SUCCESS=604800 \
-e CACHE_CONTROL_FALLBACK=604800 \
-e CACHE_CONTROL_ERROR=604800 \
-e REQUEST_TIMEOUT=5000 \
-e MAX_IMAGE_SIZE=5242880 \
-e ALLOWED_ORIGINS=* \
-e BLOCK_PRIVATE_IPS=true \
vemetric/favicon-api
# Check it's running
curl http://localhost:3000/health
Option 2: Build from Source
# Build the image
docker build -t favicon-api .
# Run the locally built image
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
favicon-api
GET /<domain>&response=<json|image>&size=<number>&format=<png|jpg|webp>&default=<url>
size (optional): Desired image size in pixels (16-512)format (optional): Image Output format - png, jpg, webpresponse (optional): Response format - image (default) or jsondefault (optional): Fallback image URL (overrides server config)Get favicon as image:
curl "http://localhost:3000/github.com"
Get favicon metadata as JSON:
curl "http://localhost:3000/github.com&response=json"
Resize favicon to 64x64:
curl "http://localhost:3000/github.com&size=64"
Convert to PNG:
curl "http://localhost:3000/github.com&format=png&size=128"
With custom fallback:
curl "http://localhost:3000/example.com&default=https://mysite.com/fallback.png"
Create a .env file (see .env.example):
DEFAULT_IMAGE_URL unset: use the bundled default.svg fallback imageDEFAULT_IMAGE_URL=https://example.com/default-favicon.png: use a custom fallback imageDEFAULT_IMAGE_URL=none: disable the default fallback image and return 404 when no favicon is foundCACHE_CONTROL_FALLBACK: cache time for fallback responses after favicon lookup fails, including default images and disabled-fallback 404 responsesThe application is a stateless processor with no built-in caching. It:
For production, add a caching layer in front (CDN or reverse proxy):
# Install dependencies
bun install
# Run development server (with hot reload)
bun run dev
# Run tests
bun test
# Run tests in watch mode
bun test --watch
# Type check
bun run typecheck
# Lint
bun run lint
# Format code
bun run format
Using Pre-built Image:
# Pull and run from Docker Hub
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
vemetric/favicon-api
# Verify it's running
curl http://your-server-ip:3000/health
Building from Source:
git clone https://github.com/vemetric/favicon-api.git
cd favicon-api
# Build and run
docker build -t favicon-api .
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
favicon-api
# Verify it's running
curl http://your-server-ip:3000/health
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Clone and run
git clone your-repo
cd favicon-api
bun install
bun run start
Cloudflare Setup:
BunnyCDN Setup:
The API searches multiple sources for favicons:
<link rel="icon"> tags<link rel="apple-touch-icon"> tagsmanifest.json)/favicon.ico, /apple-touch-icon.png)Favicons are ranked by quality (size, format, source) and the best one is returned.
When the primary favicon fetch fails (e.g., due to bot protection), the API can optionally fall back to Google's favicon service:
USE_FALLBACK_API=true): Queries Google's favicon APIdefault.svg if no custom default is configured, or 404 when DEFAULT_IMAGE_URL=noneThe Google API fallback is enabled by default and provides reliable results even for sites with strict bot protection. To disable it, set USE_FALLBACK_API=false in your environment configuration.
The following projects are using the Favicon API:
Are you using the Favicon API and wanna be listed here? Feel free to file a Pull Request!
This project was mainly coded using Claude Code. We're also using the following libraries:
TypeScript
98.2%
JavaScript
1.0%
Free and self-hostable API to fetch favicons from any website.
See the codeA free & self-hostable favicon API service built with TypeScript, Hono, and Bun. Fetch and serve website favicons with multiple format options, intelligent fallbacks, and proper HTTP caching.
Powered by Vemetric
# Install dependencies
bun install
# Start development server (with hot reload)
bun run dev
# The server will start on http://localhost:3000
Option 1: Use Pre-built Image from Docker Hub
# Run with default settings
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
vemetric/favicon-api
# Or run with custom configuration
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
-e PORT=3000 \
-e DEFAULT_IMAGE_URL=https://example.com/default-favicon.png \
-e USE_FALLBACK_API=true \
-e CACHE_CONTROL_SUCCESS=604800 \
-e CACHE_CONTROL_FALLBACK=604800 \
-e CACHE_CONTROL_ERROR=604800 \
-e REQUEST_TIMEOUT=5000 \
-e MAX_IMAGE_SIZE=5242880 \
-e ALLOWED_ORIGINS=* \
-e BLOCK_PRIVATE_IPS=true \
vemetric/favicon-api
# Check it's running
curl http://localhost:3000/health
Option 2: Build from Source
# Build the image
docker build -t favicon-api .
# Run the locally built image
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
favicon-api
GET /<domain>&response=<json|image>&size=<number>&format=<png|jpg|webp>&default=<url>
size (optional): Desired image size in pixels (16-512)format (optional): Image Output format - png, jpg, webpresponse (optional): Response format - image (default) or jsondefault (optional): Fallback image URL (overrides server config)Get favicon as image:
curl "http://localhost:3000/github.com"
Get favicon metadata as JSON:
curl "http://localhost:3000/github.com&response=json"
Resize favicon to 64x64:
curl "http://localhost:3000/github.com&size=64"
Convert to PNG:
curl "http://localhost:3000/github.com&format=png&size=128"
With custom fallback:
curl "http://localhost:3000/example.com&default=https://mysite.com/fallback.png"
Create a .env file (see .env.example):
DEFAULT_IMAGE_URL unset: use the bundled default.svg fallback imageDEFAULT_IMAGE_URL=https://example.com/default-favicon.png: use a custom fallback imageDEFAULT_IMAGE_URL=none: disable the default fallback image and return 404 when no favicon is foundCACHE_CONTROL_FALLBACK: cache time for fallback responses after favicon lookup fails, including default images and disabled-fallback 404 responsesThe application is a stateless processor with no built-in caching. It:
For production, add a caching layer in front (CDN or reverse proxy):
# Install dependencies
bun install
# Run development server (with hot reload)
bun run dev
# Run tests
bun test
# Run tests in watch mode
bun test --watch
# Type check
bun run typecheck
# Lint
bun run lint
# Format code
bun run format
Using Pre-built Image:
# Pull and run from Docker Hub
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
vemetric/favicon-api
# Verify it's running
curl http://your-server-ip:3000/health
Building from Source:
git clone https://github.com/vemetric/favicon-api.git
cd favicon-api
# Build and run
docker build -t favicon-api .
docker run -d \
-p 3000:3000 \
--name favicon-api \
--restart unless-stopped \
favicon-api
# Verify it's running
curl http://your-server-ip:3000/health
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Clone and run
git clone your-repo
cd favicon-api
bun install
bun run start
Cloudflare Setup:
BunnyCDN Setup:
The API searches multiple sources for favicons:
<link rel="icon"> tags<link rel="apple-touch-icon"> tagsmanifest.json)/favicon.ico, /apple-touch-icon.png)Favicons are ranked by quality (size, format, source) and the best one is returned.
When the primary favicon fetch fails (e.g., due to bot protection), the API can optionally fall back to Google's favicon service:
USE_FALLBACK_API=true): Queries Google's favicon APIdefault.svg if no custom default is configured, or 404 when DEFAULT_IMAGE_URL=noneThe Google API fallback is enabled by default and provides reliable results even for sites with strict bot protection. To disable it, set USE_FALLBACK_API=false in your environment configuration.
The following projects are using the Favicon API:
Are you using the Favicon API and wanna be listed here? Feel free to file a Pull Request!
This project was mainly coded using Claude Code. We're also using the following libraries:
TypeScript
98.2%
JavaScript
1.0%