ICC Colour Profile Inspector
Open an .icc or .icm file and read its header, tag table, primaries, white point and tone curves. Everything is decoded in your browser.
How to use
- Drop an .icc or .icm file on the box. Profiles live in /Library/ColorSync/Profiles on macOS, C:\Windows\System32\spool\drivers\color on Windows and /usr/share/color/icc on Linux, and can also be extracted from an image by most photo tools.
- Read the header row first: the device class and colour space tell you what kind of profile it is, and the structure tile says whether the conversion is done by a matrix and three curves or by a lookup table.
- Check the warnings block. It is empty for a well-formed profile; anything in it is a real deviation from the specification, not a stylistic preference.
- Look at the primaries and white point. If the closest standard gamut is named, treat it as a family resemblance — the numbers beside it show how far off it actually is.
- Scan the tag table for what the profile carries: A2B0/B2A0 mean lookup tables, chad means the colorants were adapted to D50, and a tag listed as sharing bytes with another is not a duplicate.
About this tool
ShowHide
An ICC profile is a 128-byte big-endian header, a table of tags, and a pile of binary structures nothing on a normal machine will open. This reads all three. The header gives the version, the device class, the data colour space and the profile connection space, the creation date (six big-endian 16-bit fields, not a Unix time), the rendering intent baked in by whoever made it, the PCS illuminant — which is meant to be D50 and is worth checking when it is not — and the 16-byte profile ID, which is an MD5 of the file with three header fields zeroed. When that ID is present this tool recomputes it and tells you whether it still matches the bytes; when it is all zeros, that means nobody ever computed it, not that the profile is broken. The tag table is listed in file order with each tag’s offset, size, type signature and decoded contents: descriptions in both the v2 textDescription and the v4 multi-localised form, colorants, the chromatic-adaptation matrix, curves, LUTs and dictionaries. Two tags that point at the same bytes — which is how rTRC, gTRC and bTRC almost always share one curve — are reported as sharing rather than printed twice. The part worth having is the derivation. Colorant tags are stored relative to D50, so a profile’s red primary does not look like the red you expect until it is pushed back through the inverse of the chad matrix; that is done here, and the resulting xy chromaticities are compared with sRGB, Adobe RGB, Display P3, Rec.2020 and ProPhoto. The closest one is named as a guess with its distance, never as an identity, because two profiles for the same space differ in the last digits. The white point is shown as XYZ, as xy and as a correlated colour temperature. Tone curves are described as what they actually are: identity, a single gamma, a parametric function with its parameters spelled out, or a sampled table — and where a gamma has to be inferred it is labelled an estimate, because an sRGB curve is a piecewise function and calling it "gamma 2.2" is a lie that has been repeated for thirty years. Structural problems are reported instead of being papered over: a declared size that is not the file length, a tag that runs past the end, a tag that overlaps the header, bytes that belong to no tag, reserved header bytes that are not zero. A file whose bytes 36-39 are not "acsp" is refused by name rather than half-parsed. What it will not do is convert an image, build a profile or judge whether a profile is any good — a calibration can be numerically valid and still describe a display nobody profiled properly.
Frequently asked questions
Why do the red, green and blue values in the tags not match the primaries I expect?
Because the colorant tags are not the device’s primaries. Every XYZ value in a v4 display profile is expressed relative to the D50 illuminant of the profile connection space, even though almost every real display is built around D65. The conversion between the two is stored in the chromatic-adaptation tag, chad, as a 3x3 Bradford matrix. To recover the chromaticities the display actually has, you invert that matrix and apply it to each colorant, which is what this tool does when a chad tag is present. Without one there is nothing to un-adapt with, so the values shown are the stored D50-relative numbers and are labelled as such — for an sRGB profile that is the difference between seeing x = 0.6484 and the 0.6400 you were expecting.
The tool says my sRGB profile is not gamma 2.2. Is it wrong?
No — "gamma 2.2" was never what sRGB specified. The sRGB transfer function is piecewise: a linear segment below 0.04045 and a power function with an exponent of 2.4 applied to a scaled and offset input above it. Written as an ICC parametric curve that is function type 3 with five parameters, and this tool prints all five. The curve happens to sit close to a pure 2.2 gamma across the midtones, which is where the shorthand came from, but it diverges near black, and that is exactly where banding shows up. When a profile stores a sampled table instead, no exact gamma exists at all, so the number shown is an estimate taken at mid-grey and is labelled as one.
What is the difference between a matrix/shaper profile and a LUT profile?
A matrix/shaper profile describes the device with three colorant tags and three tone curves: convert each channel through its curve, multiply by the 3x3 matrix built from the colorants, and you are in the connection space. It is small, fast, invertible and can only describe a device whose behaviour really is that simple — which displays mostly are. A LUT profile instead stores sampled multi-dimensional tables in A2B0/B2A0 and their siblings, one set per rendering intent, and is what printers need because ink on paper is not a linear system. Some profiles carry both; the colour management module then picks by intent, which is why a printer profile can behave differently in perceptual and colorimetric mode.
The profile ID is all zeros. Is the profile damaged?
No. The profile ID field is a 16-byte MD5 of the whole profile with the flags field, the rendering intent field and the ID field itself temporarily set to zero, and the specification never made computing it mandatory. Plenty of profilers leave it blank, so all zeros simply means nobody wrote one. What is worth noticing is the other case: an ID that is present but no longer matches, which means the file was edited after the ID was calculated. This tool recomputes the hash when an ID is stored and says which of the two you have.
Two of my tags have the same offset. Is that a bug in the profile?
It is deliberate and completely legal. The tag table maps signatures to positions, and nothing stops two signatures naming the same position. The common case is rTRC, gTRC and bTRC on a display profile: the three channels share one tone curve, so the writer stores the curve once and points all three entries at it, saving a few hundred bytes. Reporting the bytes three times would suggest three independent curves that could drift apart, which is why they are shown as sharing instead. Editing such a profile by hand is where it bites — changing "one" curve changes all three.
Why does the connection space matter, and why is a device link different?
The profile connection space is the common ground every conversion passes through: source device to PCS, PCS to destination device. The specification allows only XYZ or Lab there, so a profile claiming anything else cannot be composed with another one. The exception is the device link class, which is not a device description at all but a frozen source-to-destination conversion — its "PCS" field holds the output device space, so CMYK or RGB is correct there and this tool does not flag it. Device links are fast and exact for the pair they were built for and useless for anything else, which is why an application that hands you one cannot also tell you what your printer would do with a different paper.
Related tools
Java Class File Inspector
Read a compiled .class file in the browser: class file version and JDK release, access flags, constant pool, fields, methods and referenced classes.
File
WebP File Inspector
Walk a .webp file’s RIFF chunks in your browser: lossy, lossless or extended, canvas versus frame size, animation timing, alpha, ICC, Exif and XMP.
File
GPX Track Inspector (Distance, Elevation, Map)
Drop a .gpx from your GPS watch, Strava, Garmin or Komoot and see distance, elevation gain, moving time and speed, with a map and elevation profile.
File
PSD / PSB Inspector
Read a Photoshop .psd or .psb without Photoshop: canvas, colour mode, every layer with its blend, opacity, mask and group, plus the thumbnail.
File
Python Pickle Inspector
Disassemble a .pkl file in the browser: every opcode, the memo, the value it rebuilds, and whether loading it would run code.
Developer
PE Inspector: Windows EXE and DLL Viewer
Open a Windows .exe, .dll, .sys or .efi in your browser: architecture, subsystem, imports, exports, sections, and whether ASLR, DEP and CFG are on.
File