What Is an ICO File? How to Check a Windows Icon File Before You Trust It
ICO files are Windows icon files that store small images, and readers that open them can still accept damaged ones. Jump to your question below, or work through it in order.
What Is an ICO File? A Windows icon file that stores small images
Short answer
An ICO file is a Windows icon file that stores one or more small images. It starts with a 6 byte header and a list of 16 byte entries. Every entry points to one image, stored as BMP data or PNG data.
We read 153 ICO files and cursor files from nine public projects with six readers. We also damaged one ICO file in 50 ways. All six readers opened 128 of the 153 files and refused 2, and they split on 23. Of the 50 damaged ICO files, all six refused 10 and all six opened 11. Only 8 came back with the same pixels in two decoders.
To check ICO files without an image editor, read the six steps. To see what is inside, read the layout. If your ICO file will not open, begin with the eight causes.
An ICO file is a Windows icon file. It stores one or more small images in one container, and the first 4 bytes 00 00 01 00 name it. The ending .ico is only a label, because the first bytes decide what a file is.
Picture a folder with favicon.ico or app.ico in it. A text editor shows odd symbols, because an ICO file is binary. The ICO file is a small container, and every image inside it has its own size, bit depth and place in the file.
Wikipedia describes the ICO format as a 6 byte header followed by a 16 byte entry for every image. Microsoft explains the same layout on its developer blog, in Raymond Chen's 2010 article on the early icon format. Both agree on the first bytes of an ICO file and on how sizes are stored.
The IANA registry lists the type image/vnd.microsoft.icon with the ending .ico and the first bytes 00 00 01 00. Microsoft is the change controller, and the entry dates from September 2003. PRONOM lists the same format as x-fmt/418 under the type image/x-icon.
A cursor file is nearly the same as an ICO file. Its type field is 2 where an ICO file has 1, and its entries store a hotspot where an ICO file stores its planes and bit depth. We read 7 cursor files among our 153, so this page covers them where they differ.
Where our ICO files come from
Our 153 files come from the test folders of nine public projects. ImageSharp gave 114, image-rs 16, Pillow 13, rust-ico 3, ImageMagick 2 and SDL_image 2. Three single files came from corkami, golang-ico and png-to-ico.
Many are built to be odd, so they include cases that a normal ICO file does not. The 153 files total 3,400,823 bytes and range from 6 bytes to 372,526, with a median of 1,050. By content, 146 are ICO files and 7 are cursors.
The ending is no guide. A file named ImageSharp_cur_fake.ico is a cursor, and one named ImageSharp_ico_fake.cur is an ICO file. The tests below also use 50 damaged ICO files made from one 3,653 byte ICO file, 10 renamed copies and 12 icons taken out of programs.
ICO file facts at a glance
| Property | Value |
|---|---|
| Meaning | Icon. FileInfo files it as an icon file developed by Microsoft. |
| Ending | .ico for icons and .cur for cursors. Two of our files have the wrong ending. |
| First bytes |
00 00 01 00 for an icon and 00 00 02 00 for a cursor, per IANA and Wikipedia.
|
| Header | 6 bytes with a reserved field, a type and an image count. |
| Entries | 16 bytes for every image. Every entry has a width, a height, a color count, a bit depth, a size and an offset. |
| Images | BMP data without the 14 byte BMP file header, or a PNG file. 242 of our 269 images are BMP data and 26 are PNG data. |
| Sizes | One byte for width and one for height. A stored 0 means 256 pixels. |
| Compression | None in the container. gzip cut our 153 files to 27.7 percent of their size. |
| Opens with | Image viewers and editors, per FileInfo. We tested six readers on 153 files. |
| Our tests | 153 ICO files and cursor files, 50 damaged ICO files, 10 renamed copies, 12 icons from programs and 4 converted files. |
Wrong page? A picture that ends in .bmp is a different format. See the BMP file page.
What Is Inside an ICO File? A 6 byte header and a list of 16 byte entries
An ICO file is a 6 byte header, a list of 16 byte entries and then the images. Our example, base.ico, is 3,653 bytes long with 4 images, and its entry list starts at byte 6 and ends at byte 69.
We took one ICO file from the ImageSharp tests and called it base.ico, so every byte can be read. It has a 16 pixel BMP image and PNG images of 24, 32 and 48 pixels. The figure shows its blocks from the outside in.
Read the figure from the top. The first check in an ICO file is the 4 bytes at the start, 00 00 01 00. Wikipedia's layout notes list the other fields in order, and Chen's 2010 article gives the same fields.
The header of an ICO file, byte by byte
xxd -l 22 base.ico
00000000: 0000 0100 0400 1010 0000 0100 2000 6804 ............ .h.
00000010: 0000 4600 0000 ..F...
Bytes 0 and 1 of an ICO file, 00 00, are reserved and must be 0. Bytes 2 and 3, 01 00, are the type, where 1 means icon. Bytes 4 and 5, 04 00, are the image count of 4. Windows stores numbers low byte first.
The first entry of the ICO file starts at byte 6. 10 10 are the width and height, 16 and 16. 01 00 is 1 plane and 20 00 is 32 bits per pixel. 68 04 00 00 is a size of 1,128 bytes, and 46 00 00 00 is an offset of 70.
The 4 entries of this ICO file take 64 bytes, so the list ends at byte 69 and the first image starts at byte 70. The images follow in list order. We found no gap and no overlap between images in any of our files.
The two kinds of image inside an ICO file
A BMP image inside an ICO file has no 14 byte BMP file header. It starts with the 40 byte header, as Wikipedia says. The height field is doubled, because the pixels are followed by a 1 bit mask. In base.ico the first image says width 16 and height 32.
A PNG image is a complete PNG file that starts with 89 50 4e 47 0d 0a 1a 0a. Wikipedia says PNG support came with Windows Vista. Chen's 2023 article on icon resources inside programs says the image data is a bitmap or a PNG.
In this ICO file the 16 pixel image is BMP data and the three larger ones are PNG data. A reader must look at the first bytes of every image, because the entry does not say which kind it points to.
The entry fields of an ICO file
| Field | What we found |
|---|---|
| Width and height | One byte for the width and one for the height. A stored 0 means 256, so 20 of our 269 images use it. 12 images are not square, like 24 by 14. |
| Color count | 0 when the image has no palette, per Wikipedia. Copy D4, with 255 here, was opened by all six readers. |
| Reserved byte | Must be 0. Copy D5, with 1 here, was refused by the file command only. |
| Planes | 1 in 247 of 259 icon entries. In a cursor this field stores the hotspot x. |
| Bit count | 32 in 131 of 259 entries, then 8 in 39, 4 in 29, 24 in 28 and 1 in 22. In a cursor this field stores the hotspot y. |
| Size | The length of the image in bytes. 3 entries point past the end of the file. |
| Offset | Counted from byte 0. 6 files have extra bytes after the last image. |
The list is small. Our script reads 6 bytes and the entries of an ICO file. It decodes no image, so damage deeper in the file can pass it, as the damage tests show.
Which Kind of ICO File Do You Have? The ending names none of the images, colors or sizes
Four questions sort an ICO file, how many images it has, how every image is stored, how deep the colors are and how big the pictures are. Of 152 readable files, 127 have one image, and 242 of 269 images are BMP data. The ending names none of this.
Most questions about ICO files come down to which sizes are inside and how the images are stored. The entry list answers both without decoding a picture, and the first bytes of every image answer the second.
One image or many
127 of our readable ICO files have a single image. 16 have 2 to 5 images and 9 have 7 to 12. The most is 12, and no file has 6, 8 or 11.
BMP data or PNG data
Of 269 images, 242 are BMP data, 26 are PNG data and one is neither. 241 of the BMP images have a 40 byte header, and one has a 124 byte header. The ending of an ICO file names none of these.
Size shows the difference. 9 of our images are 256 pixels wide BMP data, with a median of 204,840 bytes and a maximum of 270,376. 11 are 256 pixel PNG data, with a median of 33,399 bytes. 15 PNG images are smaller than 256 pixels.
Colors and sizes
Among 259 entries in ICO files, 131 say 32 bit, 39 say 8 bit, 29 say 4 bit, 28 say 24 bit and 22 say 1 bit. Ten say 0 or 500. 12 entries have a plane count other than 1.
The top size is 32 by 32 with 59 images, then 16 by 16 with 44 and 48 by 48 with 28. 20 images are 256 by 256, 11 are 64 by 64 and 11 are 24 by 24. Another 87 images have other sizes.
Not sure the file is an ICO file at all? Check it with our script.
What Did We Find in 153 Icon Files? Six readers, and a split on 23 files
We read 153 ICO files and cursor files from nine public projects with six readers. The file command and our script opened 149, ImageMagick 146, Pillow 143, ffprobe 139 and icotool 135. All six opened 128 files together, and none opened 2.
We took 153 files from the test folders of ImageSharp, image-rs, Pillow, rust-ico, ImageMagick, SDL_image, corkami, golang-ico and png-to-ico. They are public test files and not a sample of the ICO files on a typical PC. Many are odd on purpose.
The readers were the file command 5.45, our 49 line Python script, Pillow 12.3.0, ImageMagick 6.9.12 with identify, icotool 0.32.3 and ffprobe 6.1.1. We worked on Linux with Python 3.13. We opened no ICO file in Windows Explorer, Paint or Photos.
A reader opened an ICO file when it listed at least one image with a size above 0 and gave no error. That is a light test, because it asks for a list and not for a picture. So we also asked four decoders to draw every image.
| Test | Result |
|---|---|
| Opened | The file command and our script opened 149 of 153 files, ImageMagick 146, Pillow 143, ffprobe 139 and icotool 135. |
| Together | All six readers opened 128 files. None opened 2, and the readers split on 23. |
| Cursors | ffprobe refused all 7 cursor files. Pillow counted 1 image in a cursor with 5. |
| Drawing | Four decoders drew the pixels. ImageMagick drew 146 files, Pillow 143, icotool 134 and ffmpeg 134. All four drew 129. |
| Labels | The file command called 2 of the 15 files that start with a 256 pixel image Targa pictures. |
| Sizes | From 6 to 372,526 bytes. The median is 1,050, and the 153 files total 3,400,823 bytes. |
| Compression | gzip level 9 cut the 153 files to 27.7 percent of their size, and xz cut them to 24.4 percent. |
All six readers opened 128 of the 153 files. Two files were opened by none. The other 23 split the readers, and 6 of those 23 are cursor files.
The 23 files that split the readers
The ffprobe tool refused all 7 cursor files. The icotool program refused 3 of them, including Pillow_no_cursors.cur, which has a header and no entries. No reader opened that file.
The file command called two ICO files Targa pictures. They are ImageSharp_8bpp_size_256x256.ico and Pillow_pillow.ico, and both start with a 256 pixel image. The other five readers opened both.
The icotool program listed 1 of the 5 images in Pillow_pillow.ico. The entry for its 48 pixel image says 9,832 bytes, and the BMP header implies 9,640. It also refused rust-ico_wiki.ico, which has the same mismatch.
The files named invalid, crash and oom
ImageSharp ships six ICO files named invalid. The file command opened all six, our script 5, ffprobe 5, ImageMagick 3, Pillow 1 and icotool none. A reader that opens an invalid ICO file has read the list and little more.
image-rs keeps three ICO files named crash or oom. The file command opened 2 of them and our script 1. No other reader opened any. They are 271, 348 and 659 bytes long.
How big the files are
74 files are under 1 KB, 50 are between 1 KB and 9.9 KB, 17 are between 10 KB and 99 KB and 12 are 100 KB or more. The middle file is 1,050 bytes long.
Read the study with care. It shows what six readers do with 153 public test files. 114 of them come from one test generator, and many are odd on purpose. A reader that agrees on our files can still fail on your ICO file.
What Do Readers Do With a Damaged Icon? 50 broken copies, six readers and 29 split decisions
We damaged one 3,653 byte ICO file in 50 ways. All six readers refused 10 damaged copies, all six opened 11 and the readers split on 29. The file command opened 37 and ffprobe 22. Only 8 copies came back with the same pixels in both Pillow and ImageMagick.
The 50 damaged ICO files are copies of base.ico and come in six groups. Group A changes header fields, B the first bytes and C cuts the file short. D changes entry fields, E image data and F adds or changes bytes. Every damaged ICO file changes one thing.
We asked two questions about every damaged ICO file. Did the six readers open it? And did Pillow and ImageMagick draw the same pixels as the intact file? The second question is the strict one, and we compared a hash of the pixels.
The 10 copies that every reader refused
Copies A1, A2, A4 and A5 broke the header of the ICO file. They have a reserved field of 1, a type of 0, a type of 3 or an image count of 0. B1, B2 and B3 remove 6 bytes, add 16 zero bytes in front or zero the header.
C1, C2 and C3 cut the ICO file at 4 bytes, at 6 bytes and right after the entry list. All six readers refused all ten. The icotool program names the reserved field when it refuses A1.
The 11 copies that every reader opened
Some entry damage in an ICO file went unseen. A color count of 255 (D4), a bit depth of 0 (D7) and two images that share an offset (D15) passed every reader. So did an image count of 2 on an ICO file with 4 images (A7) and a BMP plane count of 5 (E6).
Extra bytes at the end also passed. 64 KB of random bytes (F1), 100 bytes of text (F2) and a second copy of the ICO file (F3) matched in both decoders. So did D4 and E6, which makes five of the 11.
Opened does not mean the same pixels. A first width of 200 (D2) was opened by all six, and the file command printed a width of -56. Pillow and our script took 200 by 16 from the entry, and the other three took 16 by 16 from the BMP header.
F4 and F5 set the middle of the first image to ff or to random bytes. All six readers opened both, and neither decoder returned the intact pixels. The same is true of A7, D2, D7 and D15, which makes six of the 11.
The 29 copies that split the readers
Of the 50 damaged ICO files, ffprobe opened only 22 and ImageMagick 23, fewer than any other reader. The file command opened 37, Pillow 34, our script 30 and icotool 29.
An image count of 65535 (A8) was opened by the file command only. A type of 2 (A3) makes the ICO file a cursor. Four readers opened it, and Pillow and ffprobe refused it.
Cuts split the readers too. Removing the last byte (C5) was accepted by four readers, and Pillow drew the intact pixels. A cut in half (C4) and the loss of the last 100 bytes (C6) were opened by the file command and icotool only.
An image offset of 0 (D12) or past the end of the ICO file (D13) was opened by Pillow and icotool only. A size that points past the end (D10 and D11) was opened by the file command and Pillow only.
What our script passes
Our script opened 30 of the 50 damaged ICO files. Of those 30, 22 did not come back with the same pixels in both decoders, because the script reads no image. A pass from the script means the header and the list make sense. It does not mean the pictures draw.
Read the grid with care. Every copy changes one thing in one ICO file from one test generator. Damage in the wild changes many things at once. Same pixels means a hash of the drawn pixels matched the intact file. We opened no copy in Windows Explorer, Paint or Photos.
What Does Our Expert Say About ICO Files? A note from Neeraj Singh on trusting one reader
Check ICO files with two readers before you trust one answer. Six readers opened 128 of 153 files together and split on 29 of 50 damaged ICO files. A header check takes seconds, and a size list from a second reader takes a little longer.
Expert insight
“ICO files look like one more picture format, so people open them in the first viewer that accepts them. In our tests six readers split on 23 of 153 files, and only 8 of 50 damaged ICO files came back with the same pixels in both decoders. Check every ICO file with two readers, compare the image sizes and read the first bytes before you rely on the ending.”
Why one reader proves little
A reader that opens an ICO file shows that the header and the list make sense. It does not show that the images draw. In our tests the file command opened 37 of 50 damaged ICO files, and only 8 of the 50 came back with the same pixels in both decoders.
The check has a limit. Two readers that agree can both be wrong, and neither says whether the picture looks right. The script from the check reads 6 bytes and the entry list of an ICO file, so compare its answer with a second reader and look at the picture.
Copy the ICO file before you touch it. Write down the SHA256 hash of the original and work on a copy. The hash shows which ICO file you received, and it lets you spot a changed download later.
How Do You Open an ICO File? Six readers we tested and two viewers from outside pages
Many Windows programs open ICO files, and Microsoft's Windows Imaging Component has an ICO page of its own. We tested six other readers on 153 files instead, and we opened no file in a Windows viewer.
The table lists the programs we tested and the one Microsoft page we read. The readers with a version number are the ones we tested. We worked on Linux, so we opened no ICO file in Windows Explorer, Paint or Photos.
| Program | What it does |
|---|---|
| Windows Imaging Component | Microsoft's WIC overview of the ICO format lists the ending .ico and the type image/ico, and says Windows has no native ICO encoder. We tested nothing here. |
| The file command | Version 5.45. It names the type from the header and opened 149 of 153 files. For an ICO file it prints the image count and the first sizes. |
| Our script | A 49 line Python script that reads the 6 byte header and the entry list. It opened 149 of 153 files and decodes no image. |
| Pillow | A Python library, version 12.3.0. It opened 143 files, lists the sizes and draws the images. |
| ImageMagick | Version 6.9.12. The identify program opened 146 files and the convert program writes ICO files. |
| icotool | Part of icoutils 0.32.3. It opened 135 files, extracts images and builds ICO files. |
| ffprobe | Version 6.1.1. It opened 139 files, refused all 7 cursor files and refused 3 of 10 renamed copies. |
Open ICO files on the command line
Three commands list the images of an ICO file. For base.ico, the file command prints the first two and writes a literal \012- where a line break belongs. The identify program and icotool list all four.
file -b base.ico
MS Windows icon resource - 4 icons, 16x16, 32 bits/pixel, 24x24 with \012- PNG image data, 24 x 24, 8-bit/color RGBA, non-interlaced, 32 bits/pixel
identify base.ico
base.ico[0] ICO 16x16 16x16+0+0 8-bit sRGB 0.000u 0:00.000
base.ico[1] PNG 24x24 24x24+0+0 8-bit sRGB 605B 0.000u 0:00.000
base.ico[2] PNG 32x32 32x32+0+0 8-bit sRGB 760B 0.000u 0:00.000
base.ico[3] PNG 48x48 48x48+0+0 8-bit sRGB 3653B 0.000u 0:00.000
icotool --list base.ico
--icon --index=1 --width=16 --height=16 --bit-depth=32 --palette-size=0
--icon --index=2 --width=24 --height=24 --bit-depth=32 --palette-size=0
--icon --index=3 --width=32 --height=32 --bit-depth=32 --palette-size=0
--icon --index=4 --width=48 --height=48 --bit-depth=32 --palette-size=0
The icotool numbers start at 1, and identify numbers start at 0. All three agree on 16, 24, 32 and 48 pixels. The identify program prints 3653B for the last image, which is the size of the file and not of the image.
Open ICO files with Python
The Python package Pillow reads the same list. Six lines print the size and color mode of every image in an ICO file. The load call decodes the pixels, so a damaged image fails here and not at the open.
from PIL import Image
im = Image.open('base.ico')
for s in sorted(im.ico.sizes()):
img = im.ico.getimage(s)
img.load()
print(s, img.mode)
(16, 16) RGBA
(24, 24) RGBA
(32, 32) RGBA
(48, 48) RGBA
Pillow failed on 10 of the 153 files and on 16 of the 50 damaged ICO files, so read its answer with care. The damage grid lists the copies where its pixels differed from the intact file.
Viewers and converters for ICO files
These two links open outside pages for ICO files. One comes from SysTools and one from Freeviewer. We describe them from their own pages and tested neither.
The SysTools Image Converter lists ICO among its inputs and not among its outputs, so it reads an ICO file and does not write one. Its page lists outputs like PDF, PNG, JPG, BMP and TIFF. Its demo converts the first 5 files and adds a watermark.
Freeviewer's page describes an image viewer for Windows that lists ICO and ICON among its formats. It previews images in bulk, reorders them and prints them. Its free version reads files and exports the first 5 images. We list no prices, because they change.
Install a viewer from its maker. Download a viewer from the maker's own page, and write down the file hash if the page gives one. ICO files do not need special software, and our six readers worked without any.
How Do You Check an ICO File? Six steps, and only one of them reads image data
Check ICO files in six steps. Read the first 4 bytes, then the image count, then the entry list with our 49 line script. Only the last step reads image data. The script reads 6 bytes and the entries, and it stops there.
The first reads need no Python. The xxd command prints bytes, and the file command names the type of an ICO file. For base.ico they show a type of 1, a count of 4 and the first entry.
xxd -l 22 base.ico
00000000: 0000 0100 0400 1010 0000 0100 2000 6804 ............ .h.
00000010: 0000 4600 0000 ..F...
file -b base.ico
MS Windows icon resource - 4 icons, 16x16, 32 bits/pixel, 24x24 with \012- PNG image data, 24 x 24, 8-bit/color RGBA, non-interlaced, 32 bits/pixel
Read the first line from the left. Bytes 0 to 3, 00 00 01 00, are the reserved field and the type of the ICO file. Bytes 4 and 5, 04 00, are the count. The file command prints the same facts as words, and it names the first two images.
Step 4 starts at byte 6 of the ICO file. Every entry is 16 bytes long. The width and height come first, and the size and offset come last. A cursor starts with 00 00 02 00 instead.
Check ICO files with Python
The script reads the 6 header bytes of ICO files and then the entry list. It prints the type, the image count and the file size, then one line for every image. It decodes no image, and it never changes an ICO file.
#!/usr/bin/env python3
"""ico_peek.py - read the 6 byte header and the 16 byte entries of an ICO or CUR file. Decodes no pixels.
Usage: python3 ico_peek.py FILE [FILE ...]
"""
import os, struct, sys
PNG = b'\x89PNG\r\n\x1a\n'
def kind(blob):
if blob[:8] == PNG:
return 'PNG'
if len(blob) >= 4 and struct.unpack('<I', blob[:4])[0] in (12, 40, 52, 56, 108, 124):
return 'BMP, %d byte header' % struct.unpack('<I', blob[:4])[0]
return 'unknown data (%s)' % blob[:4].hex(' ')
def peek(path):
size = os.path.getsize(path)
with open(path, 'rb') as f:
head = f.read(6)
if len(head) < 6:
return '%s: header cut short at %d bytes' % (path, len(head))
zero, kind_id, count = struct.unpack('<HHH', head)
if kind_id not in (1, 2):
return '%s: not an icon or cursor, the first 6 bytes are %s' % (path, head.hex(' '))
name = 'ICO' if kind_id == 1 else 'CUR'
out = ['%s: %s, %d images, file is %d bytes' % (path, name, count, size)]
if zero:
out.append(' warning: the first two bytes are not 0')
if count == 0 or 6 + count * 16 > size:
out.append(' warning: the entry list does not fit inside the file')
return '\n'.join(out)
for i in range(count):
f.seek(6 + 16 * i)
w, h, colors, res, a, b, length, where = struct.unpack('<BBBBHHII', f.read(16))
w, h = w or 256, h or 256
extra = 'hotspot %d,%d' % (a, b) if kind_id == 2 else '%d bit' % b
f.seek(where)
blob = f.read(min(length, 8)) if where < size else b''
note = ''
if where + length > size:
note = ' (ends past the end of the file)'
elif where < 6 + count * 16:
note = ' (starts inside the entry list)'
out.append(' image %d: %dx%d, %s, %d bytes at %d, %s%s' % (
i, w, h, extra, length, where, kind(blob) if blob else 'no data', note))
return '\n'.join(out)
for p in sys.argv[1:]:
print(peek(p))
Here is what it printed for three files. They are base.ico, a cursor with a hotspot and an ICO file with a 256 pixel PNG image beside four BMP images.
python3 ico_peek.py base.ico sample.cur pillow.ico
base.ico: ICO, 4 images, file is 3653 bytes
image 0: 16x16, 32 bit, 1128 bytes at 70, BMP, 40 byte header
image 1: 24x24, 32 bit, 605 bytes at 1198, PNG
image 2: 32x32, 32 bit, 760 bytes at 1803, PNG
image 3: 48x48, 32 bit, 1090 bytes at 2563, PNG
sample.cur: CUR, 1 images, file is 3254 bytes
image 0: 23x42, hotspot 1,24, 3232 bytes at 22, BMP, 40 byte header
pillow.ico: ICO, 5 images, file is 102602 bytes
image 0: 256x256, 32 bit, 84676 bytes at 86, PNG
image 1: 48x48, 32 bit, 9832 bytes at 84762, BMP, 40 byte header
image 2: 32x32, 32 bit, 4392 bytes at 94594, BMP, 40 byte header
image 3: 24x24, 32 bit, 2488 bytes at 98986, BMP, 40 byte header
image 4: 16x16, 32 bit, 1128 bytes at 101474, BMP, 40 byte header
The first line of every answer gives the type, the image count and the file size. Later lines give the size, bit depth, byte length, offset and kind of every image. A cursor prints a hotspot in place of the bit depth.
python3 ico_peek.py testsrc.png A1.ico C3.ico D13.ico
testsrc.png: not an icon or cursor, the first 6 bytes are 89 50 4e 47 0d 0a
A1.ico: ICO, 4 images, file is 3653 bytes
warning: the first two bytes are not 0
image 0: 16x16, 32 bit, 1128 bytes at 70, BMP, 40 byte header
image 1: 24x24, 32 bit, 605 bytes at 1198, PNG
image 2: 32x32, 32 bit, 760 bytes at 1803, PNG
image 3: 48x48, 32 bit, 1090 bytes at 2563, PNG
C3.ico: ICO, 4 images, file is 70 bytes
image 0: 16x16, 32 bit, 1128 bytes at 70, no data (ends past the end of the file)
image 1: 24x24, 32 bit, 605 bytes at 1198, no data (ends past the end of the file)
image 2: 32x32, 32 bit, 760 bytes at 1803, no data (ends past the end of the file)
image 3: 48x48, 32 bit, 1090 bytes at 2563, no data (ends past the end of the file)
D13.ico: ICO, 4 images, file is 3653 bytes
image 0: 16x16, 32 bit, 1128 bytes at 3753, no data (ends past the end of the file)
image 1: 24x24, 32 bit, 605 bytes at 1198, PNG
image 2: 32x32, 32 bit, 760 bytes at 1803, PNG
image 3: 48x48, 32 bit, 1090 bytes at 2563, PNG
The file testsrc.png is a PNG picture and fails the first check. A1 has a reserved field of 1 and prints a warning. C3 was cut at 70 bytes, and D13 has an image offset of 3,753 in an ICO file of 3,653 bytes. Both print that an image ends past the end.
What the script found in our files
| Result | Cases |
|---|---|
| Read (149 of 153) | The script read the 149 files with a list that fits inside the file and images that end inside it. |
| Refused (4 of 153) | It refused Pillow_no_cursors.cur, which has no entries, and three files whose first image ends past the end of the file. |
| Refused copies (20 of 50) | It refused A1, A2, A4, A5, A6, A8, B1, B2, B3, C1, C2, C3, C4, C5, C6, D10, D11, D12, D13 and D14. |
| Passed with differences (22 of 30) | The script passed 30 damaged ICO files, and 22 of those did not come back with the same pixels in both decoders, because the script reads no image. |
The script reads the header and the list and nothing else. It does not decode an image or compare the pixels. ICO files with broken images can pass it, so the damaged ICO files matter.
Check order for any ICO file
- Copy the ICO file, write its SHA256 hash and work on the copy.
-
Read the first 4 bytes of the ICO file. They must be
00 00 01 00for an icon. The bytes00 00 02 00mean a cursor. - Read bytes 4 and 5 for the image count. Then read the entry list, where every entry is 16 bytes long.
- Read the list with our script. A warning means the list does not fit inside the file or an image ends past the end.
- Compare with the file command and with identify or icotool. A difference points to damage or a reader limit.
- Draw every image with Pillow, as in the Python example, and compare the sizes with the list. Only this step reads image data.
Is an ICO File Safe to Open? Reading is safe, and a name proves nothing
Reading an ICO file with a reader is safe, because the file is data. The name proves nothing. Four readers read a renamed icon under all 10 names, and 8 other files with the ending .ico were not icons.
We opened no ICO file in a viewer and scanned none for malware. The six readers only read bytes. The files come from public test folders, so their contents are not the worry here.
The rename test
We copied base.ico to 10 names, like base.png, base.jpg, base.txt, base.cur, favicon and base.ico.txt. The file command, our script, Pillow and icotool read all 10 as the same ICO file. ImageMagick opened only base.cur and base.ICO. ffprobe refused the names ending .png, .jpg and .bmp. So those two trust the ending.
The reverse also works. We gave 8 other files the ending .ico. They are PNG, JPEG, GIF and BMP pictures, a ZIP archive, an ELF program, a text note and an empty file. The file command named the true type of all 8, and our script and icotool refused all 8.
Pillow and ffprobe opened the 4 pictures as pictures, and ImageMagick opened 2. No reader took the ZIP, the ELF, the text or the empty file for an ICO file. If your file manager hides endings, a name can pass for an ICO file and be a program. Show full names and read the first bytes of anything you doubt.
What an ICO file can contain
An ICO file stores a header, a list and images. In our files the only extras were bytes after the last image and text chunks inside PNG images. 6 files end with extra bytes, from 1 to 1,088.
8 of our 26 PNG images have a tIME chunk and 8 have a tEXt chunk. They come from 3 files. A tIME chunk stores a time and a tEXt chunk stores text. Check your own favicon for chunks before you publish it, because anyone who loads your page can download it.
Icons inside programs
Programs keep their icons as resources inside the EXE or DLL file, as Chen explains in his 2023 article. The ICO file is a copy that a tool writes out. See the EXE file page for the program side.
We tested the extraction on 37 program files, 32 EXE files and 5 DLL or PYD files. The wrestool program from icoutils 0.32.3 found 13 icon groups in 8 of them. They made 12 different ICO files, and all six readers and all four decoders opened all 12.
Not sure? Check it first. Copy the hash, read the header with the entry list script and compare another reader. If the ICO file came in an email you did not expect, delete the message and ask the sender through another route.
Why Will Your ICO File Not Open? Eight causes, and what to do about every one
Most ICO files that will not open fail for one of eight reasons. Read the first bytes first, then the entry list, then draw the images. Our six readers refused 10 of 50 damaged ICO files and opened 11, and 6 of those 11 still drew different pixels.
We read 153 files and 50 damaged ICO files with six readers. The table groups what we saw into eight causes. The number in brackets matches the cause.
Every row says what happens to the ICO file and what to try. The fixes work on a copy, and none changes the original. A reader that says nothing is no sign that the images draw.
| Cause | Result and fix |
|---|---|
| A damaged header or first bytes (1) | All six readers refused 7 of our 50 damaged ICO files. Three had a reserved field of 1, a type of 0 or 3 or a count of 0. The others had the first 6 bytes removed, 16 zero bytes in front or a zeroed header. Fix: Copy the ICO file again from the source and compare the SHA256 hash. We tested no repair. |
| A cut copy (2) | A copy cut at 4 bytes, at 6 bytes or right after the entry list was refused by all six readers. A copy cut in half was opened by the file command and icotool only, and neither decoder drew the intact pixels. Fix: Compare the size and the hash with the source, then copy the ICO file again. |
| A file that is not an icon (3) |
A PNG, JPEG, GIF or BMP picture named .ico has no 00 00 01 00. Our script and icotool refused all 8 other files, and Pillow and ffprobe opened the 4 pictures as pictures. Fix: Read the first 4 bytes. If they are not 00 00 01 00, name the type with the file command and open the file as that type.
|
| A bad entry list (4) | An image offset of 0 or past the end of the ICO file was opened by Pillow and icotool only. A size that points past the end was opened by the file command and Pillow only. Fix: Read the list with our script. A warning says an image ends past the end of the file. |
| Damaged image data (5) | Three to five readers opened a BMP with a height of 0, a PNG with a zeroed checksum and a PNG with a zeroed middle. Neither decoder drew the intact pixels. Fix: Draw the images with two decoders, then ask for a new ICO file. |
| A wrong ending (6) | ImageMagick opened 2 of our 10 renamed copies, and ffprobe refused the names ending .png, .jpg and .bmp. A program that trusts the ending can refuse a good ICO file. Fix: Copy the ICO file to a name that ends in .ico, or read it with the file command, Pillow or icotool. |
| A cursor (7) |
ffprobe refused all 7 cursor files, including ImageSharp_cur_fake.ico, and icotool refused 3. ImageMagick opened 6 of the 7. Fix: Read bytes 2 and 3. If they are 02 00, the file is a cursor, so use a reader that accepts cursors.
|
| A strict reader (8) | ffprobe opened 22 of the 50 damaged ICO files and ImageMagick 23, while the file command opened 37. A refusal from one reader is no proof that the file is lost. Fix: Try a second reader, like the file command, Pillow or icotool, before you decide. |
Check ICO files that will not open, step by step
We tested the reading steps on Python 3.13 and Linux. We opened no ICO file in a Windows viewer, and the steps keep the original untouched at every point.
- Copy the ICO file, write its SHA256 hash and work on the copy.
-
Read the first 4 bytes of the ICO file with the check steps. If they are not
00 00 01 00, name the type with the file command. - Read the entry list with the list script. A warning names the point where the ICO file stops making sense.
- Compare with identify or icotool, as in the command line listing. A list of images means the entries make sense.
- Draw every image with Pillow, as in the Python drawing, and compare the sizes with the list.
- If the ICO file is smaller than the source says, copy it again and compare the hash.
- If one reader refuses the ICO file, try another before you decide, as the split files show.
What to send a helper
Short messages about an ICO file get faster answers. Include the details below, and add the script output. Its first line gives the type, image count and file size, and later lines name every image.
Subject: ICO file will not open
File: name, size in bytes and SHA256 hash
Header: the output of ico_peek.py
Reader: name, version and the exact words of the error
Platform: Windows, Mac or Linux and the program you used
Source: where the file came from and when it was copied
What no step can fix
Do not try online repair sites. A site that offers to fix or convert any ICO file for free can keep the upload. A PNG icon can have text chunks, as the privacy check shows. Try the steps above on a copy first.
How Do You Make an ICO File or a Favicon? Four writers on one PNG picture, and icotool refused one result
ImageMagick, Pillow, icotool and ffmpeg all wrote an ICO file from one 256 pixel PNG picture. ImageMagick and Pillow wrote 6 images, and icotool and ffmpeg wrote 1. The files range from 18,711 to 270,622 bytes, and icotool refused the ffmpeg file.
Making an ICO file means writing a header, a list and images. We tested four writers on one 256 by 256 PNG picture of 3,618 bytes. The table lists what the four wrote, and every row ends with the tests behind it.
| Tool | What it wrote |
|---|---|
| ImageMagick | The convert program wrote an ICO file with 6 images in 103,267 bytes. The 256 pixel image is PNG data and the five smaller ones are BMP data. All six readers opened it. Source: Our tests. |
| Pillow | The save call wrote an ICO file with 6 images in 18,711 bytes, all as PNG data. All six readers opened it. Source: Our tests. |
| icotool | The create option wrote an ICO file with 1 image in 270,398 bytes, as BMP data. All six readers opened it. Source: Our tests. |
| ffmpeg | It wrote an ICO file with 1 image in 270,622 bytes, as BMP data. The entry says 270,600 bytes and the BMP header implies 270,376. The icotool program refused it, and the other five readers opened it. Source: Our tests. |
Make an ICO file from a PNG picture
The four commands below made the four files. The option -c makes icotool create a file. The size list for Pillow is our choice, and ImageMagick takes its list from the option icon:auto-resize.
convert testsrc.png -define icon:auto-resize=256,128,64,48,32,16 out_magick.ico
python3 -c "from PIL import Image; Image.open('testsrc.png').save('out_pillow.ico', sizes=[(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)])"
icotool -c -o out_icotool.ico testsrc.png
ffmpeg -i testsrc.png out_ffmpeg.ico
ls -l out_*.ico | awk '{print $5, $9}'
270622 out_ffmpeg.ico
270398 out_icotool.ico
103267 out_magick.ico
18711 out_pillow.ico
The ImageMagick ICO file stores the 256 pixel image as PNG data and the five smaller ones as BMP data. The Pillow ICO file stores all six as PNG data, so it is about a fifth of the size. Our script lists both.
python3 ico_peek.py out_magick.ico out_pillow.ico
out_magick.ico: ICO, 6 images, file is 103267 bytes
image 0: 256x256, 32 bit, 3573 bytes at 102, PNG
image 1: 128x128, 32 bit, 67624 bytes at 3675, BMP, 40 byte header
image 2: 64x64, 32 bit, 16936 bytes at 71299, BMP, 40 byte header
image 3: 48x48, 32 bit, 9640 bytes at 88235, BMP, 40 byte header
image 4: 32x32, 32 bit, 4264 bytes at 97875, BMP, 40 byte header
image 5: 16x16, 32 bit, 1128 bytes at 102139, BMP, 40 byte header
out_pillow.ico: ICO, 6 images, file is 18711 bytes
image 0: 16x16, 32 bit, 722 bytes at 102, PNG
image 1: 32x32, 32 bit, 1555 bytes at 824, PNG
image 2: 48x48, 32 bit, 2349 bytes at 2379, PNG
image 3: 64x64, 32 bit, 3290 bytes at 4728, PNG
image 4: 128x128, 32 bit, 7075 bytes at 8018, PNG
image 5: 256x256, 32 bit, 3618 bytes at 15093, PNG
Why icotool refuses the ffmpeg file
The ffmpeg ICO file has one 256 pixel BMP image. Its entry says 270,600 bytes, and the BMP header implies 270,376. The icotool program warns about the total size and refuses the ICO file. ImageMagick, Pillow, ffmpeg and the other readers drew it.
Notes on favicons
Google's favicon page lists BMP, GIF, ICO, PNG, JPEG, PPM and TIFF as supported formats, so an ICO file is not required. The picture must be square and at least 8 by 8 pixels, and Google recommends more than 48 by 48. The page requires no file name.
We tested no favicon in a browser or in search. We tested whether four tools can write an ICO file and whether six readers can open it. We also tested drawing, and did not test saving the images out of an ICO file.
Keep the original picture. Convert from a large PNG picture and keep it. A 256 pixel BMP image costs about six times the bytes of a PNG image, as the kinds part shows.
How Does an ICO File Differ From CUR, BMP and PNG Files? The first bytes name the type
The first bytes name the type. ICO files start with 00 00 01 00, cursors with 00 00 02 00, BMP files with BM and PNG files with 89 50 4e 47. Programs keep icons as resources, and a favicon is a job, not a format.
Six things get mixed up with ICO files because they all contain small pictures. The table lists what separates them. Every row ends with its source.
| Type | What separates it |
|---|---|
| ICO file |
Starts with 00 00 01 00. A header, a list and 1 to 12 images in our files, stored as BMP data or PNG data. Source: IANA and our tests.
|
| CUR file |
Starts with 00 00 02 00. The entries store a hotspot where an ICO file stores planes and bit depth. 7 of our 153 files are cursors. Source: Wikipedia and our tests.
|
| BMP file |
Starts with the letters BM (42 4d) and has one picture behind a 14 byte file header. An ICO file stores BMP data without that header. Source: Wikipedia and our tests.
|
| PNG file |
Starts with 89 50 4e 47 0d 0a 1a 0a. 26 of the 269 images in our files are complete PNG files. Source: Our tests.
|
| Icon resource in a program | Stored inside an EXE or DLL file as a resource and not as an ICO file. A tool like wrestool writes it out. Source: Chen and our tests. |
| Favicon | A job and not a format. Google lists BMP, GIF, ICO, PNG, JPEG, PPM and TIFF. Source: Google. |
Separate them with our script
Our script reads the first 6 bytes of an ICO file and refuses any file that does not have a reserved 0 and a type of 1 or 2. For a PNG file it says the first 6 bytes are 89 50 4e 47 0d 0a. It never guesses.
Why the ending misleads
ImageSharp_cur_fake.ico is a cursor, and ImageSharp_ico_fake.cur is an ICO file. Ten renamed copies of one ICO file read the same in four readers under every name. A PNG picture named .ico is still a PNG. An ending is a label, and the first bytes say what a file is.
Which one do you have
42 4d.
What Is the ICO File Format Made Of? The facts we could check, and where they came from
Microsoft created the ICO format, and IANA, Wikipedia and Raymond Chen document the layout. The facts below come from those sources, from FileInfo and from our checks of 153 files and 50 damaged ICO files.
| Part | What we could check |
|---|---|
| Maker | Microsoft. IANA names Microsoft as the change controller, and FileInfo lists Microsoft as the developer. |
| Name | Icon. IANA registers image/vnd.microsoft.icon. Wikipedia says Microsoft uses image/x-icon, and PRONOM uses it for x-fmt/418. |
| First bytes |
00 00 01 00, as IANA lists. All 146 of our icons have a type of 1.
|
| Header | 6 bytes. A reserved field of 0, a type of 1 for an icon or 2 for a cursor and an image count. |
| Entries | 16 bytes for every image. Width, height, color count, reserved byte, planes or hotspot x, bit count or hotspot y, size and offset. |
| Image data | BMP data without the 14 byte file header, or a PNG file from Windows Vista. The BMP height is doubled for the mask. Wikipedia and Chen agree. |
| Sizes | A stored 0 for width or height means 256. Wikipedia dates it from Windows 95, and Chen says Windows 95 and NT 4. |
| Compression | None in the container. gzip cut our 153 files to 27.7 percent of their size. |
| Endings | .ico and .cur. Two of our files have the wrong one. |
| Specification | IANA names Icons in Win32, written by Hornick in 1995, as the specification. |
| Our tests | 153 ICO files and cursor files, 50 damaged ICO files, 10 renamed copies, 8 other files, 12 icons from programs and 4 converted files. Six readers and a 49 line script all worked on Linux. |
About the values we list
Facts about the layout come from Wikipedia, Chen and IANA, and every row names its source. The first bytes and the header sizes were also checked against our files. FileInfo and PRONOM are directories, so we use them for the name and the type only.
Where a source and our tests disagree, we say so. Chen's first article, on monochrome icons, says the compression must be BI_RGB, which means none. Our tests opened RLE copies in five of six readers. We do not know what Windows itself does with them.
What we left out
We opened no ICO file in Windows Explorer, Paint or Photos, and we tested no browser. We tested no repair and no deletion, and we scanned no ICO file for malware. We tested no viewer from an outside page.
Our 153 files come from 9 public test folders, and 114 come from one generator. Our damaged ICO files change one thing at a time in one ICO file. A reader that fails on our files can still work on your ICO file, and the reverse is true as well.
Sources checked
For the layout, see the Wikipedia article on the ICO format, Chen's article on the icon format and Chen's article on icon resources. For the type, see the IANA entry for image/vnd.microsoft.icon.
For Windows, see the Microsoft page on the ICO format in WIC. For the directories, see the FileInfo page on ICO files and the PRONOM record x-fmt/418.
For favicons, see the Google page on favicons. Every count came from the files and scripts in our research folder.
Frequently Asked Questions About ICO Files
What is an ICO file?
An ICO file is a Windows icon file that stores one or more small images. It starts with a 6 byte header and a list of 16 byte entries, and every entry points to one image. The first bytes are 00 00 01 00. Our 153 test files have 1 to 12 images, stored as BMP data or PNG data.
How do I open an ICO file?
FileInfo lists many image viewers and editors that open ICO files. We tested six other readers on 153 files instead. The file command and our script opened 149, ImageMagick 146 and Pillow 143. We opened no file in a Windows viewer.
What does ICO stand for?
ICO is short for icon. IANA registers the type image/vnd.microsoft.icon for the ending .ico, and Microsoft is the change controller. Wikipedia says Microsoft uses the type image/x-icon on its own pages.
Is an ICO file safe to open?
Reading an ICO file with a reader is safe, because the file is data. We opened no file in a viewer and scanned none for malware. A name proves nothing, because a renamed icon read the same under all 10 names. 8 of our 26 PNG images have a text chunk, so check an icon before you publish it.
What is inside an ICO file?
A 6 byte header, a list of 16 byte entries and the images. Our example, base.ico, is 3,653 bytes long with 4 images, a 16 pixel BMP image and PNG images of 24, 32 and 48 pixels. Every entry has a size, a bit depth, a byte length and an offset.
Can I delete an ICO file?
We did not test deletion, and the sources we read give no deletion steps. Check which program or web page uses the file first, because shortcuts and sites can point to it. Copy the ICO file and write its hash before you delete anything.
How do I make a favicon or an ICO file?
Google lists BMP, GIF, ICO, PNG, JPEG, PPM and TIFF as favicon formats, so an ICO file is not required. The picture must be square and at least 8 by 8 pixels. To make an ICO file, ImageMagick wrote 6 sizes from one PNG in 103,267 bytes, and Pillow wrote them in 18,711.
Why will my ICO file not open?
Eight causes cover what we found. The first four are a damaged header, a cut copy, a file that is not an ICO file and a bad entry list. The last four are damaged image data, a wrong ending, a cursor and a strict reader. Read the first 4 bytes of the ICO file first.
What is the difference between ICO and CUR?
Both use the same layout. An ICO file has a type of 1 and cursors have a type of 2, and cursor entries store a hotspot where ICO entries store planes and bit depth. 7 of our 153 files are cursors, and ffprobe refused all 7.
How can I check if an ICO file is damaged?
Read the first 4 bytes, then the entry list, then draw every image with two readers. Six readers split on 29 of our 50 damaged ICO files. Only 8 copies came back with the same pixels in both Pillow and ImageMagick.
Can I rename a PNG to ICO?
No. A PNG picture with the ending .ico is still a PNG. Our script and icotool refused it, and Pillow and ffprobe opened it as a PNG. Write an ICO file with ImageMagick, Pillow or icotool instead.
What size should an ICO file be?
Google recommends a favicon larger than 48 by 48 pixels, and it must be square. In our files 32 by 32 is the most common size with 59 images, then 16 by 16 with 44 and 48 by 48 with 28. One file can have 12 sizes.
Still Stuck With an ICO File? Seven routes out, depending on what went wrong
Read the first bytes and the entry list of the ICO file. The cause table lists what to try in order.
The convert part shows four writers and the Google notes.
Is it a picture file? The page on BMP files covers the format behind 242 of the 269 images in our ICO files.
Is it a GIF? The page on GIF files covers pictures that start with GIF87a or GIF89a.
Is it a Windows program? The page on EXE files covers programs, which keep their icons as resources.
Is it a file type you do not know? Browse the file extension resource library, or send it on the submit a file type page.
Do you need the format facts? Read the format part for the header, entries and sources of ICO files.