This repository contains two variants of a high-performance service that fetches, caches, and serves website favicons:
www subdomains and redirects) for <link> tags before falling back to /favicon.ico.b64) to return a JSON object with a CORS-safe data: URI.Base URL: https://your-app-url.com/
All parameters and their values are case-insensitive. Parameters can be provided via URL query string or request headers, with query string values taking precedence.
domain (Required): The domain to fetch. e.g., google.com.s / size (Optional): The desired icon size. Default: 64.m / magic (Optional): Include the key (e.g., &m) to enable www fallback.b64 (Optional): Include the key (e.g., &b64) to receive a JSON response.key (Optional): An API key for authenticated requests.Request: GET /?domain=Github.com&S=128
200 OKContent-Type: image/png(raw image data)Request: GET /?domain=github.com&s=128&b64=TRUE
200 OKContent-Type: application/json{
"href": "[https://github.githubassets.com/assets/apple-touch-icon-144x144.png](https://github.githubassets.com/assets/apple-touch-icon-144x144.png)",
"base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhE..."
}
Request: GET /?domain=google.com&key=mysecretkey0
(Header-based authentication is also supported)
The Cloudflare Worker variant runs on Cloudflare’s edge network for the lowest possible latency. The deploy button will automatically guide you through creating the required KV namespaces.
Required Manual Step (After Deployment): For security, you must add your API keys as secrets after the initial deployment.
Settings -> Variables.Environment Variables, click Add variable, enter the name (e.g., AUTHN0), enter the secret value, and click Encrypt.Option 1: Deploy with Managed Redis (Production Ready)
Option 2: Deploy Manually or In-Memory
cd into it.docker-compose.yml to understand available environment variables.docker-compose.yml directly, OR.env file with your custom values (Docker Compose will use it automatically)docker-compose up --buildThe service will be available at http://localhost:8080.
If you prefer using a .env file instead of editing docker-compose.yml:
PORT=8080
REDIS_URL=redis://redis:6379
CACHE_ENABLED=true
CACHE_TTL_SECONDS=86400
REQ_TIMEOUT_MS=5000
HTML_PAYLOAD_LIMIT=250000
ICON_PAYLOAD_LIMIT=2097152
DEBUG=false
# Optional: DNS over HTTPS
# DOH1=https://dns.google/dns-query
# DOH2=https://cloudflare-dns.com/dns-query
# Optional: API Keys and Rate Limits
# AUTHN0=your_secret_key_here
# LIMIT0=rps:10,rpm:500
# Anonymous Rate Limits
LIMITA=rps:1,rpm:60
LIMITI=rpm:30
Variable keys (e.g., PORT, AUTHN0) are case-sensitive.
| Variable | Description | Default |
|---|---|---|
PORT |
The port the server listens on. | 8080 |
REDIS_URL |
Connection string for Redis. If not set, the app falls back to in-memory mode. | "" (none) |
DOH1, DOH2 |
Optional DoH endpoints. DOH1: https://cloudflare-dns.com/dns-query, DOH2: https://dns.google/dns-query. |
"" (none) |
DEBUG |
Set to true to enable detailed console logging for troubleshooting. |
false |
LIMIT_SEPARATOR |
Character for separating multiple rate limit rules. Defaults to ,. Set to ; for GCP. |
, |
CACHE_ENABLED |
Enables/disables caching (true/false). |
true |
CACHE_TTL_SECONDS |
Cache expiration time in seconds. | 86400 (24h) |
IN_MEMORY_CACHE_MAX_SIZE |
Max cache size (in bytes) for in-memory mode. | 52428800 (50MB) |
REQ_TIMEOUT_MS |
Milliseconds to wait for target sites. | 5000 (5s) |
HTML_PAYLOAD_LIMIT |
Max HTML size to download (in bytes). | 250000 (250KB) |
ICON_PAYLOAD_LIMIT |
Max icon file size to download (in bytes). | 2097152 (2MB) |
CUSTOM_USER_AGENT |
Override the default User-Agent string. | Mozilla/5.0 (Macintosh...) |
AUTHN[0-1000] |
API key. e.g., AUTHN0=key_abc. |
"" |
LIMIT[0-1000] |
Rate limit for the corresponding API key. e.g., LIMIT0=rps:10,rpm:500. |
"" |
LIMITA |
Global rate limit for all anonymous users. | rps:1,rpm:60 |
LIMITI |
Per-IP rate limit for anonymous users. Applied in addition to LIMITA. |
"" |
Limits are defined as a comma/semicolon-separated list of unit:value pairs or just value (defaults to rps).
rps (requests per second), rpm (minute), rph (hour), rpd (day).0: Blocks all requests for that key.rps:10,rpm:500, 10 (same as rps:10).Dual Licensed: Personal Non-Commercial OR Commercial
⚠️ Important: This software is available for personal, non-commercial use only under the free license.
Prohibited without commercial license:
Commercial licenses available: Contact https://www.kalman.co.il
Full terms: LICENSE.md