Polyatic Favicon Generator
All tools

Favicon Generator

Turn an image, a letter or an emoji into a full favicon package — a multi-size .ico, PNGs, an apple-touch icon, a web manifest, icon.svg and the paste-ready HTML. An uploaded .svg stays vector: sanitised, then redrawn at every size. All in your browser; nothing is uploaded.

Letter or emoji
Text colour
Background
Shape
Site name (for the manifest)

Preview & download

16
32
48
180

Android maskable safe zone

No icon yet

Add a letter or an image and the safe-zone check runs here.

Android crops an installed app's icon to a circle, a squircle or a teardrop depending on the phone; only the middle 80% of the diameter is guaranteed to survive. Padding rewrites android-chrome-512x512.png alone — the 16/32/48, apple-touch and 192 icons keep the full-size mark — and it is the only thing that makes the manifest claim "purpose": "maskable".

In context

CSS approximations of platform chrome, not device screenshots — real rendering shifts with browser and OS version. Each icon below is the same bitmap you download, drawn at its true pixel size; transparency shows over white.

My Site — Home
Browser tab, light chrome — 16 px at 1×
My Site — Home
Browser tab, dark chrome — 32 px on a 2× screen
My Site — Homehttps://my-site.com/
Bookmark and history rows — the 16 px icon again
My Site
iOS home screen — 180 px, rounded tile
My Site
Android launcher — 192 px, circle mask

Paste into <head>

        
site.webmanifest

        

Nothing leaves your browser. Every size is drawn with the Canvas API, the .ico is packed and the download is zipped right here on your device. There are no uploads — you can disconnect from the internet and it still works.

What a modern favicon package actually needs

A favicon is no longer a single 16×16 file. Browsers draw a site's icon in a browser tab, on a bookmark bar, in history and reading lists; operating systems draw it on the taskbar, on desktop shortcuts and on phone home screens; each of those wants a different pixel size, and some want a specific file format. Rather than one image, the reliable approach today is a small package of a few files plus five or six lines of HTML — which is exactly what this tool builds from a single source image, letter or emoji.

The files this tool produces

FileSize(s)Used by
favicon.ico16, 32, 48The universal fallback: older browsers, crawlers, feed readers and Windows shortcuts request /favicon.ico even if you never link it
favicon-16x16.png16Standard browser tab
favicon-32x32.png32High-DPI tabs, taskbar, bookmark bar
favicon-48x48.png48Windows site tiles and desktop shortcuts
apple-touch-icon.png180iOS / iPadOS "Add to Home Screen"
android-chrome-192/512192, 512Android and installed PWAs, via the manifest. The 512 is the one the safe-zone padding rewrites, if you switch it on
site.webmanifestNames the app, points to the Android icons and carries theme_color. Gains "purpose":"maskable" on the 512 only when safe-zone padding is applied
icon.svgAnyText mode only. A real vector of your letter mark — same tile, corner radius and glyph as the PNGs — linked first in the snippet so modern browsers draw it at any resolution. Not produced for uploads or emoji (see Honest limits)
safari-pinned-tab.svgAnyText mode only, optional. The same letter as a flat black silhouette on transparent, which macOS Safari tints for a pinned tab. Legacy: Safari 12+ falls back to your normal favicon without it. Not produced for uploads or emoji

Platform-size matrix: which platform actually requests which size

It is easy to over-produce favicons because blog posts list a dozen "required" sizes. In reality each platform reads a specific, documented set, and several of those are only fetched in narrow situations. Here is what each surface genuinely uses — sourced from Apple's Human Interface guidance, the W3C Web App Manifest spec and the long-standing favicon.ico convention — with an honest needed-vs-optional call:

Platform / surfaceSize(s) it readsNeeded or optional
Desktop browser tab & bookmarks16, 32 PNG; favicon.ico (16/32/48)Needed. The root /favicon.ico is requested automatically by every browser, crawler and feed reader even if you never link it
Windows taskbar / desktop shortcut32, 48 (taken from the .ico)Automatic. Pulled from the same .ico — no extra tag or file
iOS / iPadOS "Add to Home Screen"180 (apple-touch-icon.png)Optional. Only used when a visitor saves the site to their home screen; supply it or iOS grabs a blurry screenshot
Android & Chrome PWA install192 (launcher), 512 (splash) via manifestNeeded for an installable PWA; present-but-unused for an ordinary site
Safari pinned tabMonochrome SVG (mask-icon), single colourOptional and legacy, Safari-only. Safari 12 and later fall back to your ordinary favicon without it. Emitted here as safari-pinned-tab.svg for a letter mark; uploads and emoji get none

Notice what is not here: there is no genuine 64, 96 or 128 "favicon requirement" — those numbers circulate but no shipping platform requests them by default. The honest minimum for a normal marketing site is the .ico plus the 16/32 PNGs; add the 180 apple-touch if home-screen saves matter, and the 192/512 manifest pair only if you are shipping an installable PWA.

The Safari pinned-tab mask-icon: still real, no longer required

This is the one favicon file whose status genuinely changed, so it is worth stating what is true rather than repeating a 2015 blog post. Apple's spec for it is still published — Creating Pinned Tab Icons, in the Apple Developer Documentation Archive, last revised 12 December 2016 — and it asks for exactly two things: the tag <link rel="mask-icon" href="…svg" color="…">, and an SVG that is a single layer of 100% black vectors on a transparent background. Safari discards the black and repaints the shape in your color. Three facts round that out:

  • It stopped being mandatory in Safari 12 (2018). Before that, a pinned tab with no mask-icon showed the site's initial letter on a grey tile; since then Safari falls back to your ordinary favicon. Shipping the file buys you control of the tinted silhouette, nothing more — so treat it as polish, never as a missing requirement.
  • It never became a standard. WebKit's engine-side icon enum recognises only the plain favicon and the two Apple touch-icon relations; mask-icon is handled by Safari the application, and MDN's rel reference does not list it among either the standard or the non-standard values it documents. Nothing else on the web reads it.
  • Big sites have quietly split on it. Checked while writing this: apple.com's own <head> carries no mask-icon; github.com's still does, pointing at a black Octocat. And realfavicongenerator.net, which popularised the file, has stopped generating it — its FAQ now answers "why is it gone?" with the argument that the icon was for the MacBook Touch Bar, which Apple discontinued in 2021.

That last argument is only half the story — the Touch Bar was a second consumer of the same file, but macOS Safari still pins tabs — which is why this tool emits it anyway, for Text mode, and frames it as optional. What you get is your letter as black on transparent in the same viewBox="0 0 100 100" as icon.svg, plus the <link rel="mask-icon"> line in the snippet with your background colour as the tint. The coloured tile is deliberately not included: a rounded square flattened to one colour is a featureless blob in a tab, and the letter is the part that carries the mark. If your pinned-tab icon should be a shape rather than a letter, hand-author the silhouette — that is still the only way to get it right.

ICO vs PNG vs SVG — which format, and why keep the .ico

ICO is a container: a tiny directory that can hold several bitmaps, so favicon.ico here packs the 16, 32 and 48 pixel images into one file and the browser or OS picks the closest match for where it draws — no scaling, no blur. Its value today is compatibility: many crawlers, feed readers and older browsers still fetch /favicon.ico from the site root by default, and it is the one file that answers that request. PNG favicons are what modern browsers actually prefer for tabs — you link the 16 and 32 pixel versions explicitly and they render crisply with an alpha channel. SVG is the newest option: a single vector file that scales to any resolution and can even flip colours in dark mode with a media query, but Safari's support is partial, so an SVG is best linked alongside the raster set rather than replacing it. Keeping all three covers every browser without betting on any one of them — which is why, in Text mode, this tool emits icon.svg as well and puts it first in the snippet: browsers take the first icon link they understand, so an SVG-capable one uses the vector and everything else falls through to the PNGs and the .ico.

The apple-touch icon and the web manifest

Apple's home-screen icon ignores your <link rel="icon"> tags and instead looks for apple-touch-icon. The current recommended size is 180×180, and unlike a favicon it should be opaque — iOS puts it on a rounded tile and a transparent background can render as black, which is why this tool fills the background for that size. Android and installable web apps (PWAs) take a different route again: they read a site.webmanifest that names the app and lists icons, conventionally 192×192 for the home screen and 512×512 for the splash screen. The manifest generated here wires both, and its theme_color follows the background colour you chose. One thing worth knowing about that colour: a manifest only reaches the browser once someone installs your site as an app, so on an ordinary visit it does nothing. The tag that actually tints Chrome's address bar and the Android status bar is <meta name="theme-color"> in the <head>, which is why the generated snippet now carries it, filled from the same value the manifest gets so the two can never disagree. Safari on iOS reads it too, for the notch area of a saved home-screen app.

How the download bundle is built without any library

Staying genuinely zero-upload rules out pulling a zip library from a CDN, so the "Download all" here writes the ZIP itself: a minimal STORE-method archive (no deflate) with a CRC-32 computed in JavaScript per file. The files are stored uncompressed on purpose — PNG and ICO are already compressed, so deflate would add code and CPU for almost no size saving. Prefer to grab one file? Every icon, the manifest and the ICO also have their own button, so you never need the zip at all.

Worked example: one logo taken to a full favicon pack

Take a real case: a 512×512 PNG of a bold single-letter mark on a transparent background — the kind of simple logo that survives being shrunk. Switch to Upload image, drop it in, leave a little padding, and pick a brand background colour. The preview shows 16, 32, 48 and 180 pixels at once so you can catch problems before you ship. Here is every file the pack ends up with and the reason each one earns its place:

  1. favicon.ico packing 16 + 32 + 48. Multi-resolution on purpose: the OS or browser picks the nearest bitmap for where it draws, so the tab stays crisp and the Windows taskbar isn't a blurry upscale of a single size. One file also answers the automatic /favicon.ico request that never goes away.
  2. 16 and 32 PNG links. Modern browsers prefer PNG for the tab and keep a clean alpha edge; you link them explicitly so a high-DPI tab gets the sharp 32 rather than an upscaled 16.
  3. A 180×180 apple-touch icon, opaque. iOS ignores your <link rel="icon"> tags and looks for apple-touch-icon; 180 is the current iPhone home-screen size and iOS downscales it for smaller devices. It must be opaque, because iOS composites a transparent icon onto black — so here the background is filled for that size even if the tab icons stay transparent.
  4. 192 and 512 for Android via the manifest. 192 is the launcher/home-screen size and 512 feeds the splash screen; the site.webmanifest names the app and points at both, with theme_color following your chosen background.
  5. The maskable 512 decision. A fully robust pack marks the 512 with "purpose":"maskable" and keeps the mark inside the central 80% safe zone, so Android can crop it to a circle or squircle without clipping the logo. This is now measured rather than left to you. The Android maskable safe zone panel renders your icon at 512, treats every pixel that differs from the background tile as mark, and reports the furthest one as a percentage of the safe radius — 100% means exactly on the circle. Three measured cases from this page, so you can see it is not a rubber stamp: the default single letter A on a rounded tile reaches 84% and passes untouched; type a second character and the glyph hits the 84%-of-side width cap, which throws its corners out to 114% with 682 pixels outside the circle; and a plain square image uploaded at the default 8% padding lands at 148% with 53,112 pixels outside, because a square's diagonal always escapes the circle inscribed around it. Switch the padding on and the mark is scaled to fit — to 87% of its size in the two-letter case, 67% for the square image — the 512 is re-measured, and only then does the manifest gain the flag. Two honest limits: a mark drawn in (or very near) your background colour is invisible to the scan, and the padding is a centred shrink — it will not reposition an off-centre logo.
  6. The SVG decision. The ideal pack links an .svg favicon first, for infinite sharpness and the option of dark-mode switching. Where that vector comes from depends on your source. A text mark is vector data by definition, so this tool writes icon.svg itself — the same tile, corner radius and glyph as the PNGs, about 360 bytes — and puts its <link> at the top of the snippet. An uploaded vector is passed through: the .svg you drop in is sanitised and becomes icon.svg unchanged in geometry, and every PNG beside it is rasterised from those outlines at its own size. An uploaded raster — which is what this walkthrough uses — cannot produce one: a 512×512 PNG is pixels, and wrapping it in an <svg> would be a fake vector, so that pack ends up raster-only and you should keep your own .svg as the primary <link> with the .ico from here as the fallback beneath it. A text mark also gets safari-pinned-tab.svg — the same letter as a flat black silhouette, about 300 bytes — for macOS Safari's pinned tabs; no upload of either kind gets that file.

Click Download all, unzip into your site root so the files sit beside your home page, and paste the generated snippet into your <head>. Because every path is root-absolute (/favicon.ico, /favicon-32x32.png…), the same block works on every page.

Uploading an .svg: what gets stripped, and what gets drawn

Design handoffs ship vectors, so an .svg is usually the first thing anyone drops into a favicon tool. Here it is treated as a vector all the way through rather than being flattened on arrival. Two things happen to it, in this order.

1. It is sanitised, and the sanitiser will refuse

SVG is XML, and XML can carry things that are not drawing. Before anything is rendered, the file is scanned in your browser and these are removed: <script> elements together with their contents, every on* event-handler attribute (onload, onclick and the rest), <foreignObject> subtrees — which embed arbitrary HTML inside the artwork — javascript: URLs including entity-obfuscated spellings like java&#115;cript:, and every href, xlink:href, src, CSS url() or @import that does not resolve inside the file itself. Only a plain #fragment survives, so your gradients, filters and <use> references keep working while a remote stylesheet, web font or tracking pixel does not.

Being straight about why this matters: an SVG loaded into an <img> element — which is the only way this page ever renders one — runs in what the HTML spec calls secure static mode, where script never executes and external resources are never fetched. So none of those payloads could have run here in any browser. The strip earns its place further down the line: the sanitised text is also the icon.svg written into your pack and served from your own origin, where it may be opened directly, inlined into a template, or passed through a build step — and in those places script and remote references are very much live. Treat it as defence in depth, not as the only thing standing between you and code execution.

The scanner is deliberately strict, and where it cannot parse a file with confidence it refuses instead of half-cleaning it: unquoted attribute values, unbalanced tags, a custom <!ENTITY> declaration or an inline DTD all produce a plain-English refusal beside the drop zone and nothing is drawn. A "best effort" clean is exactly how sanitisers get bypassed, so no is the correct answer. Ordinary exports from Figma, Illustrator, Inkscape and Sketch are well-formed XML and go through untouched.

2. Every size is rasterised from the vector, separately

The usual shortcut is to draw an SVG into one large canvas and then shrink that bitmap down to 16 pixels. That gives you a blurry 16 — you are downscaling a raster, not drawing the shape. Here the sanitised markup is handed to the browser once per output size with the pixel dimensions already set, so 16, 32, 48, 180, 192 and 512 are six independent renders from the same outlines. A hairline that would smear into grey mush at 16 in a downscale gets a full-strength edge instead. The geometry is untouched between renders — only the raster target changes — and the padding slider and shape mask still apply exactly as they do to a raster upload.

One honest caveat: live <text> in your vector rasterises with a font this machine actually has. If the SVG names "Gilroy Bold" and this computer does not have it, the browser substitutes something else and the PNGs freeze that substitute — the same trap as the emoji case above, one step earlier. When the file contains <text> you get a warning saying so under the drop zone. The fix is in your editor, not here: convert text to paths (Illustrator's Create Outlines, Inkscape's Path → Object to Path, Figma's Flatten) and re-export. Then the shape cannot shift no matter where it is rendered.

The file never leaves the device at any point in this: it is read with FileReader, sanitised as a string, and rendered through a blob: URL in the same tab. There is no upload step to opt out of.

Dark-adaptive icon.svg: what the checkbox actually writes

The SVG is the only member of the pack whose appearance can change with the operating system theme, because CSS inside an SVG is live. Tick Dark-adaptive icon.svg beside the downloads and the emitted file gains exactly one element, injected straight after the root <svg> tag. Nothing else in the file is touched — no path, no attribute, no reordering. For the default letter mark (indigo tile, white glyph) the block is:

<style>@media (prefers-color-scheme: dark){
  [fill="#5b6cff"]{fill:#5160e5!important}
  [fill="#ffffff"]{fill:#000000!important}
}</style>

The rule, in one line of arithmetic

Every colour the file states — as a fill, stroke or stop-color attribute, or in an inline style — is pushed through one function of its WCAG relative luminance Y:

Y′ = 0.0525 / (Y + 0.05) − 0.05

0.0525 is 1.05 × 0.05, and it is the constant that makes white (Y = 1) map to black and black back to white. The point of that particular shape is contrast: WCAG contrast between two colours is (Ya + 0.05) / (Yb + 0.05), so pushing both of them through this function flips which one is lighter and leaves the ratio itself alone. The default pair contrasts 4.17:1 today and 4.15:1 after the map — the 0.02 is 8-bit rounding, nothing else. A dark navy #0f172a on white goes to #ececed on black: 17.85:1 becomes 17.79:1. Hue survives when a colour darkens (its linear-light channels are scaled by one factor); a colour that has to lighten is blended toward white in linear light, which is the only way to raise luminance without clipping a channel, so it also desaturates a little.

Where it will disappoint you, stated up front

  • SVG only, and a raster upload cannot have one. Upload a PNG or JPG and the option is disabled with the reason shown: your file is rasterised onto the canvas, so the pack has no vector member, and .ico and PNG are fixed pixels that no media query can reach. That limit has not moved.
  • Chrome and Firefox honour it in a favicon; Safari's handling differs. Treat the dark variant as an enhancement for the browsers that switch, and keep the .ico and PNGs linked underneath — which the generated snippet already does. The same file inside an ordinary <img> may be pinned to the light branch; this is a favicon technique, not a general image one.
  • It is a mechanical mapping, not a redesign. Nothing here knows what your artwork depicts. A mid-luminance colour barely moves, because the map has a fixed point around #767676 (Y ≈ 0.179): a mid-tone brand red like #e11d48 becomes #e12d4f, essentially itself, while the white beside it becomes black. That is correct for a contrast-preserving map and it is also the reason to look at the output before shipping it — if your mark is a mid-tone shape on a mid-tone tile, the dark block will change almost nothing.
  • Only colours the file states are mapped. The block targets them with attribute selectors and never rewrites your artwork, so colours declared inside your own <style> block, shapes relying on the default black fill, and gradients reached through url(#id) are left alone. The status line counts the first case for you. Recognised literals are hex (#abc, #aabbcc) plus the keywords black and white; anything else is left exactly as written rather than guessed at.
  • Off means off. With the checkbox clear, icon.svg is byte-for-byte the file this tool has always emitted — the dark path does not run at all. safari-pinned-tab.svg is never touched either: it is a single-colour silhouette that Safari tints itself.

How this compares to realfavicongenerator.net

The best-known tool in this space is realfavicongenerator.net, and it is genuinely excellent — worth naming plainly what it does that this tool does not:

  • A draggable maskable editor, and a macOS Safari pinned-tab preview. This is the real remaining gap and it is worth being precise about it. Its maskable editor lets you drag and scale the artwork inside the safe zone until the crop looks right — position it off-centre, size it by eye. The safe-zone check here is not that: it measures the 512 render, tells you in words whether any pixel of your mark falls outside the 80% circle, and offers one button that scales the mark down until it fits, centred. That covers the common case (a mark that is simply too big) and not the uncommon one (a mark you want deliberately off-centre inside the crop). Their pinned-tab mockup also stays theirs — though the file it previews is no longer missing here: for a letter mark this tool writes safari-pinned-tab.svg and adds the mask-icon line to the snippet. The rest of this page's in-context strip — browser tab in light and dark chrome, a bookmark row, the iOS tile, the Android launcher circle — is CSS approximations of platform chrome, not device-accurate screenshots.
  • Broader platform coverage — narrower than it used to be. Its FAQ now carries a "why is it gone?" entry for two of the outputs it was famous for. On the mask-icon: "The mask icon is an icon defined by Apple, to be displayed in the MacBook Touch Bar. However, Apple discontinued the Touch Bar in 2021 … There is no use supporting the Touch Bar anymore." On the Microsoft tiles: Windows 8 left support on 10 January 2023, so browserconfig.xml went with it. The snippet gap that used to sit here has closed: this tool's block now carries a <link> for every file it writes plus the <meta name="theme-color"> tag, each with a one-line comment naming what asks for it, and it still declines to emit the two retired tags above.
  • A site auditor. It can scan an existing site and report what its favicon setup is missing — a checker this tool has no equivalent for.

Where this tool wins is privacy and simplicity: it is fully client-side — your source image is decoded, drawn, packed and zipped entirely in your browser and never uploaded, whereas realfavicongenerator processes your uploaded image on its servers. That makes this the safer choice for unreleased logos and confidential brand art, it needs no sign-up, and it keeps working with the network off. On the SVG question the gap has closed: upload an .svg here and it is sanitised, kept as vector, rasterised separately at each output size, and shipped back as icon.svg linked first in the snippet — the same thing realfavicongenerator does, except the file never leaves your tab. Dark-adaptive SVG favicons are offered by both tools now, and the difference is worth naming rather than glossing: the dark palette here is derived from the light one by the contrast-preserving luminance flip described above, not designed — a weaker promise, honestly labelled, and the block it writes is a handful of CSS lines you can edit. For a typed letter mark this tool also writes the Safari mask-icon silhouette, which the incumbent has retired. And the maskable question is now answered rather than left to you: the safe-zone check measures your own mark against the 80% circle and only writes "purpose": "maskable" into the manifest once the 512 has actually been padded to satisfy the crop. What this tool still will not do is vectorise an uploaded raster, so a PNG or JPG logo gets the PNG/ICO pack and neither SVG, and an uploaded vector gets icon.svg but no pinned-tab silhouette (that file has to be one flat colour, and nothing here can decide which parts of your artwork become the shape). Two honest reasons to pick the incumbent survive: its draggable maskable editor, if you need to place a mark off-centre inside the crop rather than simply shrink it, and its site auditor that scans a live URL and reports what the favicon setup there is missing. Pick this one when you want the essential pack — safe-zone verdict included — instantly, without your art leaving the machine.

Honest limits

  • Small sizes are unforgiving. A detailed logo shrunk to 16×16 loses its detail no matter what tool renders it — that is physics, not a bug. Bold, simple marks or a single strong letter read best at tab size.
  • It rasterises through Canvas. Sizes are drawn with the browser's image scaler, which is good but not a hand-tuned icon pipeline; for pixel-perfect 16-pixel hinting a designer editing each size by hand will still do better.
  • A raster upload gets no SVG, and no upload gets a mask-icon. Upload a PNG or JPG and you get the raster package alone: your file is drawn onto the canvas with the background tile, shape mask and padding baked in, so there is no vector left to write out — and wrapping a base64 PNG inside an <svg> would be a fake vector, not a real one. Upload an .svg and the vector is kept: it is sanitised, re-rendered from the outlines at every output size, and returned as icon.svg. safari-pinned-tab.svg is still text-mode only, for both kinds of upload — a mask-icon has to be reduced to one flat colour, and no tool can decide which parts of a photo or a multi-colour logo become the silhouette without guessing.
  • An uploaded SVG is sanitised, and a sanitiser that is unsure says no. Anything with an unquoted attribute, unbalanced tags, a custom <!ENTITY> or an inline DTD is refused outright with the reason shown next to the drop zone, because a half-cleaned render is worse than a clear refusal. Well-formed exports from Figma, Illustrator, Inkscape and Sketch pass; hand-edited files that were relying on HTML's forgiving parser may not. Re-export from your editor and it will go through.
  • Emoji look native, and get neither SVG. A rendered emoji uses your device's emoji font, so the exact glyph style can differ slightly between the machine that generates it and the visitor's browser — the downloaded PNG at least freezes it. A vector <text> emoji would not: it re-renders with each visitor's own emoji font, which can look plainly different from the PNGs beside it, so emoji marks are deliberately refused for icon.svg. They are refused for safari-pinned-tab.svg for an additional reason: a mask-icon is painted in a single colour, and an emoji stripped of its colours is usually unrecognisable. The font effect is milder but real for letters — both SVGs name a system sans-serif stack rather than embedding outlines, so the letterform can differ by a hair across platforms while the PNGs stay fixed.
  • The mask-icon is a letter, not your tile. The silhouette is the glyph alone on transparent — the background colour, corner radius and circle/square choice are dropped, because flattened to one colour they would fill the whole tab with a solid block. If the shape itself is your logo, this file will not represent it, and hand-authoring the silhouette remains the only honest route.
  • The dark-adaptive SVG is optional, SVG-only and mechanical. It applies to icon.svg alone — a raster upload has no vector member, so the option is disabled and says why, and the .ico and PNGs beside it are fixed pixels that cannot adapt no matter what. Chrome and Firefox honour the media query in an SVG favicon; Safari's handling differs, so keep the raster fallbacks linked. And the second palette is computed, not designed: colours are flipped through a contrast-preserving luminance map, which leaves mid-tone colours almost where they were. Full detail, including the formula and what it will not touch, is in the section above.
  • ICO here is PNG-in-ICO. The bitmaps inside the .ico are stored as PNG, which every browser since IE11 reads; a handful of very old Windows programs expect the legacy BMP form and may not show it, though they will still fall back to the linked PNGs.

Frequently asked questions

Is my image uploaded anywhere?

No. Your image is decoded and every icon size is drawn locally with the browser's Canvas API, the .ico is packed byte-by-byte in JavaScript on your device, and the download bundle is zipped in the page itself. There is no server call and no upload — you can disconnect from the internet and it still works, which makes it safe for logos and brand art you would not want to send to a remote service.

Do I still need a .ico file, or is a PNG enough?

You still want one. Every modern browser reads PNG favicons, but a favicon.ico at the site root is the universal fallback that older browsers, feed readers, some crawlers and Windows shortcuts still request by default even when you never link it. It costs a couple of kilobytes, so the safe pattern is: ship favicon.ico for the long tail, link 16x16 and 32x32 PNGs for crisp modern rendering, add the apple-touch icon for iOS and the webmanifest for Android — which is exactly the set this tool produces.

What sizes does a favicon actually need?

16x16 is the classic browser-tab size and 32x32 is used on high-DPI tabs, the Windows taskbar and bookmark bars; 48x48 covers Windows site tiles and desktop shortcuts. Apple touch icons are 180x180 (the current iPhone home-screen size), and Android/PWA installs pull 192x192 and 512x512 from the web manifest. This tool emits all of those, plus a .ico that packs the 16, 32 and 48 pixel versions into one file.

Why does the .ico contain three sizes instead of one?

The ICO container is a small directory that can hold several images at once, and the operating system or browser picks the closest match for where it is drawing the icon — a tab, a taskbar, a large tile. Packing 16, 32 and 48 pixel bitmaps means the icon stays sharp whether it is shown tiny in a tab or larger on a desktop shortcut, instead of one size being scaled and going blurry. Each size is stored as its own PNG inside the ICO.

Should I use an SVG favicon instead?

Use it alongside the raster set, not instead of it. An SVG favicon scales to any resolution and can switch appearance in dark mode with a media query, but Safari's coverage is partial and crawlers still fetch /favicon.ico, so the SVG belongs first in the head with the .ico and PNGs beneath it. This tool now emits that file for you in Text mode: a letter or two on a coloured tile is genuinely vector data, so it writes icon.svg with the same tile, corner radius and glyph the PNGs use, and puts the <link rel="icon" type="image/svg+xml" href="/icon.svg"> line at the top of the generated snippet. Two honest limits: a RASTER upload (PNG, JPG, GIF, WebP) gets no SVG, because your file is rasterised onto the canvas with the tile, shape mask and padding baked in — an uploaded .svg does keep its vector and ships back as icon.svg — and emoji get no SVG either, because a vector <text> emoji is drawn with each visitor's own emoji font rather than the pixels baked here.

Why is there no single 'Download all' without a library?

There is one — the Download all (.zip) button. Rather than pull in a third-party zip library over a CDN (which would break the no-upload, no-external-code promise), this page writes the ZIP itself using a small STORE-method encoder with a hand-computed CRC-32. The files are stored uncompressed because PNGs are already compressed, so nothing is lost by skipping deflate, and the whole bundle is assembled in memory on your device.

Where do I put the files and the HTML snippet?

Unzip the package into the root of your website (the same folder as your home page), so the files answer at /favicon.ico, /favicon-32x32.png and so on. Then paste the generated <link> block into the <head> of every page, ideally in a shared template or layout. The paths in the snippet are root-absolute, so they work from any URL on the site without editing.

What is a maskable icon and what is the safe zone?

Android draws installed-app icons inside a shape it chooses — a circle on one phone, a rounded square (squircle) on another, a teardrop on a third — so it crops whatever you give it. Only a centred circle of 80% of the icon's diameter is guaranteed to survive every mask; that circle is the safe zone, and the outer 20% ring is background the system may trim. You opt in by adding "purpose":"maskable" to that icon's entry in the web manifest. This tool checks it for you: it renders your icon at 512, counts how many pixels of the mark (as opposed to the background tile) fall outside the circle, and says in plain words whether the mark fits or gets cropped. If it overflows, one button pads it — the mark is scaled down inside the safe circle on android-chrome-512x512.png only, so your 16, 32, 48, apple-touch and 192 icons keep the full-size mark — and the padded 512 is re-measured before the manifest is allowed to say "purpose":"maskable". Leave the button off and the manifest carries no purpose at all, exactly as before: the flag is never set on an icon that was not padded to satisfy the crop.

Can a favicon change in dark mode?

Only an SVG favicon can — and this tool now writes that block for you instead of telling you how to do it by hand. CSS inside an SVG is live, so a @media (prefers-color-scheme: dark) rule recolours the artwork in place: one file, your normal mark on light browser chrome, a remapped version at night. Tick 'Dark-adaptive icon.svg' beside the downloads and every fill, stroke and stop-color the file states is pushed through one formula on WCAG relative luminance — Y' = 0.0525 / (Y + 0.05) − 0.05 — the constant that sends white to black and black back to white, and that leaves the contrast ratio between any two mapped colours where it was. The default indigo tile with a white letter becomes #5160e5 with a black letter: 4.17:1 before, 4.15:1 after. Three honest limits, none of them small. It is SVG-only: .ico and PNG are fixed pixels, so a raster upload gets no dark variant at all and the option is disabled for one. Chrome and Firefox honour the query in an SVG favicon while Safari's handling of SVG favicons differs, so the .ico stays the fallback. And it is a mechanical colour mapping, not a redesign — nothing here knows what your artwork depicts, so look at the result before you ship it. With the option off, icon.svg is byte-for-byte the file this tool has always written.

Why do my 16x16 and 32x32 icons look blurry?

Two causes. First, detail loss: a logo with fine lines or small text simply has no room to survive at 16 pixels, so it reads as mush no matter which generator you use — the fix is a bolder, simpler mark or a single strong letter, not a different tool. Second, soft downscaling: browsers resize with a smooth (bilinear) scaler that can leave edges slightly fuzzy versus an icon hand-pixel-hinted for that exact size. Watch the live 16 and 32 previews here on the checkerboard while you adjust padding and shape — if the mark looks vague at 16, increase the padding a little or simplify it before you download.

What about the Safari pinned-tab icon?

Safari's pinned tabs use a monochrome SVG referenced with <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5b6cff">: Apple's spec asks for a single layer of 100% black vectors on a transparent background, and Safari tints that silhouette with the color you set. It is optional and legacy — since Safari 12 (2018) a pinned tab falls back to your ordinary favicon when no mask-icon is present, so it only buys you control of the tinted shape. In Text mode this tool now emits safari-pinned-tab.svg: your letter as a flat black silhouette on transparent, in the same 100x100 viewBox as icon.svg, with the mask-icon line added to the snippet carrying your background colour as the tint. The coloured tile is deliberately dropped, because flattened to one colour it would be a featureless black square. Uploads and emoji get no mask-icon at all: an uploaded .svg does come back as icon.svg, but the pinned-tab silhouette needs a single-colour reduction this tool will not guess at.

Can I upload an SVG, and what happens to it?

Yes. Drop an .svg into Upload image and it is treated as a vector all the way through. First it is sanitised in your browser: script elements together with their contents, every on* event-handler attribute, foreignObject subtrees, javascript: URLs and every href, xlink:href, src, CSS url() or @import that does not resolve inside the file are all removed, leaving internal #fragment references so gradients and use elements keep working. Where the file cannot be parsed with confidence — unquoted attributes, unbalanced tags, a custom ENTITY declaration — it is refused with a reason rather than half-cleaned. Then every output size is rasterised from the vector separately, so the 16-pixel tile is its own render of the outlines rather than a shrunken 512, and the sanitised file ships as icon.svg linked first in the snippet. Nothing is uploaded at any point.