ScreenshotNeo

BlogHow-to

How to deliver website images through a CDN

Serve responsive website images through a CDN with deliberate transformations, cache keys, and freshness rules. Learn the tradeoffs and troubleshoot common delivery issues.

By the ScreenshotNeo team4 October 20268 min read

To deliver website images through a CDN, store originals at a hosted image service or your own origin, put cacheable image URLs behind the CDN, and serve dimensions suited to each rendered image. Use responsive candidates or automatic width selection, choose transformations and format negotiation deliberately, and ensure the CDN cache key distinguishes every output variant. Set freshness and revalidation behavior so image updates appear when intended.

A CDN can reuse cacheable image responses near users, but the result depends on the CDN configuration and origin response headers. The right setup depends on where your originals live, which transformations you need, and your existing cloud infrastructure. There are no comparable benchmarks in the reviewed documentation to support a universal fastest or cheapest choice.

1. Choose where your image originals live

There are two common patterns:

  • Hosted image service: Upload originals to the provider and deliver provider-managed URLs. Cloudflare Images, for example, uses an account hash, image ID, and variant in its URL pattern. The service manages variants and can select supported formats for browsers.
  • Your origin plus CDN transformations: Keep originals on your own storage or web origin. The CDN fetches an original and returns a resized, cropped, compressed, or converted response using URL parameters or an edge program such as a Worker.

Choose a hosted service when you want provider-managed image URLs and variants. Choose an origin-backed setup when retaining your existing source of truth and controlling transformation URLs matters. For AWS-based systems, a transformation layer can be paired with a CloudFront distribution; AWS documents a Lambda-based architecture as one implementation pattern. It is an example, not evidence that this is the best or cheapest option.

2. Serve an image close to its rendered size

Do not make every device download the largest source image when the page displays it at a smaller size. Provide candidates and let the browser select one with srcset and sizes:

<img
  src="https://images.example.com/products/shoe-800.jpg"
  srcset="https://images.example.com/products/shoe-400.jpg 400w,
          https://images.example.com/products/shoe-800.jpg 800w,
          https://images.example.com/products/shoe-1200.jpg 1200w"
  sizes="(max-width: 600px) 100vw, 50vw"
  width="800"
  height="800"
  alt="Blue running shoe"
>

The sizes value describes the image’s expected layout width; the browser uses that and its device characteristics to choose among the candidates. Set intrinsic width and height to reserve layout space. If you cannot change markup to list candidates, a provider may offer automatic width selection; Cloudflare documents a width=auto option for this case.

Generate candidates at the sizes your layouts actually use, including larger pixel-density needs where appropriate. Too few candidates can mean an image looks soft or downloads more bytes than needed. A candidate URL should return the intended dimensions consistently, and each distinct width or crop is a distinct transformed object for caching purposes.

3. Define transformations and format delivery

Common transformations include resizing, cropping, compression, and converting to another format. A provider may expose them as URL parameters, a Worker API, or a programmatic interface. Google Cloud documents image transformations using URL query parameters, with output variants cached at the edge.

Format negotiation can serve a format such as AVIF or WebP to browsers that support it while retaining a fallback. Cloudflare Images documents this behavior for supported browsers. When a response varies according to the request’s Accept header, cache behavior must preserve the distinction between the variants. Cloudflare’s optimized image documentation describes separate cached variants selected using Accept.

Decide the output format and quality policy with your actual content and clients in mind. A photograph, transparent icon, and line illustration may have different requirements. Confirm the response’s Content-Type and dimensions for representative requests rather than assuming the URL parameters produced the requested result.

4. Configure cache keys and freshness

Think of every output transformation or negotiated format as a separate cache object. If a width, crop, quality, or format parameter changes the bytes, that difference needs to be reflected in the cache key. CloudFront cache policies let you choose which query strings, headers, and cookies contribute to its key. Including irrelevant values can fragment the cache; omitting a value that changes the response can cause the wrong variant to be reused.

Set freshness behavior in coordination with the origin. CloudFront’s TTL behavior works with origin Cache-Control and Expires headers. Cloudflare says optimized images follow caching rules derived from the original, with a minimum cache time of one hour, and recommends ETag for revalidation. This means an origin replacement may not appear everywhere immediately; the result depends on the selected freshness and revalidation rules.

Use stable, versioned URLs when a changed image must be visible promptly, or use a planned revalidation or invalidation process supported by your platform. Avoid changing the bytes behind a long-lived immutable URL unless the cache policy accounts for it.

5. Select a CDN approach that fits your stack

Approach Useful when Constraints to check
Cloudflare Images hosted delivery You want hosted originals, provider-managed variants, and format selection. URLs use the hosted service’s image IDs and variants. Supported browsers can receive AVIF or WebP with fallback behavior.
Cloudflare image optimization You want URL or Worker transformations of origin images. Cache behavior follows HTTP rules; the documented optimized-image behavior has a one-hour minimum cache time and supports ETag revalidation.
Google Cloud CDN image optimization You already use supported Google Cloud load-balancing and CDN infrastructure. The reviewed documentation marks the feature Pre-GA. It requires caching, a Global External Application Load Balancer, an acceptable image request, and a supported origin response. Check current launch status and prerequisites before adopting it.
CloudFront with a transformation layer You run on AWS and need control over cache keys and TTLs. CloudFront cache policies determine which query strings, headers, and cookies enter the cache key. Transformation logic must be implemented or adopted.

Compare services on where originals are hosted, responsive sizing, format negotiation, transformation control, cache-key and freshness behavior, compatibility with your existing cloud and load balancer, and feature maturity. The available documentation does not establish comparable current pricing or performance, so measure your own workload before choosing on cost or speed.

6. Verify delivery paths

  1. Request each representative width, crop, and format variant from the public CDN URL.
  2. Inspect response status, Content-Type, dimensions, and cache-related response headers.
  3. Repeat the same request to check whether the expected cache behavior occurs.
  4. Change an origin image or variant and verify that it becomes visible according to your freshness, revalidation, or invalidation policy.
  5. Test browsers and page layouts that use the image, including mobile widths and any transparent assets.

These are implementation checks inferred from documented format selection, transformations, and cache rules; they are not claims of hands-on testing of a particular provider.

7. Common problems and fixes

Symptom Likely cause What to check or change
The wrong size or crop appears The transformation URL is missing a parameter, or the cache key ignores a parameter that changes the response. Compare the requested URL and output dimensions. Ensure all response-changing query parameters are included in the cache key.
A browser receives an unsupported format Format negotiation and cache variation are not aligned. Check the request’s Accept header, response Content-Type, and whether the cache distinguishes negotiated variants.
Image changes do not show up A fresh cached response is still valid, or the URL remains unchanged despite changed bytes. Review origin Cache-Control/Expires, TTL policy, ETag revalidation, and any invalidation or versioned-URL approach.
Images are larger than the layout needs Only one oversized asset is used, or srcset/sizes describes candidates incorrectly. Provide appropriate width candidates, correct the sizes layout description, or use the provider’s documented automatic width selection.
An image optimization feature is unavailable The request, origin response, cache setup, load balancer, or product maturity does not meet platform requirements. Check the provider’s current prerequisites. For Google Cloud, the reviewed feature is Pre-GA and requires caching and a supported Global External Application Load Balancer.
Cache hit rate is unexpectedly low URLs vary unnecessarily, such as by irrelevant query strings or headers. Inspect the cache key policy and keep only values that meaningfully change the response.

8. Performance, reliability, and cost considerations

Serving the right dimensions avoids sending an oversized image to every device. Edge caching can reuse transformed results for repeat requests, but the first request may require an origin fetch or transformation. Actual latency and cache hit behavior depend on cache configuration, URL stability, origin response headers, and the user’s path to the CDN.

Reliability depends on both the CDN path and origin availability for uncached or expired objects. Plan how updates are propagated and how unsupported inputs or origin responses are handled. Where a feature has infrastructure prerequisites or a pre-release maturity designation, include that in the deployment decision.

Cost cannot be compared from the reviewed documentation: it does not provide a complete, current, like-for-like price or benchmark across these options. Check current provider pricing for storage, delivery, transformations, and any supporting compute. Avoid assuming an architecture is cheaper because transformations happen at the edge; measure the request mix, cache reuse, and transformation needs.

Or skip the browser setup

If your goal is to document or inspect a page while building its image delivery workflow, ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a PNG, JPEG, WebP, or PDF. Its screenshot API is not a CDN and does not replace image delivery; it can help capture pages without setting up a browser automation stack. See the ScreenshotNeo API documentation.

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}`);

Cookie banners are accepted like a visitor and removed before the capture, along with 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say which occurred. Its MCP server lets AI agents use 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 shots. Sign up free for ScreenshotNeo.

FAQ

Should image transformations happen at the origin or edge?

Either can work. Use the approach your platform supports and account for where the transformed result is cached. The reviewed documentation describes both hosted or edge transformations and origin-backed setups.

Do all CDN image URLs need a separate cache key?

They need cache distinctions for values that change the response, such as width, crop, or negotiated format. Unrelated values should not fragment the cache unnecessarily.

Can I keep the same URL when replacing an image?

Yes, if your freshness and revalidation policy is designed for updates. For predictable propagation, use versioned URLs or a supported invalidation approach.

Which provider is the fastest?

The reviewed sources do not contain comparable benchmarks. Test the candidate architecture with your origins, transformations, cache policy, and user locations.