Favicon Setup in Five Minutes

2026-03-27 · SPUNK13 · spunk.bet

Four files cover every browser worth supporting

Favicon generators cheerfully hand you a zip of thirty-eight PNGs and a browserconfig.xml for Windows 8 tiles. Almost all of it is dead weight in 2026. What a current site needs is this:

FileWhy it exists
/favicon.icoA container bundling 16, 32 and 48 px. Browsers request it from the site root whether you link it or not, and it is what shows in bookmarks and older tooling.
icon.svgVector, one file, sharp at any size. Modern browsers prefer it when offered.
apple-touch-icon.png180×180, opaque background. iOS home-screen shortcuts ignore the manifest and composite transparency onto black.
icon-192.png, icon-512.pngReferenced from the web app manifest for installed PWAs and Android home screens.

The head markup is four lines:

<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">

Build the .ico from one master PNG

Start from a square PNG at 512 or 1024 px. ImageMagick 7 packs multiple resolutions into a single ICO in one pass:

magick icon.png -define icon:auto-resize=48,32,16 favicon.ico
magick icon.png -resize 180x180 -background white -alpha remove apple-touch-icon.png
magick icon.png -resize 192x192 icon-192.png
magick icon.png -resize 512x512 icon-512.png

On ImageMagick 6 the command is convert rather than magick. On macOS with nothing installed, sips -z 180 180 icon.png --out apple-touch-icon.png handles the PNG resizes, though sips cannot write multi-size ICO files. A finished favicon.ico with three sizes lands around 5-15 KB.

Design for 16 pixels, not for the logo sheet

At 16×16 a wordmark is a grey smudge. Take the single most distinctive element — one letter, one glyph, one silhouette — and drop everything else. Two practical rules: keep strokes at least 2 px wide at the 16 px rendering, and leave roughly 10% padding inside the square so the mark does not collide with the tab's rounded corners. Then actually check it: shrink the PNG to 16 px in an image viewer at 100% zoom before you ship, because a design that reads at 512 frequently does not survive the downsample.

An SVG favicon can be a data URI, within limits

You can skip the file entirely and inline the icon:

<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'
  viewBox='0 0 100 100'><circle cx='50' cy='50' r='48' fill='%23ff5f1f'/></svg>">

This saves a request and is genuinely useful for prototypes and single-file pages. Caveats: you must percent-encode # as %23 or the URL truncates at your first hex colour, use single quotes inside the attribute, and keep the payload small — a couple of kilobytes is fine, a traced logo of tens of kilobytes bloats every page that carries it. Data-URI favicons that lean on a text glyph render from the local font stack, so the same markup looks different on Windows, macOS and Android — draw shapes instead if consistency matters.

Make the icon respond to dark mode

A dark navy monogram vanishes against a dark tab strip. Because an SVG favicon is a document, media queries inside it work:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
  <style>
    path { fill: #14181f }
    @media (prefers-color-scheme: dark) { path { fill: #f2f4f8 } }
  </style>
  <path d="M6 26 16 5l10 21z"/>
</svg>

The query resolves against the browser chrome's theme, not the page's. The ICO fallback cannot do this, so choose a mid-tone colour there that survives both backgrounds.

Getting a changed favicon to actually appear

Favicons are cached harder than any other asset — browsers keep them in a separate store that a normal reload does not touch, and it is routine for an old icon to persist for days. The reliable fix is a new URL. Serve the icon from a versioned path such as /icon.svg?v=3 in the <link> tag and bump the number on every change. Note that the root /favicon.ico request is made without consulting your HTML, so it cannot be versioned — set a shorter Cache-Control: max-age=86400 on that one path and a long max-age on everything else. To verify locally, open the icon URL directly in a tab and hard-reload it there; that clears the entry the tab strip reads from.

Explore More

Free tools, guides, and resources.

Visit spunk.bet
400+ ToolsCasinoMemesAstrologyScam DB