API Reference

A simple JSON API to fetch a normalized 128×128 PNG favicon for any domain.

Checking API mode…

Quick start #

One GET request returns a JSON object containing a CDN URL to a normalized 128×128 PNG favicon plus cache metadata. The PNG itself is served separately by /cdn/favicons/{domain}.png and is cached for 7 days.

GET https://<this-host>/api/v1/favicon?url=https://github.com

        

        

        

        

        

Try it #

Send a real request to your own instance from the browser. The response JSON and the resulting CDN-cached PNG are shown below.

No image
 
(no response yet)

Authentication #

Every call to /api/v1/favicon needs an API key. Only the SHA-256 hash of each key is stored server-side - the raw key is shown exactly once at creation time.

Sending the key

Pass the key in one of two ways:


      

      

Creating keys

Keys are generated and managed through the bundled scripts/manage-keys.js CLI:

# Create a key for "customer A" on the pro plan
docker compose exec maflplus-favicon-api npm run keys:create -- --label "customer A" --plan pro

# List active keys with this month's usage counter
docker compose exec maflplus-favicon-api npm run keys:list

# Revoke a key by its visible prefix (kept in DB for audit history)
docker compose exec maflplus-favicon-api npm run keys:revoke -- --prefix fa_abcdefgh

Endpoint reference #

GET /api/v1/favicon?url={website}

Query parameters

Name Required Description
url Yes Absolute URL (or bare domain) of the website to look up. The host is extracted, lowercased and validated.
key If keys are required Optional alternative to the Authorization: Bearer header. Ignored when this instance does not require a key.

Successful response (HTTP 200)

The image bytes are not in the response body. Fetch the PNG from the url field instead - it points to /cdn/favicons/{domain}.png with a long Cache-Control.


      
Field Type Description
urlstringPublic CDN URL of the cached PNG (/cdn/favicons/{domain}.png).
domainstringNormalized hostname extracted from the input.
width / heightnumberAlways 128 × 128.
formatstringAlways "png".
sourceTypestringWhere the icon came from, in priority order: svg > manifest > apple-touch-icon > png > og-image > catalog fallbacks > external.
cachedbooleantrue if served from the 7-day disk cache, false if just generated.
cachedAtstring (ISO-8601)Timestamp of when the PNG was stored.

Errors #

All error responses are JSON with the shape { "error": ..., "code": ... }, plus extra context fields where useful (such as plan, limit, used, period on quota errors).

Status Code Meaning
400missing_url
invalid_url
The url query parameter is missing or could not be parsed.
401missing_api_key
invalid_api_key
No key was sent, or the provided key is not recognized / has been revoked.
422favicon_not_found
favicon_not_processable
No usable icon could be discovered for the domain, or the bytes could not be decoded.
429quota_exceededThe monthly call quota for this key has been reached. Resets on the 1st of next month (UTC).
500internal_errorUnexpected server error.

A request counts toward the monthly quota only when the API returns 200.

Plans & quotas #

Each API key is assigned a plan at creation time. A monthly limit of 0 means unlimited. Quotas reset on the 1st of every month (UTC).

Plan Monthly calls
free…
pro…
enterprise…

CDN route #

The url field in every successful response points here. It is publicly readable, requires no API key, and returns 404 until /api/v1/favicon has been called at least once for that domain.

GET https://<this-host>/cdn/favicons/{domain}.png
✓ URL copied