Image Compressor topic guide
PPI vs DPI vs pixels: what actually matters on screen
Direct answer
On the web, pixel dimensions are the only number that controls how sharp an image looks on a given display. PPI (pixels per inch) is a property of a screen, not of an image - a 5K iMac and a 1080p monitor both display a 1920 by 1080 image at their own PPI. DPI (dots per inch) is a property of a printer, and the DPI value saved inside a PNG or JPEG is a hint to the printer about how to scale the pixels to physical inches - browsers do not read it. The number that actually matters on screen is the pixel count of the file, matched to the device pixel ratio (1x, 2x retina, 3x) of the display it is shown on.
What this workflow handles
The three terms are often used as if they were interchangeable, so it helps to keep them separate. A pixel is the smallest dot a screen can address; the only number that controls sharpness on a given display is how many pixels the file contains. PPI is a property of the display - a 27 inch 5K monitor and a 6 inch phone screen have very different PPI values, but both render a 1920 by 1080 image in the same number of addressable pixels. DPI is a property of a printer, and the value stored in a PNG or JPEG is metadata that tells the print pipeline how to scale pixels to physical inches. Pillow's Image.save() takes a dpi parameter for this exact purpose: the value is written into the JFIF marker (JPEG) or a pHYs chunk (PNG) and the bytes of the image itself are unchanged. Modern browsers do not consult the DPI field, so two PNGs with identical pixel dimensions and different DPI values display identically. For the web, the right pattern is to resize to the actual rendered display size, double it for the 2x retina slot, re-encode at a balanced quality, and serve the result with srcset or a <picture> element so each browser picks the size that matches its device pixel ratio. The W3C CSS Values 4 specification defines the resolution unit (dpi, dppx, x) the browser uses for that match, MDN's CSS resolution reference explains the mapping, the WHATWG HTML Living Standard describes how width and height attributes interact with device pixel ratio, web.dev's responsive images guide is the canonical implementation pattern, and Chrome for Developers' Properly size images Lighthouse audit is the first-party reference for what counts as a wasted pixel.
Use the image compressor to re-encode a single image in its original format at the same pixel dimensions, then compare the byte counts in the result panel before keeping the output.
How to use it
- Decide where the image will be displayed - a web page, an app screen, a print piece, or a marketplace listing - so you know which number actually controls the result.
- For a web page, find the actual rendered display size in CSS pixels at the largest viewport, then double it for the 2x retina slot (multiply by 3 if the audience includes 3x phones or VR headsets).
- Resize the source to that pixel dimension with a resizer or the Image Compressor. The file's pixel count is what controls sharpness on a given display, not the DPI value in its metadata.
- Re-encode the resized file at a balanced quality with the WebP Converter or Image Compressor. The DPI value in the file header does not change the bytes or the display.
- Reference the file from a srcset or <picture> element so each browser picks the size that matches its device pixel ratio (1x, 2x, 3x) without shipping the largest variant to every visitor.
- Open the actual output in a real browser at 1x and 2x display densities to confirm the image is sharp at both, then keep both variants and serve them through the markup.
Common mistakes
- Saving at 300 DPI without increasing the pixel count. The DPI value is metadata - the browser never reads it. A 1920 by 1080 PNG saved at 300 DPI is the same number of addressable pixels as the same PNG at 72 DPI, so the on-screen appearance is identical. Pillow's Image.save() documents the dpi parameter as a print hint, not a control over screen sharpness. To make an image sharper on screen, increase the pixel count of the file (resize up to a larger canvas) or serve a 2x variant via srcset - do not raise the DPI value in metadata.
- Uploading a 4K image and letting CSS scale it down. The browser still downloads all 3840 by 2160 pixels and discards most of them at paint time. CSS width and height set the display size, not the bytes shipped. Chrome for Developers' Properly size images Lighthouse audit flags exactly this case - images whose intrinsic pixel dimensions are far larger than the rendered display size. Resize to the display slot (plus the 2x retina slot) before encoding, then serve with srcset so each browser picks the right size for its own device pixel ratio.
- Ignoring device pixel ratio (1x, 2x, 3x) on retina and HiDPI displays. A 400 by 300 image looks sharp on a 1x display and visibly soft on a 2x retina display because the same number of pixels is being stretched across four times the screen area. The WHATWG HTML Living Standard and the W3C CSS Values 4 spec describe how the browser maps CSS pixels to device pixels, and web.dev's responsive images guide is the canonical implementation pattern: ship a 1x and a 2x variant and let srcset pick, or use a single 3x file that downsamples to 1x and 2x automatically.
- Resizing up (upscaling) a small image to a larger canvas to fake higher resolution. The new pixels are invented rather than measured, so the result is softer than the source rather than sharper. Resizing down (a 4000 by 3000 source to a 1200 by 900 display slot) is the operation that removes pixels the display will never use; resizing up is the operation that softens detail. If the source is smaller than the display needs, the right fix is to find a sharper source, not to upscale - and Pillow's resize filters can only interpolate, not invent real detail.
Frequently asked questions
Should I save images at 300 DPI for the web?
No - DPI is metadata the browser ignores. Saving a 1920 by 1080 PNG with dpi=(300,300) produces the same number of addressable pixels as the same PNG with dpi=(72,72); the on-screen appearance is identical. Pillow's Image.save() documents the dpi parameter as a hint to print software, not a control over screen sharpness. For the web, the only number that controls sharpness is the pixel count of the file. To get a sharper image on a 2x retina display, double the pixel dimensions and serve the larger file via srcset - do not raise the DPI.
What is the difference between PPI and DPI?
PPI (pixels per inch) describes a screen - the number of addressable pixels packed into one physical inch of the display. DPI (dots per inch) describes a printer - the number of ink dots the device lays down per physical inch of paper. The two units are not interchangeable. W3C CSS Values 4 defines the resolution data type with separate unit identifiers (dpi, dpcm, dppx, x) so the spec can refer to each without ambiguity, and MDN's CSS resolution reference lists the same four units.
What DPI should I use for the web?
Any value. Because browsers do not read the DPI field, the saved value has no effect on how the image displays in Chrome, Firefox, Edge or Safari. A web image can ship with the default 72 DPI, an explicit 96 DPI, an inherited 300 DPI from a camera export, or no DPI at all - the on-screen result is the same. The number that actually matters is the pixel count of the file, matched to the device pixel ratio of the display it is shown on.
Why does my image look blurry on a retina display?
Because the file does not have enough pixels for the display's device pixel ratio. A 400 by 300 image shown in a 400 by 300 CSS pixel slot looks sharp on a 1x display (one file pixel per one screen pixel) and visibly soft on a 2x retina display (one file pixel stretched across four physical pixels). The fix is to ship a second, larger file - a 800 by 600 version in the same example - and let the browser pick it via srcset, not to change the DPI value. web.dev's responsive images guide is the canonical reference for the srcset + sizes pattern.
Does the DPI value in image metadata affect file size?
Negligibly. The DPI value is stored in a small metadata field (the JFIF marker for JPEG, the pHYs chunk for PNG), so changing it from 72 to 300 adds a handful of bytes to the file. The pixel data, which is the bulk of the file, is unchanged. The Pillow Image.save() reference documents the dpi parameter as metadata, and saving at dpi=(300,300) versus dpi=(72,72) produces files that differ in size by less than 1 percent on a typical photo.
What is device pixel ratio (DPR)?
Device pixel ratio is the multiplier a browser uses to map CSS pixels to physical screen pixels. A standard 1x display has a DPR of 1 (one CSS pixel = one physical pixel); a Retina display has a DPR of 2 (one CSS pixel = four physical pixels); some high-density phones and VR headsets report a DPR of 3. The W3C CSS Values 4 spec defines the resolution unit x and the dppx unit, MDN's CSS resolution reference documents how the browser exposes the ratio, and the WHATWG HTML Living Standard describes how the browser combines the CSS size with the device pixel ratio when laying out an <img> element.
How do I serve a sharp image on a 2x retina display?
Ship a 2x file and let the browser pick it with srcset. For an image that will render in a 400 by 300 CSS pixel slot, prepare an 800 by 600 file as the 2x version and reference both with the srcset attribute: <img src="photo-1x.jpg" srcset="photo-1x.jpg 1x, photo-2x.jpg 2x" alt="...">. A 2x display picks the larger file, a 1x display picks the smaller one. The same pattern works for 3x displays. web.dev's responsive images guide is the canonical reference, and Chrome for Developers' Properly size images Lighthouse audit flags images that are missing the larger variant.
Does Pillow's dpi parameter make the image sharper?
No - it only writes a metadata value. Pillow's Image.save() takes dpi as a (x, y) tuple and stores it in the file header so a downstream print pipeline can use it, but the pixel data of the image is not changed. The Pillow documentation lists dpi under format-specific options for PNG, JPEG and other formats and describes it as a metadata field. To make the image sharper on screen, increase the pixel count of the file (resize up) or generate a larger 2x version; do not raise the dpi value.
Sources
- W3C CSS Values and Units Module Level 4 - resolution: https://www.w3.org/TR/css-values-4/#resolution — Canonical W3C definition of the resolution data type and its unit identifiers (dpi, dpcm, dppx, x) - the units the browser uses to map CSS pixels to device pixels.
- MDN - CSS resolution: https://developer.mozilla.org/en-US/docs/Web/CSS/resolution — MDN reference for the resolution type, the device pixel ratio (DPR) concept, and the supported units (dpi, dppx, x).
- MDN - Image file type and format guide: https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Image_types — MDN reference for the pixel-based raster formats the open web uses (JPEG, PNG, WebP, AVIF) and their encoder behaviour - the formats the on-screen sharpness question is actually about.
- web.dev - Responsive images: https://web.dev/articles/responsive-images — web.dev's canonical guide to srcset, sizes, <picture>, and the 1x / 2x / 3x device pixel ratio pattern that serves a sharp image to every display density without oversizing.
- web.dev - Serve responsive images: https://web.dev/articles/serve-responsive-images — Companion web.dev guide that pairs the srcset / sizes pattern with the actual display size decision and the 2x retina consideration.
- WHATWG HTML Living Standard - Images: https://html.spec.whatwg.org/multipage/images.html — Authoring spec for the <img> element, the srcset and sizes attributes, the <picture> element, and how the browser combines CSS size with device pixel ratio when laying out an image.
- Chrome for Developers - Properly size images (Lighthouse): https://developer.chrome.com/docs/lighthouse/performance/uses-responsive-images — First-party Lighthouse audit reference for intrinsic-versus-rendered dimension mismatch and the byte waste it produces - the second Lighthouse audit that runs on every PageSpeed Insights report.
- Pillow (PIL) documentation - Image.save PNG: https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#png — Pillow's reference for the PNG encoder options, including the dpi parameter (a metadata field stored in the pHYs chunk, not a control over screen pixels) and the optimize flag that actually reduces file size.
- Pillow (PIL) documentation - Image.save JPEG: https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#jpeg — Pillow's reference for the JPEG encoder options, including the dpi parameter (stored in the JFIF marker) and the quality and optimize knobs that do affect screen appearance.
Explore the image compressor topic cluster
Each guide answers a different image-decision question. Pick the one that matches your situation, then use the linked tool to produce the output you need.
Related guides
-
Image file size vs dimensions: why pixels do not equal bytes
A 500 by 500 image can be larger in bytes than a 2000 by 2000 image. File size depends on pixel dimensions, compression format, quality setting, colour depth and image complexity — not dimensions alone. A practical explanation with sources from MDN, web.dev and Pillow.
-
Resize vs Compress: which one actually shrinks your image
Resizing changes the pixel dimensions of an image; compression keeps the dimensions and re-encodes the file at a smaller byte count. Pick resize when the source is larger than the display size, and compression when the dimensions are right but the bytes are still too high. Backed by Chrome for Developers' two Lighthouse audits and the Pillow documentation.
-
Responsive images: serve the right size for every device
Responsive images let one HTML element serve different pixel-sized files to different devices, so a phone does not download a 2000-pixel-wide desktop photo. The pattern uses the srcset and sizes attributes on <img>, or the <picture> element with multiple <source> children. Backed by MDN, web.dev and the WHATWG HTML Living Standard.
-
How to optimize images for the web
Optimizing an image for the web is a four-step decision chain: pick the format that matches the content, resize to the actual display size, re-encode at a balanced quality, and serve the result with a modern-format fallback. A practical guide backed by web.dev, MDN, Chrome for Developers Lighthouse audits, and the Pillow documentation.
-
JPEG vs PNG vs WebP: how to choose the right image format
JPEG, PNG and WebP are not interchangeable. The right choice depends on what is in the image, whether it needs transparency, the file-size budget, and where the image will be displayed. A practical decision guide backed by MDN, Google Developers, web.dev, the WHATWG HTML Living Standard and the Pillow documentation.
-
Why is my image still large after compression
Your image may still be large after compression because the source was already optimized, the format is inefficient for the content type, the dimensions are too large for the destination, or the quality setting is too high. A troubleshooting guide with actionable checks from MDN, web.dev and Chrome for Developers.
All image compressor guides
- Resize vs Compress: which one actually shrinks your image
- JPEG vs PNG: which format should you actually use
- Transparent image format: PNG vs WebP vs AVIF for alpha
- Image file size vs dimensions: why pixels do not equal bytes
- Why is my image still large after compression
- How to tell if an image is over-compressed
- How to optimize images for the web
- Responsive images: serve the right size for every device
- Crop vs resize: how to fit an image into a target shape
- JPEG vs PNG vs WebP: how to choose the right image format
- Image alt text and SEO: how to write alt text Google Images can use
- Why does my image look blurry on my website