Favicon API

Favicon API

Turn a single image into a complete favicon package — every size, every platform, a drop-in HTML snippet, and a ready-to-deploy ZIP, over one POST request.

Upload one image, get back a full favicon package: every size every modern browser asks for, plus a site.webmanifest, the HTML snippet ready to paste into <head>, and a ZIP download URL.

# Generate a favicon package
curl -X POST https://jinero.online/api/v1/favicon/generate \
  -F "[email protected]" \
  -F "app_name=My App" \
  -F "theme_color=#0ea5e9"
const form = new FormData();
form.append("image", file);
form.append("app_name", "My App");
form.append("theme_color", "#0ea5e9");

const r = await fetch("https://jinero.online/api/v1/favicon/generate", { method: "POST", body: form });
const { download_url, html_snippet } = await r.json();

All endpoints are public — no key required. Favicon generation runs a Node toolchain (sharp) for every requested size, so the limit is tight.

# Anonymous limits (per IP):
#   POST /favicon/generate         3  req/min
#   GET  /favicon/download/{id}    10 req/min

# Max source image: 10 MB
# Session TTL after generation: 60 minutes

Submit a source image and per-platform flags. Returns a session ID, preview thumbnails, an HTML snippet, and a download URL for the ZIP. Apple, Android and standard favicons are emitted by default; Windows and Yandex are opt-in.

POST https://jinero.online/api/v1/favicon/generate
ParameterTypeDescription
image file (multipart) Source image — png, jpg, jpeg, svg, or webp. Max 10 MB. Square images give the best results.
app_name string Application name written into site.webmanifest. Max 100 chars.
theme_color string CSS color (hex or rgb) used for the address bar / theme-color meta tag.
background string Background color used for opaque PNG tiles where transparency is not supported.
display string Manifest display mode: standalone (default), browser, fullscreen, or minimal-ui.
orientation string Manifest orientation: any (default), portrait, or landscape.
apple_icon boolean Emit apple-touch-icon-*.png. Default: true.
android boolean Emit android-chrome-*.png. Default: true.
windows boolean Emit mstile-*.png + browserconfig.xml. Default: false.
yandex boolean Emit yandex-browser-50x50.png + yandex-browser-manifest.json. Default: false.
curl -X POST https://jinero.online/api/v1/favicon/generate \
  -F "[email protected]" \
  -F "app_name=Jinero" \
  -F "theme_color=#0ea5e9" \
  -F "background=#ffffff" \
  -F "apple_icon=true" \
  -F "android=true" \
  -F "windows=true"
const form = new FormData();
form.append("image", logoFile);
form.append("app_name", "Jinero");
form.append("theme_color", "#0ea5e9");
form.append("background", "#ffffff");
form.append("apple_icon", "true");
form.append("android", "true");

const r = await fetch("https://jinero.online/api/v1/favicon/generate", { method: "POST", body: form });
const data = await r.json();
document.querySelector("head").insertAdjacentHTML("beforeend", data.html_snippet);
window.location = data.download_url;
$response = Http::attach(
    "image",
    file_get_contents("logo.png"),
    "logo.png"
)->post("https://jinero.online/api/v1/favicon/generate", [
    "app_name"    => "Jinero",
    "theme_color" => "#0ea5e9",
    "apple_icon"  => true,
    "android"     => true,
]);
$package = $response->json();
Example response
{
  "success": true,
  "session_id": "8c1f2e7a-4b5d-4dca-9c3e-1d6f7a0b2c5e",
  "file_count": 27,
  "html_snippet": "<link rel=\"icon\" type=\"image/x-icon\" href=\"/favicon.ico\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\">\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n<meta name=\"theme-color\" content=\"#0ea5e9\">",
  "preview": [
    {"label": "favicon-16x16",    "url": "..."},
    {"label": "favicon-32x32",    "url": "..."},
    {"label": "apple-touch-icon", "url": "..."},
    {"label": "android-chrome-192", "url": "..."}
  ],
  "download_url": "https://jinero.online/api/v1/favicon/download/8c1f2e7a-…",
  "expires_in_minutes": 60
}

Stream the generated favicon-package.zip. Sessions stay valid for 60 minutes; afterwards the file is purged from temp storage.

GET https://jinero.online/api/v1/favicon/download/{session}
curl -L -o favicon-package.zip https://jinero.online/api/v1/favicon/download/8c1f2e7a-…
// Trigger a browser download
window.location.href = data.download_url;

A typical package with defaults (apple + android on, windows + yandex off) contains 16–18 files; with everything enabled, ~27.

favicon.ico                  # classic multi-resolution ICO
favicon-16x16.png            # browser tabs
favicon-32x32.png            # browser tabs (retina)
favicon-48x48.png            # taskbar
favicon-96x96.png            # Chrome desktop shortcut
favicon-192x192.png          # PWA / android
favicon-512x512.png          # PWA splash

apple-touch-icon.png         # iOS home screen (180×180)
apple-touch-icon-152x152.png # iPad
apple-touch-icon-120x120.png # iPhone retina
apple-touch-icon-precomposed.png

android-chrome-192x192.png
android-chrome-512x512.png
android-chrome-maskable-512x512.png

mstile-150x150.png           # Windows Start tile (windows=true)
browserconfig.xml            # Windows config (windows=true)
yandex-browser-50x50.png     # Yandex.Browser (yandex=true)
yandex-browser-manifest.json # Yandex meta (yandex=true)

site.webmanifest             # PWA manifest
snippet.html                 # paste-into-<head> markup

Standard HTTP semantics. Errors return JSON with a "message" field describing the failure.

// 400 — malformed session id on /download
{ "message": "Invalid session id" }

// 404 — session expired or unknown
{ "message": "Result not found or expired" }

// 422 — validation (unsupported file type, oversize image, invalid color)
{ "message": "The image field must be a file of type: png, jpg, jpeg, svg, webp." }

// 429 — rate limit exceeded (/generate = 3 req/min)
{ "message": "Too Many Attempts." }

// 422 — generator crashed (rare; original error is forwarded)
{ "message": "Failed to load source image (corrupt input?)" }

About the jinero.online Favicon API

Free REST API that turns a single source image into a deploy-ready favicon package — every icon size, the PWA manifest, and a drop-in HTML snippet, in one call.

One image in, full kit out

Upload PNG/JPG/SVG/WebP and receive every size browsers ask for — classic favicon.ico, Apple Touch, Android Chrome, PWA, Windows tiles, Yandex.

Drop-in HTML snippet

Response includes the exact <link> and <meta> tags ready to paste into your document <head> — no guessing.

PWA-ready manifest

site.webmanifest is generated with your app name, theme color, background, display mode and orientation — install-as-app works on day one.

No key required

Public endpoint, 3 generations/minute per IP. Get an API token for higher limits.

Frequently Asked Questions

No. The Favicon API is public. /generate is rate-limited to 3 requests/minute per IP because each call runs the sharp toolchain for every requested size. Sign up for an API token if you need more.

A square PNG or SVG at 512×512 or larger gives the best results across all sizes. Anything smaller than 192×192 will look soft on Android home screens. We accept png, jpg, jpeg, svg and webp up to 10 MB.

Classic favicon (ico + 6 PNG sizes), Apple Touch Icon (180/152/120 + precomposed), and Android Chrome (192/512 + maskable). Windows tiles and Yandex.Browser icons are opt-in via the windows=true and yandex=true flags — most modern stacks do not need them.

60 minutes from generation. After that the ZIP and previews are deleted from temp storage. If you need the bundle later, generate it again.

The snippet returned in html_snippet is opinionated and minimal — exactly the tags modern browsers consult. If your CMS needs extra meta tags (Open Graph icons, etc.), append them yourself; the icon paths in the ZIP match what is in the snippet.