Image File Size
Image file size is how many bytes the file takes. The browser already knows it for pictures the page loaded via the Resource Timing API, which reports encodedBodySize per resource. For data URIs the size is computed from the encoded payload.
Why it matters
Weight, not pixel dimensions, is what slows a page down. A 4000×3000 pixel image compressed as AVIF might weigh just 80 KB, while a 200×200 PNG icon can be 50 KB if it's poorly optimised. When you're deciding which images to replace, convert, or delete, you need the actual file size in kilobytes.
The good news: the browser already knows this for every image it loaded. The Resource Timing API reports encodedBodySize per resource, which is the exact number of bytes transferred. For data URIs, you can compute the size from the payload itself, no download needed. So you can filter and sort images by weight without making a second network request.
How it works
When a browser loads an image from a URL, it records the transfer in the performance timeline. The PerformanceResourceTiming interface exposes three related sizes:
encodedBodySize: the actual bytes transferred over the network, accounting for compression (gzip, brotli, etc.). This is what you usually want.transferSize: the full size including HTTP headers. Often close toencodedBodySizebut not identical.decodedBodySize: the uncompressed pixel data in memory. Usually much larger than the file on disk.
For a JPEG photograph that's gzipped in transit, encodedBodySize might be 120 KB, but decodedBodySize could be 8 MB in RAM. When filtering for images to optimise, encodedBodySize tells you what actually hit the network.
Cross-origin images present a catch: the browser only reports their size if the server sends a Timing-Allow-Origin header that permits it. Otherwise, encodedBodySize reads as 0. This is a security boundary. The browser won't leak pixel dimensions or file sizes to a script that crossed origin boundaries without explicit permission.
For data URIs, there's no network request and no Resource Timing entry. But you can still compute the size. A data URI like data:image/png;base64,iVBORw0KGgoAAAANS... encodes the whole file as base64. Base64 expands any data by roughly 33%, so a 150-character base64 string represents about 113 bytes of actual image data. The formula: (base64String.length * 3) / 4 (minus any padding), then convert to kilobytes.
What does not matter
Don't confuse file size with image dimensions. A 2000×1500 photo can weigh 40 KB if it's modern WebP at high compression, or 800 KB if it's an old, poorly optimised JPEG. Dimensions alone won't tell you which images are expensive.
Don't worry about EXIF data or metadata in the file size. The encodedBodySize is the on-the-wire transfer size, which usually excludes EXIF unless the server is serving it stripped. (If you're downloading to your device, your browser doesn't extract or remove EXIF data. That's your responsibility.)
The transferSize field can be smaller than encodedBodySize if the resource came from the browser's memory cache (sometimes it reports 0). For filtering purposes, use encodedBodySize to be safe.
Code example
// Get all images and their sizes from Resource Timing
performance.getEntriesByType('resource').forEach(entry => {
if (entry.initiatorType === 'img' || entry.name.match(/\.(jpg|png|webp|avif|gif)$/i)) {
const sizeInKB = (entry.encodedBodySize / 1024).toFixed(2);
console.log(`${entry.name}: ${sizeInKB} KB`);
}
});
// Compute size of a data URI (base64 only)
function getDataURISize(dataURI) {
const base64Part = dataURI.split(',')[1];
if (!base64Part) return 0;
const decoded = (base64Part.length * 3) / 4;
return (decoded / 1024).toFixed(2); // KB
}
const dataURISize = getDataURISize('data:image/png;base64,iVBORw0KG...');
console.log(`Data URI size: ${dataURISize} KB`);
How Scalpel shows it
The weight filter in the Scalpel Images popup lets you set minimum and maximum kilobytes, so you can instantly find all images above a certain threshold, say, anything over 500 KB. Each image tile displays a KB badge showing its exact transferred size. Filter by weight, then convert the heavy ones or delete them outright. The scan reads encodedBodySize from Resource Timing, so it's accurate and runs with no extra download.