ScreenshotNeo

BlogHow-to

How to Optimize Images on Netlify

Use Netlify Image CDN to resize, crop, and convert images on demand. Configure remote sources, framework components, caching, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20268 min read

To optimize images on Netlify, use Netlify Image CDN at /.netlify/images to request images at the dimensions and crop your page needs. It can convert formats, negotiate a supported format from the browser’s Accept header, and cache each transformed result. Same-site images need no extra configuration; remote images need an allowlist. If your site uses a supported framework, its standard image component may provide the CDN integration.

Netlify describes Image CDN as a way to transform images on demand without impacting build times. See the Netlify Image CDN documentation for current options and framework prerequisites.

1. Choose a transformation for the rendered image

Start with the image’s actual display size. A 400-pixel-wide card usually should not download the full original when a smaller rendition will work. Set width with w, height with h, and choose fit behavior when dimensions would change the image’s aspect ratio.

Need Parameters Behavior
Resize while preserving the full image w and/or h fit=contain is the default; the image keeps its proportions.
Fill a fixed-size card by cropping w, h, fit=cover Fills the requested dimensions and crops excess image area.
Force an image into exact dimensions w, h, fit=fill May distort the image to fit.
Keep a particular part visible in a crop position Chooses the retained region when using a crop such as cover.

Dimensions are integer pixel values. Decide crop position by checking the result, especially for portraits, product photos, and images with text or a subject near an edge.

2. Resize a local image with Netlify Image CDN

For an image deployed with your site, put its path in the url parameter. A minimal transformation is:

/.netlify/images?url=/images/photo.jpg&w=800

For a 600 by 400 card crop centered on the source:

/.netlify/images?url=/images/photo.jpg&w=600&h=400&fit=cover&position=center

Use that URL in HTML as the image source:

<img
  src="/.netlify/images?url=%2Fimages%2Fphoto.jpg&w=600&h=400&fit=cover&position=center"
  alt="A descriptive image alternative"
  width="600"
  height="400"
>

The HTML dimensions reserve layout space; keep them consistent with the intended rendered aspect ratio. URL-encode source URLs when constructing a transformation URL in application code, since a remote source URL contains its own query delimiters.

3. Choose output format and quality

To force a format, use fm. Netlify documents avif, jpg, png, webp, gif, and blurhash as format values. For a lossy format, q accepts whole numbers from 1 to 100. The documented default for supported lossy conversions is 75.

/.netlify/images?url=/images/photo.jpg&w=800&fm=avif&q=75

These settings are examples, not universal quality recommendations. Compare the output at its real display size: photographs, illustrations, screenshots, and images with fine text can react differently to compression.

Does Netlify automatically convert images to WebP or AVIF?

When you do not set fm, Netlify checks the browser’s supported formats in this order: WebP, then AVIF, then the original format. The browser’s Accept header is part of format negotiation. If you need a particular output regardless of negotiation, set fm explicitly and verify that format is suitable for the source and use case.

4. Use remote images with Netlify Image CDN

Remote image hosts must be allowed in the site configuration. Add patterns under [images] in netlify.toml, keeping the pattern limited to the hosts and paths you actually use:

[images]
  remote_images = ['https://images.example.com/.*']

Then pass the complete remote source as the url value. Because it is nested inside the transformation URL, encode the source URL when constructing the outer URL. For example, in JavaScript:

const source = 'https://images.example.com/products/photo.jpg';
const params = new URLSearchParams({
  url: source,
  w: '800',
  fit: 'contain'
});
const imageUrl = `/.netlify/images?${params}`;
console.log(imageUrl);

The remote image must be publicly accessible, or use a self-authorizing URL such as a presigned URL. Netlify does not forward credential-bearing Authorization or Cookie headers to a remote source. If the origin requires those headers, make the image available through a supported public or self-authorizing source instead.

5. Use your framework’s image integration when supported

Netlify documents Image CDN integration for Angular, Astro, Gatsby, Next.js, and Nuxt. The integration route can reduce manually assembled URLs, but each framework has its own prerequisites and remote source settings. Check the current Netlify documentation and your framework’s version before switching components.

Framework Documented path and configuration
Angular NgOptimizedImage automatically uses Image CDN. Configure remote domains with images.remote_images.
Astro <Image /> automatically uses Image CDN. Configure remote sources in astro.config.mjs using image.domains or image.remotePatterns.
Gatsby Set NETLIFY_IMAGE_CDN=true and use supported Contentful, Drupal, or WordPress source plugins. Check the documented Gatsby version requirements.
Next.js The documented route requires Next.js 13.5 or later and Netlify adapter v5. Configure remote paths with remotePatterns in next.config.js.
Nuxt nuxt/image automatically uses Image CDN. Configure remote domains in nuxt.config.ts under image.domains.

Use the framework component when it fits the project and its documented prerequisites are met. Use direct CDN URLs when you need a simple drop-in source or want to control each transformation explicitly.

6. Test locally and deploy

  1. Choose a source image and identify its rendered sizes, aspect ratios, and crop needs.
  2. Add the Image CDN URL or configure the relevant framework integration. Allowlist remote sources before requesting them.
  3. Open representative transformed URLs locally and inspect dimensions, framing, and visual quality.
  4. Use Netlify Dev to test transformations in a local environment intended to mimic production.
  5. Deploy and check actual page requests and image appearance at the sizes your design uses.

7. Caching, reliability, and performance

Transformed outputs are uniquely cached at the edge, so repeated requests for the same transformation can use cached output. Different dimensions, crop settings, or formats create different transformation requests. Reuse a consistent set of sizes and options instead of generating arbitrary variants for every request.

Image CDN respects atomic deploys by default. If a relative source image changes in a new deploy, new requests trigger transformations against the new source. For reliable results, keep the source path stable where possible and avoid generating unnecessary combinations of transformation parameters.

Image optimization can reduce the bytes sent for an appropriately sized rendition, but the savings depend on the source, dimensions, format, and quality. No single quality value or format is best for every image; inspect the result and measure your own page payloads. Netlify discourages cross-site redirects for image transformations because they may hurt performance.

8. Troubleshooting

Symptom Likely cause What to check or change
Remote source is rejected or unavailable The host is not allowed, the pattern does not match, or the source is not publicly accessible. Add a narrow matching remote_images pattern and verify the source can be fetched without private cookies or authorization headers.
A remote URL with query parameters behaves incorrectly The nested source URL was not encoded as the outer url parameter. Build the request with a URL encoder such as URLSearchParams rather than concatenating query strings by hand.
The crop cuts off the subject fit=cover fills the box by cropping, and the default or chosen position does not retain the desired region. Set an appropriate position, change the aspect ratio, or use contain to preserve the full image.
The result looks stretched fit=fill forces the requested dimensions. Use contain to preserve the full image proportions or cover to crop without stretching.
The browser does not receive the expected format Automatic negotiation depends on browser support and the Accept header, or fm explicitly requests a different format. Remove fm for negotiation or set the intended format explicitly; inspect the returned image type in the browser’s network tools.
Output quality is too low or files are still large The chosen dimensions, format, and lossy quality do not suit the image. Use dimensions that match display needs, compare formats, and visually review a few quality values from the documented 1–100 range.
A framework image component does not use Image CDN A version, adapter, plugin, or framework configuration prerequisite is missing. Compare the installed versions and configuration with the current Netlify integration instructions for that framework.
Different results appear during Split Testing Netlify states that Split Testing is unsupported for Image CDN and may produce inconsistent results between branches. Do not rely on Image CDN transformations in Split Testing; account for the documented limitation in the site design.

9. Netlify Image CDN limitations to account for

  • Split Testing is unsupported for Image CDN and can produce inconsistent results between branches.
  • Image CDN is not currently part of Netlify’s HIPAA-compliant hosting offering.
  • Cross-site redirects for transformations are not recommended because they may negatively affect performance.

For older sites using Netlify Large Media, its legacy transformation syntax uses parameters such as nf_resize=fit or nf_resize=smartcrop. Current Image CDN URLs use /.netlify/images with parameters such as url, w, h, and fit. Do not mix the two URL styles when configuring a current Image CDN transformation.

10. Or skip the browser setup

If your task is capturing a rendered web page as an image or PDF rather than optimizing images already served by Netlify, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. For an image response, request a URL like this:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed, and response headers say the page verdict and billing status. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month with no card.

11. Frequently asked questions

Do I need to install a plugin to use Netlify Image CDN?

No for direct URLs: use the built-in /.netlify/images route. Framework image integrations have their own prerequisites and configuration.

Can I use an image that requires a login?

Not by relying on the visitor’s private cookies or Authorization header. Remote sources need to be publicly accessible or use a self-authorizing URL such as a presigned URL.

Should I always force AVIF?

No. Let Netlify negotiate a format based on browser support unless you have a reason to force a particular format, and check the result with your image content and audience.

Does changing a local source image require a new transformation URL?

Netlify’s documented atomic deploy behavior means a changed relative source in a new deploy is used for new requests. Keep transformation settings stable and verify the deployed result.