Why You Need to Know What's Inside an Image#

Your operating system tells you three things about an image file: name, dimensions, and creation date. That's the surface layer. What you don't see is how the image was encoded, which chroma subsampling it uses, whether an ICC color profile is embedded, whether there's a hidden thumbnail, and what compression parameters were applied.

These details directly inform every optimization decision you make. A JPEG saved at quality 95 can be re-encoded with sensible lossy settings and shrink by 60–70% with no visible difference. The same JPEG already saved at quality 55 will only degrade further if you compress it again — you'd need to go back to the source. Without knowing which case you're in, you're working blind.

Here's the toolchain at a glance:

Image inspection toolchain comparison
Image inspection toolchain comparison

Browser Developer Tools#

The Network Panel#

Open DevTools, switch to the Network tab, filter by Img, and reload the page. For every image, you immediately see:

  • Transfer size (the Size column). This is what actually traveled over the wire — gzip or brotli compression applied by the CDN is already factored in. The decoded pixel size in memory is a different number, typically 3–4x larger for photos.
  • Request priority (the Priority column). If your cover image shows "Low" here, you forgot fetchpriority="high" and it's queuing behind less important resources.
  • Content-Type response header. Confirms your CDN is returning image/avif and not silently falling back to JPEG.
  • Content-Encoding. If the CDN is applying an additional compression layer on top of the image format itself.
  • Waterfall timing. Shows DNS lookup, connection negotiation, TTFB, and download duration for each image. A resource taking 800ms to start downloading has a server-side or redirect problem, not an image size problem.

Lighthouse Image Audits#

Run Lighthouse and check the Opportunities section. It flags three specific image problems:

  • Properly size images — images whose intrinsic resolution far exceeds the rendered size. A 2400px image in a 400px container wastes roughly 35x the necessary pixels.
  • Serve images in next-gen formats — JPEGs and PNGs that could be AVIF or WebP. The estimated savings are usually accurate to within 10–15%.
  • Efficiently encode images — images whose compression parameters could be tightened without visible quality loss. This is the one that catches JPEGs saved at unnecessarily high quality settings.

Right-Click Inspection#

In the Elements panel, right-click any <img> and open it in a new tab. The URL bar will reveal the exact image URL with any CDN transformation parameters. This is the fastest way to confirm whether your CDN's image resizing and format conversion are actually firing.

Command-Line Tools#

ExifTool — The Universal Metadata Reader#

ExifTool is the closest thing to a universal decoder for image file internals. It reads EXIF, IPTC, XMP, ICC profiles, and format-specific encoding parameters across essentially every image format in existence.
bash
1# macOS
2brew install exiftool
3 
4# Full metadata dump
5exiftool photo.jpg
6 
7# Targeted fields
8exiftool -ImageSize -FileSize -Quality -Compression \
9 -ColorSpace -BitDepth -EncodingProcess photo.jpg
10 
11# JSON output for scripting
12exiftool -j photo.jpg
13 
14# Recursive directory scan
15exiftool -r -ImageSize -FileSize -MIMEType ./images/

The fields that matter for optimization decisions:

FieldWhat It Tells YouWhy It Matters
ImageWidth / ImageHeightPixel dimensionsIs this image oversized for its display context?
FileSizeBytes on diskThe bluntest and most useful metric
MIMETypeActual file formatA .jpg extension doesn't guarantee JPEG encoding
EncodingProcessBaseline vs. Progressive JPEGProgressive loads as a full-image preview; baseline renders top-to-bottom
YCbCrSubSamplingChroma subsampling mode4:2:0 halves color data vs. 4:4:4 which preserves every pixel's color
QualityEstimated JPEG qualityAn approximation, not always reliable — depends on the encoder
ColorSpacesRGB, Display P3, Adobe RGBAffects how colors render on different displays
BitsPerSampleBit depth8-bit is standard; 16-bit means the source had more data to work with

ImageMagick identify#

bash
1# Compact summary
2identify -verbose photo.jpg
3 
4# Just the useful bits
5identify -format "%wx%h %b %m Q=%[quality] %[colorspace]" photo.jpg
6# → 1920x1280 245KB JPEG Q=92 sRGB

FFprobe (If You Already Have FFmpeg)#

bash
1ffprobe -v quiet -print_format json -show_format -show_streams photo.jpg

Sharp Metadata (Node.js)#

js
1const sharp = require('sharp');
2 
3async function inspectImage(path) {
4 const metadata = await sharp(path).metadata();
5 
6 console.log({
7 format: metadata.format, // 'jpeg', 'png', 'webp', 'avif'
8 width: metadata.width,
9 height: metadata.height,
10 space: metadata.space, // 'srgb', 'rgb16'
11 channels: metadata.channels, // 3 = RGB, 4 = RGBA
12 depth: metadata.depth, // 8, 16
13 density: metadata.density, // DPI
14 hasProfile: metadata.hasProfile, // ICC profile embedded?
15 hasAlpha: metadata.hasAlpha,
16 isProgressive: metadata.isProgressive,
17 pages: metadata.pages, // frame count for GIF/PDF
18 });
19}

Online Tools#

For quick checks when you're not at your dev machine:

  • EXIF.tools processes everything locally via WebAssembly. The file never leaves your machine — important for sensitive or pre-release images.
  • Squoosh (from Google) gives you side-by-side before/after comparisons across multiple encoders. The quality slider is interactive, so you can visually find the inflection point for a specific image.
  • PageSpeed Insights / WebPageTest audit images at the page level. They'll tell you which specific images on a URL need attention, not just generic advice.

The Decision Flow#

Knowing which tool to reach for depends on what question you're asking:

Image inspection decision flow
Image inspection decision flow

Understanding Chroma Subsampling Notation#

ExifTool's output may show YCbCrSubSampling as YCbCr4:2:0, YCbCr4:2:2, or YCbCr4:4:4. The notation describes how many chrominance (color) samples are stored relative to luminance (brightness) samples:
text
14:4:4 — No subsampling. Every pixel keeps its own color data. Largest files.
24:2:2 — Horizontal pairs of pixels share one set of chroma values. Moderate savings.
34:2:0 — 2×2 pixel blocks share one set of chroma values. Maximum savings.

For photographs, 4:2:0 is almost always fine — the eye resolves luminance detail far better than color detail, and the visual difference is essentially zero for natural imagery. For screenshots and images containing text, however, 4:2:0 produces visible color fringing at edges. Those should use 4:4:4, or better yet, a format that doesn't do chroma subsampling at all (PNG or lossless WebP).

Detecting Prior Compression#

JPEG compression leaves fingerprints in the quantization tables — the matrices that determine how aggressively each frequency coefficient gets rounded. You can extract them:

bash
1exiftool -JPEGQTables photo.jpg

When an image has been compressed multiple times with different quality settings, the quantization tables take on a characteristic "flattened" pattern. The coefficients no longer follow the smooth distribution of a single-pass encode. This is a clear signal: the image has already been through the wringer. Further lossy compression will stack artifacts on top of artifacts. If you see this, find the original source file.

A Practical Inspection Routine#

bash
1# 1. Quick overview — immediately tells you if there's a size problem
2exiftool -ImageSize -FileSize -MIMEType photo.jpg
3 
4# 2. If file is suspiciously large for its dimensions, check encoding
5exiftool -EncodingProcess -YCbCrSubSampling -Quality photo.jpg
6 
7# 3. If colors look wrong, check color space
8exiftool -ColorSpace -ProfileDescription photo.jpg
9 
10# 4. Dump everything to JSON for programmatic processing
11exiftool -j -G -t photo.jpg > info.json

The rule is simple: inspect before you act. Every image tells you what it is, if you know where to look.