What this tool does
A placeholder is the cheapest performance work on a page and the most often done wrong. A BlurHash is a published, implementable specification that turns any image into a string of 22 to 44 characters, and that string can be stored in a column, rendered in a canvas before the image arrives, and never fetched. This encodes BlurHash, ThumbHash and a low-quality image placeholder from your own file, and tells you which of the three fits the job.
How it works
BlurHash takes each colour channel into linear light and runs a two-dimensional cosine DCT against a componentX × componentY grid of basis functions. The first coefficient is the DC term, which is simply the average colour of the image and is worth four characters on its own; every other coefficient is an AC term describing a spatial frequency and is worth two. Each is quantised against the maximum value recorded in the header, so the large coefficients get the resolution. The result is packed into a custom base83 alphabet that deliberately contains no slash, no quote and no angle bracket, so it survives being dropped into a URL or an HTML attribute without escaping.
The length is a pure function of the component count, and nothing else. Two characters of header, four for the DC term and two for each remaining coefficient gives 2 + 4 + 2 × (x × y − 1), so 3 × 3 is 22 characters, 4 × 3 is 28, 4 × 4 is 36 and 5 × 4 is 44. A 4000 × 3000 JPEG and a 16 × 16 favicon both produce exactly 22 characters at 3 × 3. That is the entire reason it is worth storing: a short string per image, in a column, forever.
Decode it at 32 pixels wide and let CSS scale it up. A BlurHash holds only componentX × componentY coefficients per channel, so evaluating it at full resolution spends real work describing detail that was never in the string, and looks worse for it. At 32 pixels the reconstruction error is smaller than the eye resolves; at 600 pixels every ringing artefact is visible. There is a punch control that exaggerates the AC terms, which makes a placeholder feel less washed out at the cost of accuracy.
ThumbHash is the 2021 successor and the difference worth knowing is alpha. A BlurHash throws transparency away entirely; a ThumbHash keeps it in one extra byte, which is what lets it stand in for a logo with a soft edge or a cut-out product shot. It is also smaller, typically 17 to 25 bytes against 22 to 44 characters, and it needs no JavaScript to display, because the whole hash is already a valid data URL payload. An LQIP is the third option and the bluntest: a 24px WebP data URI, a few hundred bytes, no decoder at all, and no structure beyond those pixels.
Worked example
A product grid loads 200 catalogue images from a database and each one flashes empty before it arrives.
- Each image is encoded at 3 × 3, which is 2 + 4 + 2 × (9 − 1) = 22 characters
- The DC term alone gives the average colour as a hex value for a background set before any image loads
- The same image at 4 × 3 gives 28 characters and at 5 × 4 gives 44, and the suggestion engine picks from measured detail
- A ThumbHash of a cut-out PNG is 25 bytes because it keeps the alpha channel
- The placeholder is decoded at 32 × 32 and scaled up by CSS
200 rows render a plausible blurred version of each photograph immediately, from 22 bytes per row in the database rather than a few hundred bytes of base64 data URI, and the real image fades in over the top when it arrives.
Accuracy and limitations
- A BlurHash is a deliberately lossy average, not the image and not a security control. At 3 × 3 a detailed photograph is a smudge no decoder can fix.
- A BlurHash has no alpha channel, so transparency is ignored. Use ThumbHash when the shape of the image matters.
- The DCT reads every pixel, so very large images with a high component count do a lot of trigonometry. Downsample first if you care.
Frequently asked questions
- What is a BlurHash and how long is the string?
- A BlurHash is a compact string that reconstructs a blurred version of an image, and its length depends only on the component count: 2 characters of header, 4 for the average colour and 2 per remaining coefficient. So 3 × 3 is 22 characters, 4 × 3 is 28, 4 × 4 is 36 and 5 × 4 is 44, whatever the image size.
- How long should a BlurHash string be?
- For most photographs 3 × 3 at 22 characters is enough, because the eye cannot resolve detail below that anyway. 4 × 3 at 28 characters is worth it for an image with real structure, and 5 × 4 at 44 characters only for genuinely detailed images, and even then it still reads as a smudge.
- What is the difference between BlurHash and an LQIP?
- A BlurHash is a mathematical string of 22 to 44 characters that has to be decoded with a small canvas routine, and it scales to any size. An LQIP is a real 24px WebP image as a data URI, a few hundred bytes, needing no JavaScript at all but carrying no structure beyond those pixels.
- When should I use ThumbHash instead of BlurHash?
- When the image has transparency that matters, such as a logo with a soft edge or a cut-out product shot. A BlurHash has no alpha channel and ignores it entirely, while ThumbHash keeps it in one extra byte and is typically smaller, at 17 to 25 bytes against 22 to 44 characters.
- Where should I store the hash?
- If your images come from a database, store the BlurHash in a column: 22 to 44 bytes, indexed and queryable. If the image is a static import, the opposite is right, because you can inline the LQIP data URI in the HTML and skip the decoder entirely.
- How big should I decode a BlurHash to?
- 32 pixels wide, with CSS scaling the result up. A BlurHash holds only a handful of coefficients per channel, so rendering it at full size spends work describing detail that is not in the string and produces visible ringing.