ByteScope

ICO file format

Windows icon file, containing one or more small raster images.

MIME type
image/x-icon
Extensions
.ico
Category
Images

Magic-number signature

0x0000000000000100····reserved + type 1 (icon)

About the ICO format

An ICO bundles several sizes of the same icon so the OS can pick the right one; browsers also use it for favicons. The header is a zero reserved word followed by image type 1, then a count, then one sixteen-byte directory entry per image giving that image's size, colour depth, byte length and position in the file. The payloads themselves are not a format of their own: each is either a Windows DIB with its file header removed or, since Windows Vista, a complete PNG embedded whole. So an ICO is a tiny index in front of a pile of other images, and reading one means reading the directory first and then dispatching per entry.

Header layout, byte by byte

OffsetLengthFieldMeaning
02ReservedMust be 00 00. Combined with the type field after it this is the whole of the format's magic number, which is unusually weak — four bytes of which two are zero — so a detector should also sanity-check that the image count is plausible and that the first directory entry points inside the file.
22Resource type01 00 means an icon and 02 00 means a cursor. That single byte is the entire difference between .ico and .cur: the header, the directory and the payloads are otherwise identical, and two fields further down change meaning depending on which it says.
42Image countLittle-endian number of images in the file, and therefore the number of sixteen-byte directory entries that follow immediately. A favicon typically carries two or three sizes; a Windows application icon often carries six or more, from 16 pixels up to 256.
61Width of the first imageA single byte, so the largest value it can express is 255 — and the format handles the 256-pixel icons Windows Vista introduced by defining 0 to mean 256. A reader that takes the byte at face value produces a zero-width image and usually a division by zero.
71Height of the first imageSame encoding and the same 0-means-256 rule. Unlike the DIB header this is the true display height, not the doubled value that the embedded bitmap will claim, so the two disagree by design for every non-PNG entry.
81Palette entry countHow many colours the image uses, or 0 when it is 8 bits per pixel or deeper and therefore has no palette. Modern 32-bit icons always write 0 here.
91ReservedMust be 0. One of the few bytes in the whole file with no interpretation at all, which makes it a reasonable extra check when deciding whether four weak magic bytes really mean an icon.
102Colour planes, or cursor hotspot XIn an icon this should be 0 or 1 and readers accept both — Pillow writes 0, Windows tooling writes 1. In a cursor the same two bytes are the horizontal coordinate of the hotspot, the pixel that counts as the pointer tip.
122Bits per pixel, or cursor hotspot YLittle-endian colour depth: 32 for the alpha-blended icons everything writes today, 8 or 4 for legacy palette icons. In a cursor these two bytes are the vertical hotspot coordinate instead, which is why a .cur renamed to .ico reports absurd colour depths.
144Size of the image dataByte length of this entry's payload, whether that payload is a headerless DIB or a whole PNG. Adding it to the offset in the next field gives the position of the following image, so the directory can be walked and checked against the file size without decoding anything.
184Offset of the image dataWhere this entry's payload starts, counted from the beginning of the file. For the first entry of a two-image icon it is 38: six bytes of header plus two sixteen-byte entries. Everything about an ICO's layout is discovered from these pointers rather than assumed.
2216Second directory entryThe entries are a packed array, so the second one begins at 22, the third at 38, and so on with the same twelve-field layout. Entries are conventionally ordered largest first but nothing enforces it, and neither Windows nor any browser relies on the order.

Telling it apart from its neighbours

Easily confused withHow to tell
PNGA modern ICO usually contains PNG files whole, so a hex dump shows 89 50 4E 47 0D 0A 1A 0A — just not at offset 0. In a two-image favicon it typically appears at offset 38, exactly where the first directory entry's offset field points. Read offset 0 before concluding anything: 00 00 01 00 is an icon that happens to contain PNGs, 89 50 4E 47 is a PNG that someone named .ico.
CURThe byte at offset 2 and nothing else. Type 1 is an icon and type 2 is a cursor, and the consequence is that the two bytes at offset 10 and the two at offset 12 stop being colour planes and bit depth and become the hotspot coordinates. A cursor opened as an icon therefore reports a nonsense colour depth like 12 bits per pixel.
BMPWhere an entry's payload is a bitmap it is not a valid .bmp file: the fourteen-byte BITMAPFILEHEADER is stripped, so the payload begins with the DIB header size — 28 00 00 00 — and the height field inside it is twice the real height, because a one-bit AND transparency mask of the same dimensions follows the colour data. Extracting the payload and renaming it to .bmp gives a double-height image with the mask visible as noise below the picture.
PNG/SVG faviconNot a byte-level test but the practical one people actually need: browsers have accepted a PNG or SVG served at any path via a link rel=icon element for years, and will also accept a PNG served at /favicon.ico despite the extension. What still genuinely requires the ICO container is Windows itself — Explorer, taskbar and .exe resources — and very old browsers that fetch /favicon.ico blindly.

How these files break

  • A directory entry pointing past the end of the file. Because each image is reached independently, the result is partial: the 16-pixel icon renders and the 256-pixel one is blank, or the favicon appears in one browser and not another depending on which size each chose to request. The check is arithmetic — offset plus size must not exceed the file length for every entry.
  • A PNG renamed to favicon.ico. Nothing in the file is damaged, but offset 0 reads 89 50 4E 47 instead of 00 00 01 00. Every current browser accepts it anyway, so the file works on the web and then fails the moment Windows, an installer or an older toolchain tries to read it as an icon resource.
  • The image count out of step with the entries. A tool that removes a size without decrementing the count at offset 4 leaves a reader parsing sixteen bytes of the first payload as a thirteenth directory entry, producing an entry with an insane offset and, in careless software, a crash rather than an error.
  • The 256-pixel size written as 256 rather than 0. It cannot be: the width and height fields are one byte each. Writers that get this wrong truncate to 0 by accident and readers that do not implement the 0-means-256 rule then report a zero-sized image, so the same file is a large icon in Windows and an invalid one elsewhere.
  • A DIB payload whose AND mask is missing or the wrong size. The colour data decodes fine and the transparency is garbage, giving the black or white box around an otherwise correct icon that is instantly familiar from badly converted icon sets.

Where the format stands today

ICO exists today for essentially one reason: browsers still request /favicon.ico from the root of every site whether or not the HTML asks them to, so shipping one remains the cheapest way to keep a stray 404 out of the log and to have something appear in a bookmark list. Beyond that it is a Windows resource format — Explorer icons, shortcut icons, taskbar entries and the icon resources compiled into an .exe or .dll all use the same directory-plus-payloads structure. Modern web practice has moved past it: a single SVG declared with link rel=icon scales to every size a browser wants, and a couple of PNGs cover the platforms that will not take vector, which is why most sites now ship a small two-size .ico purely as a legacy fallback and put their real effort into the PNG and SVG variants. The one thing ICO still does that neither of those can is bundle genuinely different artwork per size, which matters when a 16-pixel icon needs to be a simplified drawing rather than a shrunken one.

Open ICO files on this site

Every one of these runs in your browser — the file never leaves your machine.

Related formats

Formats that are easy to confuse with ICO — compare their leading bytes.

FormatFirst bytesExtension
PNG89 50 4E 47 0D 0A.png
BMP42 4D.bmp

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the ICO format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.