The ICO file format is an image file format for computer icons in Microsoft Windows. An ICO file holds one or more images at multiple sizes and color depths, from which Windows selects and scales the most appropriate one for a given use. A Windows application's own icon — shown on the desktop, in the Start menu, or in File Explorer — is stored in the same format inside its executable as an icon resource, rather than as a separate file.
The CUR file format is an almost identical format for non-animated cursors in Microsoft Windows. The two differ only in the bytes that identify the file and in a hotspot recorded in the CUR header — the pixel offset, in x,y coordinates, from the top-left corner of the cursor image to the point at which the user is actually pointing.
The ANI file format is used for animated Windows cursors. ANI is a RIFF container; each frame within it is a complete CUR-format image and may itself contain images at multiple sizes.
First introduced as monochrome images in Windows 1.0, the format acquired its directory-based multi-image structure in Windows 3.0 and support for larger sizes and higher color depths in Windows 95; Windows Vista added 256×256 images and PNG compression. Each image is stored either as a DIB or as a complete PNG file, and a file typically bundles several so the best match for the requested size and colour depth can be chosen.
Contents
History
Icons introduced in Windows 1.0 were monochrome; in Windows 1.x and 2.x, ICO and CUR files were raw binary images with no directory wrapper — each file contained a single such image, at 64×64 pixels for icons and 32×32 for cursors. The 64×64 icon size was designed for a 1024×1024 target display and was shown downscaled on the lower-resolution monitors of the era. These single-image icons and cursors were created with the SDK's Icon Editor (ICONEDIT), which worked in separate Icon, Cursor and Bitmap modes. In icon and cursor modes it offered four pen "colors" — White, Black, Screen and -Screen — where a Screen pixel took on the color of the screen pixel already beneath it and a -Screen pixel took the opposite (inverted) color, the same transparent-and-invert behavior later carried by the 1-bit AND/XOR mask of the ICONDIR format (see below). The two masks were stored in the opposite order used by that later format, however: the AND mask came first, followed by the XOR mask, and each mask's rows were padded to a 2-byte (word) boundary rather than the 4-byte boundary the ICONDIR format uses. Cursors additionally stored a hotspot, which the Icon Editor placed at the image's center by default if the author did not set one explicitly. Applications loaded icons and cursors only from the resources compiled into an executable module, via the LoadIcon and LoadCursor functions, each taking a module handle and a resource name.
The multi-image ICONDIR format and the DIB-based frame layout were introduced in Windows 3.0, replacing the raw binary format: each file now begins with a directory of fixed-size entries followed by the image data as DIBs, using the 40-byte BITMAPINFOHEADER as the norm. The legacy 12-byte BITMAPCOREHEADER is also accepted; it is the bitmap header of OS/2 Presentation Manager 1.x, whose own icon and pointer resources were likewise built around an AND/XOR-mask-plus-image scheme comparable to the one Windows uses, though held in a different, multi-image-capable container. Shipping 3.x icons used only 1 bpp (monochrome) and 4 bpp (16-color VGA), typically pairing both depths in a single file; 8 bpp was not yet used.
With Windows 95, the icon directory gained the headroom to describe images of any size from 1×1 up to 256×256 pixels (including non-square sizes) — by letting a bWidth or bHeight value of 0 stand for 256 pixels — and added a new 32 bpp colour depth (16.7 million colours, without an alpha channel) on top of the 1, 4 and 8 bpp depths the format already supported; though these were format capabilities rather than depths the shell of the era actually rendered, and the shell could not display very large icons. Shipped system icons of the era remained 16-color (4 bpp) in practice. It was possible to enable 16-bit (65535 color) icons by setting the Shell Icon BPP value in the registry; the high-colour icons feature of Microsoft Plus! for Windows 95 applied this setting. The Shell Icon Size registry value set the size of the large (desktop) shell icons and could be adjusted from 16 to 72 pixels through the Appearance tab of the Display Properties dialog, defaulting to 32 pixels; the small shell icon size was fixed and could not be changed. The notification area of the Windows taskbar was limited to 4 bpp icons until Windows Me when it was updated to support 16-bit icons.
Icon size and color-depth timeline
The standard color depths and pixel sizes shipped in system icons changed over successive releases, as summarized below.
MIME type
While the IANA-registered MIME type for ICO files is image/vnd.microsoft.icon, it was submitted to IANA in 2003 by a third party and is not recognised by Microsoft software, which uses image/x-icon or image/ico instead. Erroneous types image/ico, image/icon, text/ico and application/ico have also been seen in use.
Both ICO and CUR remain partially supported in current web browsers for legacy reasons, although the CUR format's screen pixel inversion feature was never implemented there.
Structure
An ICO or CUR file is made up of an ICONDIR ("Icon directory") structure, containing an ICONDIRENTRY structure for each image in the file, followed by a contiguous block of all image data. Each image is stored either as a raw DIB (see DIB format) or as a complete PNG file (see PNG format). It is customary practice to store the image data in the same order as the entries in the image directory.
All values in ICO/CUR files are represented in little-endian byte order.
DIB format
DIB frames are stored as raw DIB (.bmp) data: a BITMAPINFOHEADER followed by the pixel data and a 1-bit AND mask, without the BITMAPFILEHEADER that precedes DIB data in a standalone .bmp file. Frames should use the standard 40-byte BITMAPINFOHEADER (biSize = 40); the extended BITMAPV4HEADER (108 bytes) and BITMAPV5HEADER (124 bytes) are not accepted.
The height declared in the BITMAPINFOHEADER is twice the height declared in the image directory, because the DIB holds two stacked parts of equal dimensions: the colour image (the XOR mask) above the 1-bit AND mask. Rows in both parts are padded to a multiple of four bytes.
The AND mask is one bit per pixel regardless of the image's colour depth: a 0 bit draws the corresponding image pixel, while a 1 bit leaves the screen unchanged, making the pixel transparent.
The colour image is conventionally stored at 1, 4, 8 or 32 bits per pixel, the depths authoring tools produce; 16- and 24-bit frames are also loaded by Windows, described below.
A 1-bit (monochrome) frame carries a two-entry colour table: index 0 is black (#00000000) and index 1 is white (#00FFFFFF). This format dates to the monochrome displays for which icons and cursors were originally designed, where the result was computed as Output = (Existing AND Mask) XOR Image. The AND and XOR bits combine to give four pixel types:
On colour frames the XOR step draws from the colour bitmap instead of a 1-bit image, so transparency is carried by the AND mask alone.
4- and 8-bit frames are paletted: a colour table of 4-byte BGRA entries (16 and 256 entries respectively) follows the header, and each pixel is an index into it.
16- and 24-bit frames store their pixels directly — 16-bit as a two-byte RGB value, 24-bit as BGR triples — with no colour table and no alpha channel, so transparency comes only from the AND mask. Neither is produced by mainstream authoring tools, and both are rarely encountered. Windows loads both and promotes them to 32 bpp; Microsoft additionally lists 24-bit outside the supported colour formats, recommending conversion to 0RGB 32-bit beforehand.
PNG format
A PNG frame is a complete PNG file embedded verbatim, with no BITMAPINFOHEADER, no doubled height, and no AND mask. Windows recognises it by the PNG file signature at the start of the image data; any other leading bytes are interpreted as a BITMAPINFOHEADER-prefixed DIB frame. The PNG is stored raw rather than wrapped in a DIB with biCompression = BI_PNG, because icon editors of the era crashed on the unrecognised compression value, whereas a raw signature made those parsers fail early and safely.
The image data is conventionally 32-bit RGBA, the format authoring tools produce, although current versions of Windows also load paletted, 24-bit RGB and grayscale PNGs. Dimensions and color depth are taken directly from the PNG data, and Windows derives the AND mask automatically from the alpha channel, so none need be supplied.
A PNG frame can be stored at any size, but compression is conventionally applied only to the 256×256 frame; because PNG frames are unreadable on pre-Vista Windows, keeping the smaller frames as uncompressed DIB preserves down-level compatibility.
In executable files
Icons and cursors in Portable Executable (EXE or DLL) files are organised in resources of type RT_GROUP_ICON (14), RT_GROUP_CURSOR (12), RT_ICON (3) and RT_CURSOR (1).
A RT_GROUP_ICON or RT_GROUP_CURSOR resource has the same shape as the ICONDIR directory of an ICO or CUR file — a header giving the image type and count, followed by one fixed-size entry per image — with the entries differing from the file's ICONDIRENTRY in two ways. Each entry's trailing four-byte dwImageOffset is replaced by a two-byte ordinal that indexes the corresponding RT_ICON or RT_CURSOR resource rather than a file offset, so an entry is 14 bytes rather than 16. In the cursor form, the entry stores its width and height as two WORD values and holds no hotspot data; as described below, the hotspot is instead part of the RT_CURSOR resource itself, in contrast to CUR files, where it is held in the directory entry.
These two structures have no single agreed name. Microsoft's current documentation calls the header NEWHEADER and each entry RESDIR; other sources call them GRPICONDIR and GRPICONDIRENTRY; and the original Windows SDK documentation gave the in-executable entry no distinct name at all, reusing the file-format names ICONDIRENTRY and CURSORDIRENTRY.
RT_ICON and RT_CURSOR resources have the same image data format as in ICO files and can store PNG images as well. The first four bytes of an RT_CURSOR resource contain the cursor hotspot as two WORD values (x, y); the resource entry's dwBytesInRes includes these four bytes, unlike in CUR files, where the hotspot lives in the directory entry and is not counted in dwBytesInRes.
The icon a module presents to Windows File Explorer is the alphabetically first named icon group, or, if none are named, the group with the numerically lowest resource identifier.
Icon library
An icon library is a way to package Windows icons; it is typically a 32-bit Portable Executable binary file having an .ICL extension, with icon resources being the packaged icons. Unlike an ordinary EXE or DLL, an ICL file conventionally contains only icon resources, with no cursors or other resource types. As in an ordinary DLL, each icon in the library is identified by a numeric (0–32767) or named resource identifier together with a language code, and this identifier/language-code pair must be unique within the file. An ICL file may also carry an optional, non-standardized block of user-friendly icon names. A legacy 16-bit New Executable variant of the format dates to Windows 3.11 and is no longer generally supported; Windows Vista and later dropped the ability to display icons from such 16-bit libraries (see History).
Image selection
When Windows loads an ICO or CUR file with multiple images, it scores each candidate entry and picks the one with the lowest score. The target size comes from the system metrics (see below) and the target color depth is that of the primary monitor, since no API supplies an explicit depth. The score combines a size component and a color depth component:
widthScore = |entry width − target width| × (2 if entry is narrower than target, else 1)
heightScore = |entry height − target height| × (2 if entry is shorter than target, else 1)
bppScore = |entry bpp − target bpp| × 2
totalScore = widthScore + heightScore + bppScore
Images smaller than the requested size are penalized with a ×2 multiplier. An entry that scores 0 is an exact match on size and color depth. When two entries have the same score, the one with higher color depth wins. A bWidth or bHeight value of 0 in ICONDIRENTRY is interpreted as 256 for scoring purposes. Because these fields are one byte each, they cannot represent sizes above 256, and the size used for scoring is taken from these directory fields rather than from the embedded image.
For icons, a non-zero bColorCount gives the size of the color palette, and Windows derives the color depth as the number of bits needed to represent that many colors — so 2 colors map to 1 bpp, 4 to 2 bpp, 8 to 3 bpp, and 16 to 4 bpp; if bColorCount is 0, wBitCount is used directly instead. Cursors have no equivalent field to read: in the cursor form of ICONDIRENTRY, bColorCount is unused and wBitCount instead holds the hotspot's vertical coordinate (see above). Through Windows Vista, this meant cursor candidates differing only by color depth could not be distinguished during scoring. From Windows 7 onward, the color depth for cursor scoring is instead read from the cursor's own image data.
Earlier versions of Windows further penalized color compression by doubling the color-depth delta a second time; Windows XP dropped this extra penalty so that a 32-bpp icon can be chosen over an 8-bpp one on a 24-bpp display, which the alpha-blended XP user interface relies on.
Default sizes and DPI scaling
Windows exposes the nominal icon and cursor sizes through the Win32 GetSystemMetrics function. SM_CXICON/SM_CYICON report the default icon size; SM_CXSMICON/SM_CYSMICON report the small icon size. SM_CXCURSOR/SM_CYCURSOR report the nominal cursor size. These values are used as the default target dimensions when loading an image without an explicit size.
On current versions of Windows (Windows 10 and later), higher DPI settings make Windows request larger images. Both icons and cursors are always square. Icon sizes scale linearly with DPI; cursor sizes are rounded to a fixed set of five discrete slots. When no image at the exact target size is available, Windows applies the scoring algorithm above to select the nearest candidate and scales it to the target size.
The SM_CXCURSOR values above assume the default cursor size setting (pointer size = 1 in Windows Settings). The cursor size slider scales all five slots proportionally: at pointer size 2 all values double, at size 3 they triple, and so on. SM_CXICON and SM_CXSMICON are not affected by the cursor size setting.





