Skip to content

PNG to ICO Converter (and ICO to PNG)

Convert PNG, JPG, SVG or WebP into a real multi-size .ico — 16, 32 and 48 px in one file, full alpha kept. Choose PNG or uncompressed BMP storage and see both sizes. Opens .ico files back up too.

No Tracking Runs in Browser Free
Conversion runs entirely in your browser. Your image is never uploaded.

Drop an image here or click to browse

PNG, JPG, SVG, WebP, GIF or BMP · up to 10 MB

Sizes to pack

16, 32 and 48 px is what the 1995 Microsoft icon guidance asked for and the combination that turns up most often in real favicons. 512 is not offered: the directory stores the side length in one byte, so it has no valid representation.

Both are legal inside a .ico. PNG has been read by Windows since Vista and by every current browser; uncompressed BMP is what 13 of the 14 genuine ICO files found across 20 sampled sites actually use, because ImageMagick converts to it by default.

What is inside a .ico file (16 + 32 + 48 px example)
Offset Bytes Field Value
0 2 idReserved 0
2 2 idType 1
4 2 idCount 3
6 1 bWidth[0] 16 → 16
7 1 bHeight[0] 16 → 16
8 1 bColorCount[0] 0
9 1 bReserved[0] 0
10 2 wPlanes[0] 1
12 2 wBitCount[0] 32
14 4 dwBytesInRes[0] 248
18 4 dwImageOffset[0] 54
22 1 bWidth[1] 32 → 32
23 1 bHeight[1] 32 → 32
24 1 bColorCount[1] 0
25 1 bReserved[1] 0
26 2 wPlanes[1] 1
28 2 wBitCount[1] 32
30 4 dwBytesInRes[1] 720
34 4 dwImageOffset[1] 302
38 1 bWidth[2] 48 → 48
39 1 bHeight[2] 48 → 48
40 1 bColorCount[2] 0
41 1 bReserved[2] 0
42 2 wPlanes[2] 1
44 2 wBitCount[2] 32
46 4 dwBytesInRes[2] 1464
50 4 dwImageOffset[2] 1022
The hex dump, the byte counts and the command output quoted on this page were captured from files this tool produced, and every claim about how decoders behave was cross-checked against three independent implementations: a from-scratch encoder, Pillow 12.3.0 and Chromium's own ICO decoder. The observation that most shipped favicons use uncompressed bitmaps comes from fetching and parsing twenty well-known sites' icon files in September 2026. — Go Tools Engineering · Sep 22, 2026

Written and reviewed by the developers who build the Go Tools conversion utilities. The container layout, the byte counts and the failure modes described here come from a written domain review rather than from other people's summaries of the format.

PNG to ICO quick answers

What sizes should a favicon.ico contain?

16, 32 and 48 px Those three cover the browser tab, the Alt-Tab switcher and the desktop, and have been the recommended set since 1995. Add 256 only if the icon also has to hold up in a large-icon view.

Can one .ico file hold several sizes?

Yes — that is what it is for The format is a container: a six-byte header, one sixteen-byte directory entry per image, then the images. Each one is a separate drawing, which is why a good icon stays crisp at 16 px.

Does converting PNG to ICO lose transparency?

No, not if it is done properly Both ways of storing an image inside a .ico carry a full eight-bit alpha channel. Transparency is lost only when a tool leaves the alpha bytes blank or drops the one-bit mask that older software reads instead.

How big is a 256 px layer inside an .ico?

264 KB uncompressed, or a few KB as PNG An uncompressed 256 px layer is exactly 270,376 bytes — 40 bytes of header, 262,144 of pixels and 8,192 of mask — whatever the picture is. Stored as PNG the same layer usually costs a couple of kilobytes.

What is an ICO file?

An .ico file is not an image format so much as a small archive of images. It starts with a six-byte header saying how many pictures are inside, followed by one sixteen-byte directory entry per picture giving its width, height, byte count and position in the file, and then the picture data itself. Each picture can be stored in either of two ways: as a complete PNG file embedded whole, or as an uncompressed Windows bitmap with a one-bit transparency mask bolted underneath it.

That design is why a favicon can look sharp at 16 px in a browser tab and at 48 px in a file manager — they are different drawings, hand-tuned at each size, not one image being resized. It is also why the format has a few surprises. The side length is stored in a single byte, so 256 is written as zero and 512 cannot be written at all. And the directory records a size for each entry that the image data itself also records, which means the two can disagree — and different software believes different ones.

$ file favicon.ico
favicon.ico: MS Windows icon resource - 3 icons, 16x16, 32 bits/pixel, 32x32, 32 bits/pixel

$ python3 -c "from PIL import Image; print(sorted(Image.open('favicon.ico').ico.sizes()))"
[(16, 16), (32, 32), (48, 48)]

What this ICO converter does

One file, every size you tick

16, 32 and 48 px by default, up to 256. Each size is drawn separately from the original at full quality rather than being scaled from the layer above it, so small sizes do not inherit a bigger size's blur.

PNG or uncompressed BMP, with both sizes shown

The two legal payload formats have very different trade-offs and most converters never mention which one they write. Here it is a switch, and the resulting file size for each is displayed so the decision is made on a number rather than a guess.

Transparency that survives either route

The alpha channel is written in full, and the one-bit mask that older software reads instead is derived from it rather than left blank. Leaving that mask blank is what turns a transparent icon into a black square in the places that only read the mask.

An ICO viewer, not just a downloader

The reverse tab lists every image inside a .ico with its real size, storage format, bit depth and where its transparency comes from — including palette-based bitmaps that several well-known favicons still use. A browser will only ever show you one of them.

It tells you when a file is inconsistent

If the directory claims a size the image data does not match, that is flagged. So is an embedded PNG that Firefox will throw away — its ICO decoder only takes 8-bit RGB or RGBA, so a palette or greyscale layer simply vanishes there while every other browser shows it. Both are common reasons an icon works in one program and is blank in another, and no other converter reports either.

Nothing is uploaded

Reading, resizing and packing all happen on this page. The file never reaches a server, so there is nothing to delete afterwards and no queue to wait in.

Converting PNG to ICO in code

ImageMagick

magick in.png -define icon:auto-resize=48,32,16 favicon.ico

The usual answer, and the reason so many favicons are uncompressed. Every layer except 256 px is converted to a bitmap before packing, so three sizes come out around 15 KB instead of a few hundred bytes. The sizes are written largest-first.

Python + Pillow

img.save('favicon.ico', sizes=[(16,16),(32,32),(48,48)])

Embeds PNG, so the same three sizes land in roughly a tenth of the space. Pillow also reads ICO well: Image.open(f).ico.sizes() lists what is inside, which is handy for checking someone else's file.

png-to-ico (npm)

npx png-to-ico icon.png > favicon.ico

A single-purpose CLI that takes one or more PNGs and packs them as PNG payloads. Convenient in a build script; it will not resize for you, so you supply each size as its own file.

sharp

sharp(input).resize(32).png()

Excellent for producing the individual PNGs but it does not write ICO containers, so it is normally paired with one of the packers above. A common source of confusion when a build pipeline is already standardised on sharp.

Go

github.com/Kodeworks/golang-image-ico

Writes a single-image ICO from an image.Image. Enough for a one-size favicon; packing several sizes into one container means writing the directory yourself, which is about thirty lines.

Windows icon compilers

.rc resource script, rc.exe

How application icons are normally produced. The compiler embeds the .ico into the executable's resource section; the container inside is exactly the same format as a web favicon.

GIMP

File → Export As → .ico

Exports each layer of the image as one icon size and lets you choose the bit depth per layer, including compressed PNG. One of the few graphical tools that exposes the choice rather than deciding silently.

macOS sips

sips -s format ico in.png --out favicon.ico

macOS does have an ICO writer after all: sips --formats lists com.microsoft.ico as writable, and the command above produced a valid file here. What it will not do is pack several sizes — the output was a single 48×48 layer. iconutil, which search results usually suggest instead, makes .icns, Apple's own container, which Windows and browsers do not read.

PNG to ICO examples, byte by byte

The first 38 bytes of a three-size .ico

$ xxd -l 38 favicon.ico
00000000: 0000 0100 0300 1010 0000 0100 2000 e903  ............ ...
00000010: 0000 3600 0000 2020 0000 0100 2000 6c05  ..6...  .... .l.
00000020: 0000 1f04 0000                           ......

0000 is the reserved field, 0100 is type 1 (icon, not cursor), 0300 says three images. Then the first 16-byte directory entry: 10 10 is 16×16, 00 colour count, 00 reserved, 0100 one plane, 2000 32 bits per pixel, e903 0000 is 1,001 bytes of payload at offset 3600 0000 = 54 — which is exactly 6 + 3 × 16, the end of the directory. Every number is little-endian except the sizes, which are single bytes.

A 256 px entry stores zero, not 256

bWidth = 0x00    bHeight = 0x00
256 × 256

The directory has one byte for each side, so 255 is the largest number it can hold and 0 is defined to mean 256. This is also why 512 px is not offered anywhere on this page: there is no byte that means 512. Several online converters offer it anyway and write a 512 px image behind a directory entry that cannot describe it.

Same three sizes, two ways of storing them

16 + 32 + 48 px, PNG payloads
16 + 32 + 48 px, uncompressed BMP payloads
389 bytes
15,086 bytes

An uncompressed payload costs 40 + width × height × 4 bytes plus a 1-bit mask, so its size depends only on the dimensions and not at all on the picture. That is why three different sites can ship three completely different icons in files of identical length.

Building the same file from the command line

$ magick logo.png -define icon:auto-resize=48,32,16 favicon.ico
$ file favicon.ico
favicon.ico: MS Windows icon resource - 3 icons, 48x48, 32 bits/pixel, 32x32, 32 bits/pixel

ImageMagick converts every layer except 256 px to an uncompressed bitmap before packing it, which is why its output is around 15 KB rather than a few hundred bytes. Pillow does the opposite and embeds PNG: Image.open('logo.png').save('favicon.ico', sizes=[(16,16),(32,32),(48,48)]).

Unpacking an .ico again

$ magick favicon.ico favicon-%d.png
favicon-0.png   48×48
favicon-1.png   32×32
favicon-2.png   16×16

A browser cannot do this for you. Give a multi-size .ico to an <img> tag and you get exactly one image — the largest one — no matter what order the sizes are in. Listing what is actually inside a file means parsing the container by hand, which is what the ICO → PNG tab does.

How to convert PNG to ICO

  1. 1

    Drop your image

    PNG, JPG, SVG, WebP, GIF and BMP are all accepted, up to 10 MB. Nothing leaves the browser: the file is read with the File API and every pixel is drawn on a local canvas.

  2. 2

    Pick the sizes

    16, 32 and 48 px are ticked to start with. Add 64, 128 or 256 if the icon needs to survive a large-icon view or a high-DPI desktop. If your source is smaller than the largest size you ticked, the page says so rather than quietly enlarging it.

  3. 3

    Choose the storage format

    PNG is the default because it is an order of magnitude smaller and every current browser and every Windows since Vista reads it. Switch to uncompressed BMP if you want the form that most shipped favicons are actually in. The two file sizes are displayed side by side.

  4. 4

    Download and wire it up

    Save the .ico, and use the Copy link tags button for the markup. The root /favicon.ico path still works as a fallback, but an explicit link element is the path browsers are told to try first.

Why ICO files go wrong

A 256 px layer written as 255

The directory byte for a 256 px image must be 0. Writing 255 looks like a harmless off-by-one and produces a file that some browsers silently refuse to draw.

✗ Wrong
bWidth = 0xFF   bHeight = 0xFF   ; "255", meant as 256
✓ Correct
bWidth = 0x00   bHeight = 0x00   ; 0 is defined to mean 256

The directory and the image disagree about the size

When a directory entry says 16×16 over a payload that is really 32×32, decoders split: some trust the directory and draw nothing at all, others trust the payload and render it fine. The file then works on one machine and is invisible on another.

✗ Wrong
entry: 16×16     payload IHDR: 32×32
✓ Correct
entry: 32×32     payload IHDR: 32×32

The bitmap height field is not doubled

Inside an uncompressed layer the height covers the colour data and the mask together. Writing the plain height produces a file that shows as blank in some decoders and as the bottom half of the image in others, with no error either way.

✗ Wrong
biHeight = 32        ; for a 32 px image
✓ Correct
biHeight = 64        ; 2 × 32, colour data plus mask

An uncompressed layer with a blank alpha channel

Some tools fill the mask and leave every alpha byte at zero. One decoder reads that as a fully transparent image and the icon vanishes; another falls back to the mask and shows it correctly. Writing both, consistently, avoids the whole argument.

✗ Wrong
alpha bytes: all 0x00   mask: all 0x00
✓ Correct
alpha bytes: real values   mask: set where alpha < 128

An SVG that pulls in a file from the internet

External references inside an SVG are blocked when it is rasterised, and nothing reports it — no error fires and the canvas stays readable. The broken-image placeholder simply gets baked into the icon. Inline the artwork before converting.

✗ Wrong
<image href="https://cdn.example.com/logo.png"/>
✓ Correct
<image href="data:image/png;base64,iVBORw0KGgo…"/>

When you need a PNG to ICO converter

Shipping a favicon for a new site
Drop the logo, keep the default three sizes, download favicon.ico and drop it in the web root. The copied link tags give you the modern markup for the same icon alongside an SVG and an Apple touch icon.
Fixing an icon that looks fine large and muddy small
Usually the file has only one big layer and everything else is the browser shrinking it. Packing a real 16 px layer, drawn from the source rather than from the 256 px version, is what fixes it.
Giving a desktop application its icon
Windows executables, installers and shortcuts take .ico, and different parts of the shell reach for different sizes out of the same file. Packing 16, 32, 48 and 256 covers the small icons in lists, the Alt-Tab switcher and the large-icon views.
Working out why an icon renders in one place and not another
Open the file on the ICO → PNG tab. A size the directory describes wrongly, a layer with no alpha at all, or a truncated entry all show up in the listing, and each good layer still exports even when a neighbouring one is broken.
Getting PNGs back out of an old .ico
Icons inherited from an old project are often the only surviving copy of a logo. The reverse tab exports each layer as its own PNG, including layers stored as palette bitmaps that most converters refuse.

What is actually inside a .ico file

Six bytes, then sixteen per image
The header is 00 00 reserved, 01 00 for an icon (02 00 marks a cursor file), then a two-byte count. Each directory entry is width, height, palette size and a reserved byte — one byte each — followed by two-byte plane and bit-depth fields and two four-byte fields giving the payload's length and offset. Everything multi-byte is little-endian.
Zero means 256, and 512 is not expressible
Because width and height are single bytes, 256 has to be encoded as 0 and anything larger has no encoding at all. Writing 255 instead of 0 for a 256 px layer is not a close approximation — it produces a file that browsers refuse to draw. Converters that offer a 512 px option are writing entries that cannot describe their own contents.
An uncompressed layer costs exactly 40 + w × h × 4 bytes, plus a mask
The mask adds ceil(width ÷ 32) × 4 bytes per row. A 16 px layer is therefore 1,128 bytes, 48 px is 9,640, and 256 px is 270,376 — regardless of what the picture shows. That fixed cost is why three unrelated sites can ship favicons of byte-identical length, and why a 256 px layer is only offered here when the payload is PNG.
The bitmap header stores double the height
Inside an uncompressed layer, the height field describes the colour bitmap and the transparency mask stacked together, so it is written as twice the real height even when the mask carries no information. Getting this wrong is one of the quietest failures in the format: some decoders produce a blank image, others produce the bottom half of the picture, and neither reports an error.
The plane, bit-depth and colour-count fields are advisory at best
The specification is precise about them and real files ignore it. Microsoft's own documentation site serves a favicon whose directory claims zero planes and zero bits per pixel over a four-bit-per-pixel payload, and it displays everywhere. Decoders work out the real format from the payload — a PNG signature, or the bitmap header — rather than trusting the directory.
ICO has never had an RFC
The media type image/vnd.microsoft.icon was registered with IANA in September 2003, and the reference it cites is a 1995 Microsoft article called "Icons in Win32". RFC 2361, which is widely quoted as the ICO specification, is in fact titled "WAVE and AVI Codec Registries" and says nothing about images at all.

Getting a favicon.ico right

Pack 16, 32 and 48 and stop there for the web
That trio has been the recommended set since 1995 and is still the combination that turns up most often in real favicons. Extra sizes are not free — every one of them is another layer a browser may download before it knows which one it wants.
Draw the 16 px layer, don't just shrink the big one
A logo that works at 256 px usually loses its thin strokes by the time it reaches 16. If the small size matters, simplify the artwork for it — fewer shapes, heavier lines — and pack that simplified version as its own layer.
Use a link element and keep /favicon.ico as the fallback
The HTML specification only tells browsers they may fetch /favicon.ico, and only when no icon link is present. An explicit link element is the reliable path; the root file still earns its keep for feed readers, crawlers and anything else that does not parse your markup.
Add a size above 48 px if search results matter
Google's favicon guidance asks for a square image of at least 8 px and recommends going larger than 48 px so it holds up across surfaces. It accepts PNG as readily as ICO, so the large size does not have to live in the .ico at all.
Check the file, don't just look at it
An icon that renders in your browser can still be wrong: a mismatched directory entry, a missing alpha channel or an unreadable layer will not stop the one image your browser picked from displaying. Opening the file on the reverse tab shows all of them.

PNG to ICO FAQ

How do I convert a PNG to an ICO file?
Drop the PNG on this page, leave 16, 32 and 48 px ticked and download the result. Everything runs in the browser, so the image is never uploaded. On the command line the usual equivalent is magick logo.png -define icon:auto-resize=48,32,16 favicon.ico.
Why does my icon look blurry at small sizes?
Almost always because the file contains one large image and everything small is a browser shrinking it on the fly. No conversion is lossless once the pixel grid shrinks — thin strokes and fine detail disappear below about 24 px no matter how good the resampling is, so quality is decided by which sizes are packed, not by the converter. Pack a real 16 px layer, and if the logo is detailed, simplify the artwork for that layer rather than scaling it.
Should the images inside be PNG or uncompressed BMP?
PNG unless you have a reason not to: it is an order of magnitude smaller and every current browser and every Windows release since Vista reads it. Uncompressed bitmaps remain the more common choice in the wild, mostly because ImageMagick converts to them by default, and they are the safer bet for very old software. The page shows both file sizes so you can decide on the number.
Why is there no 512 px option?
The directory stores each side length in a single byte, so the largest value it can express is 255 and 0 is reserved to mean 256. There is no way to write 512. Converters that offer it produce a directory entry that does not describe the image behind it, which is a good way to get an icon that some software refuses to display.
Does a PNG with a transparent background stay transparent as an ICO?
Yes. The alpha channel is written in full, and the one-bit mask that older software reads instead is derived from it rather than left blank — that mask is what turns a transparent background into a black square in tools that leave it empty. A partly transparent pixel counts as transparent in the mask when its alpha falls below half, which is the only choice available since the mask is one bit per pixel.
Can I convert an SVG to ICO?
Yes, and a vector source is the best possible input because each size is drawn from the geometry rather than resampled from a bitmap. One caveat: anything the SVG pulls in over the network — a linked image, a remote font, an imported stylesheet — is blocked during conversion without raising an error. The page checks for those references and warns you.
Do I still need a favicon.ico in the site root?
It is worth having, but it is no longer the main path. The HTML specification says browsers may request /favicon.ico, and only when the page has no icon link element. A link element is what browsers are told to use first; the root file covers feed readers, crawlers and anything else that never parses your HTML.
Does Google need an ICO file for search results?
No. Google's favicon documentation accepts BMP, GIF, ICO, PNG, JPEG, PPM and TIFF, requires a square image of at least 8 px and recommends going larger than 48 px so it looks right across different surfaces. A single large PNG satisfies it; the .ico is for everything else.
Why does my browser only show one size when I open an .ico?
Because that is all an image element can give you. Hand a multi-size .ico to a browser and it picks one image — in practice the largest — and the rest are unreachable. Listing every layer means parsing the container directly, which is what the ICO → PNG tab on this page does.
What does it mean when the directory and the image disagree about the size?
It means the file is internally inconsistent, and decoders handle it in opposite ways: some trust the directory and end up drawing nothing, others trust the image data and render it correctly. That is a classic cause of an icon that works on one machine and is invisible on another, so this page flags it when you open a file.
Can this tool open ICO files that other converters reject?
Often, yes. Layers stored as palette bitmaps — four or eight bits per pixel — are still used by several well-known favicons and many converters refuse them outright. Broken layers are also handled one at a time, so a single unreadable size does not stop the rest from exporting. The listing also marks any embedded PNG layer that Firefox will discard: its ICO decoder accepts only 8-bit RGB or RGBA, so a palette or greyscale PNG disappears there. Mozilla's own site has shipped an icon with exactly that problem — its 64 px layer is a palette PNG that Firefox itself drops, and only the other layers keep the icon visible.
Is my image uploaded anywhere?
No. The file is read with the browser's File API, drawn on a canvas on this page and packed into the container by JavaScript running locally. No request carries the image anywhere, which you can confirm in the network panel of your developer tools — or by loading the page, going offline and converting anyway.

Related Tools

View all tools →