How to Optimize Images to Improve Website Performance
Reduce image bytes without sacrificing visual quality. Learn how to choose formats, compress assets, serve responsive sizes, and diagnose image-related LCP delays.
To optimize images for website performance, first identify which images users actually see and how large they render. Remove unnecessary images, resize assets to fit their display dimensions, choose a format and compression level that preserve acceptable quality, and serve responsive candidates so each device downloads a suitable file. Lazy-load images below the fold, but keep the likely largest contentful paint (LCP) image discoverable early. Measure the page before and after each change: smaller files help only when image transfer is a meaningful part of the delay.
This guide covers a practical workflow for HTML sites, the browser markup to use, how to diagnose LCP, common failure cases, and when an image CDN may help.
1. Find the images that matter
Start with the rendered page, not the source directory. Inspect the hero, product imagery, article images, logos, and other prominent content at the viewport sizes your visitors use. Record each image’s intrinsic dimensions, rendered dimensions, file size, and role. A large source image scaled down with CSS still transfers its full bytes.
- Remove first: If an image adds no useful information, removing it is the most direct way to avoid its transfer and rendering work.
- Resize to use: Generate assets near the widths at which they are displayed. Include larger candidates for high-density screens where needed, without sending the original full-resolution asset to every device.
- Reserve layout space: Set intrinsic
widthandheightattributes so the browser can account for the image’s aspect ratio before it loads. - Identify the LCP image: Use PageSpeed Insights, browser developer tools, or a performance trace to find the largest contentful element in the initial viewport.
Google’s web.dev guidance notes that serving desktop-sized images to mobile devices can use 2–4 times more data than needed in some cases. Responsive candidates let the browser choose a more appropriate resource for the layout and device; the actual savings depend on your images and visitors.
2. Choose a format for the content
There is no format that wins for every image. Compare the output at the actual rendered size and quality you need. Conversion can make an already optimized file larger, so keep the original when a new format does not improve the result.
| Image content or need | Formats to evaluate | Check before shipping |
|---|---|---|
| Photographs and detailed raster imagery | JPEG, lossy WebP, lossy AVIF | Compare file size and visible detail at the rendered size. Confirm browser support for your audience, especially if choosing AVIF. |
| Logos, diagrams, charts, and clean line art | SVG | Check that the artwork is suitable for vector representation and renders as intended at the sizes used. |
| Transparency, pixel accuracy, or crisp edges | PNG or another suitable lossless format | Lossy artifacts can be obvious around text, flat colors, and high-contrast boundaries. |
| Longer animation with playback needs | Video may be more suitable | Consider whether video playback and controls fit the content and user experience. |
WebP is broadly supported across modern browsers. AVIF support is reasonably decent but less broad, so assess your audience and provide a fallback when needed. Use <picture> when you want format selection or art direction; ordinary responsive width candidates can use srcset and sizes.
3. Compress, then inspect the result
Lossy compression reduces file size by discarding image information. It often works well for photographs, but can introduce artifacts near sharp edges, flat colors, or text. Lossless compression preserves image data while reducing encoding overhead, and is a better fit when fidelity matters.
- Choose representative assets: include photos, images with text, transparent artwork, and high-contrast graphics.
- Generate candidate outputs in the formats you are considering.
- Compare bytes and inspect each result at its actual rendered size and at a closer zoom.
- Check gradients, fine detail, text edges, transparency, and color boundaries.
- Adopt settings only when the visual difference is acceptable for that image type.
Google web.dev recommends experimenting with compression levels to find a compromise between quality and file size. Squoosh and ImageOptim are examples named in its guidance; neither a specific tool nor a single setting is right for every asset.
4. Serve responsive image candidates
Use srcset with width descriptors and a truthful sizes value to let the browser select among image widths. The example below assumes the image fills the viewport on narrow screens and occupies up to half the viewport on wider screens. Adjust the candidates and sizes to match your actual layout.
<img
src="/images/product-960.jpg"
srcset="
/images/product-480.jpg 480w,
/images/product-960.jpg 960w,
/images/product-1440.jpg 1440w
"
sizes="(max-width: 700px) 100vw, 50vw"
width="960"
height="640"
alt="A person using the product"
>
The browser uses the candidate widths together with the rendered slot described by sizes and the device’s pixel density to choose a resource. If sizes claims the image is smaller than it really renders, the browser may choose an image that looks soft. If it overstates the slot, it can download more pixels than needed.
Use <picture> for alternate formats or art direction. In this example, browsers that support AVIF can select it, while others can use WebP or the JPEG fallback:
<picture>
<source
type="image/avif"
srcset="/images/hero-800.avif 800w, /images/hero-1440.avif 1440w"
sizes="100vw"
>
<source
type="image/webp"
srcset="/images/hero-800.webp 800w, /images/hero-1440.webp 1440w"
sizes="100vw"
>
<img
src="/images/hero-1440.jpg"
srcset="/images/hero-800.jpg 800w, /images/hero-1440.jpg 1440w"
sizes="100vw"
width="1440"
height="900"
alt="A landscape at sunrise"
>
</picture>
For art direction, provide a source with a different crop at a breakpoint, then retain an <img> fallback. Keep the width and height attributes consistent with the fallback image’s intrinsic aspect ratio, and use CSS as needed to control the displayed crop.
5. Load images according to their role
Images below the fold are good candidates for native lazy loading. Do not add loading="lazy" to an above-the-fold hero image likely to be the LCP element: delaying its request can make the main content appear later.
<!-- Below-the-fold content image -->
<img
src="/images/article-detail.webp"
width="1200"
height="800"
loading="lazy"
alt="A close-up of the finished detail"
>
For an important image, first verify that the browser discovers it early. If it is discovered late or fetches at low priority, test an appropriate fetch priority or preload hint. Do not prioritize every image: high-priority work competes with scripts, fonts, and other resources.
When markup already exposes the LCP image early, the browser can often discover it without a preload. Add preload only when measurements show that it helps resource discovery, and ensure the preload matches the actual responsive image selection so it does not trigger an unnecessary duplicate download.
6. Diagnose LCP before choosing a fix
Largest Contentful Paint measures when the largest image or text block in the viewport is rendered. Google web.dev’s guidance, updated March 31, 2025, says a good LCP is 2.5 seconds or less for at least 75% of page visits. Treat this as a user-experience target, not a promise that optimizing images alone will meet it.
Inspect the LCP element and divide the time into the parts that matter: when the browser discovers the resource, connection and request time, resource load duration, and render delay. If image transfer dominates, resize or compress it and serve a responsive candidate. If discovery is late, expose the image earlier in the document or investigate the delivery path. If render delay dominates, image compression alone may not fix the page.
- Run PageSpeed Insights or record a browser performance trace for the page.
- Identify the LCP element and its resource URL.
- Check whether it is an image, whether it is lazy-loaded, and when its request starts.
- Compare its transferred bytes and request duration with the overall LCP timeline.
- Change one relevant factor, then measure again under comparable conditions.
Field results vary with device, network, cache state, and page content. Use repeat measurements and real-user data when available; a single local run is not a reliable universal benchmark.
7. Decide whether an image CDN fits
An image CDN can transform and deliver variants by dimensions, pixel density, format, and compression. It can reduce the work of generating and maintaining variants manually. Compare it with a build-time image pipeline using these factors:
- Does it support the transformations and output formats your images need?
- What are the current costs, limits, and support terms for your expected usage?
- How much setup, documentation review, and migration work will it take?
- Will another origin add connection setup or delay discovery of the LCP image?
- Can your cache strategy reuse generated variants effectively?
No provider is universally best. Verify current capabilities and pricing directly before choosing one. A build-time pipeline may be simpler when the image set changes infrequently; a CDN may suit sites that need many on-demand variants. Measure the resulting page, including connection and discovery effects.
8. Troubleshooting common image performance problems
| Symptom | Likely cause | What to change |
|---|---|---|
| A small image looks blurry on a high-density screen | Only a low-resolution candidate is available, or sizes understates the rendered slot. |
Add a suitable larger candidate and correct the sizes expression for the actual layout. |
| Mobile still downloads a large image | The markup has no responsive candidates, or its sizes value describes a larger slot than the image uses. |
Generate width candidates and use srcset plus an accurate sizes value. Confirm the selected URL in browser developer tools. |
| The hero image appears late | It may be lazy-loaded, discovered late through CSS or script, or delayed by delivery. | Remove lazy loading if it is the above-the-fold LCP image; inspect discovery and request timing before adding priority or preload hints. |
| Compression creates halos, smearing, or rough text edges | Lossy compression is too aggressive or unsuitable for the image. | Raise quality, use lossless output, or choose another format. Inspect at actual display size. |
| A converted image is larger than the source | The source was already well optimized, or the new format/settings do not suit its content. | Keep the smaller source or compare different settings. Conversion is not automatically an optimization. |
| LCP stays high after reducing image bytes | Resource discovery or render delay may dominate, or another element is the LCP. | Inspect the LCP element and its full timeline. Fix the measured bottleneck rather than continuing to compress unrelated images. |
| The page shifts while images load | The browser does not know the image’s dimensions before it arrives. | Set intrinsic width and height attributes or reserve the correct aspect ratio in CSS. |
| An alternate format is missing or fails on some browsers | The format is unsupported for that visitor, or the <picture> fallback is missing or incorrect. |
Provide a supported fallback in an <img> element and check source order, MIME types, and generated URLs. |
9. Keep the optimization reliable and cost-aware
Image optimization has a recurring cost in build time, storage, bandwidth, and maintenance. Generate only the variants your layouts need; an excessive candidate set can add storage and operational work without improving selection. Preserve originals when they are useful for future processing, and avoid blindly recompressing an already optimized asset.
After deployment, check representative viewport sizes and browser support, confirm that image URLs resolve, and inspect layout stability. Compare performance measurements under similar conditions. When using a CDN, account for transformation and delivery pricing, cache behavior, and the extra origin connection. When using build-time processing, account for the pipeline’s processing time and the effort of regenerating images after source changes.
Or skip the browser setup
If you need a screenshot of a page to inspect its visible image layout, ScreenshotNeo is a website screenshot API and MCP server. It returns a PNG, JPEG, WebP, or PDF from one GET request. It captures what the page renders; it does not replace image profiling or LCP measurement.
Use this cURL request to capture a page:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Equivalent Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Equivalent Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server gives AI agents such as Claude, Cursor, and other MCP clients the tools take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.
FAQ
Should every image be converted to WebP or AVIF?
No. Compare formats for each kind of image and retain the source when conversion makes the file larger or the quality worse. Provide a fallback where browser support requires one.
Does compressing an image always improve LCP?
No. It helps when image transfer is a meaningful part of the LCP path. Late discovery or render delay can remain the main cause.
Can I lazy-load all images?
No. Lazy loading is for images that are initially below the fold. Delaying the likely LCP image can make the page’s main content appear later.
How many responsive image widths should I generate?
Generate enough candidates to cover the actual rendered widths and pixel densities your layouts need. There is no universal count; check the selected resource and quality on representative screens.


