netlify-image-cdn
netlify/context-and-tools
Transform images on demand with resizing, cropping, format conversion, and quality control via Netlify Image CDN.
What is netlify-image-cdn?
Netlify Image CDN transforms images on-the-fly using the /.netlify/images endpoint with query parameters for resizing, cropping, format conversion (WebP/AVIF/PNG/GIF), and quality adjustment. Use it to optimize images for responsive design, generate thumbnails, serve remote images through the CDN, or create blur placeholders.
- Resize images by width and height with aspect-ratio-aware fitting (contain, cover, fill)
- Convert image formats (AVIF, JPG, PNG, WebP, GIF) with content negotiation
- Crop images with position anchors (top, bottom, left, right, center) when using cover fit
- Generate BlurHash text strings for client-side blur placeholders
- Allowlist and transform remote/third-party images via netlify.toml configuration
- Cache transformed images with custom headers and atomic deploy invalidation
How to install netlify-image-cdn
npx skills add https://github.com/netlify/context-and-tools --skill netlify-image-cdn- Netlify site deployed or running netlify dev locally
- netlify.toml configuration for remote image allowlisting (if using remote sources)
- BlurHash library (https://blurha.sh) if generating blur placeholders
How to use netlify-image-cdn
- 1.Call /.netlify/images?url=<source> with required url parameter and optional query params (w, h, fit, position, fm, q)
- 2.For remote images, add regex patterns to [images] remote_images in netlify.toml and percent-encode the URL with encodeURIComponent()
- 3.Use fit=contain (default) to maintain aspect ratio, fit=cover to crop to exact dimensions, or fit=fill to stretch
- 4.Specify fm parameter to force output format (avif, jpg, png, webp, gif, blurhash) or omit for content-negotiated format
- 5.Set q parameter (1–100) to control quality for lossy formats; default is 75
- 6.For framework integration (Angular/Astro/Gatsby/Next.js/Nuxt), use the framework's built-in image component and configure remote allowlist only
Use cases
- Build responsive image pipelines that serve optimized formats based on browser support
- Generate thumbnail previews and blur placeholders for lazy-loaded images
- Convert user-uploaded images to multiple formats and sizes on demand
- Serve third-party images (e.g., from APIs or CDNs) through your Netlify domain
- Create friendly URL redirects that apply consistent transformations across images
- Frontend developers building image-heavy sites or galleries
- Full-stack developers handling user-uploaded image pipelines
- Teams using Angular, Astro, Gatsby, Next.js, or Nuxt frameworks
- Developers optimizing Core Web Vitals and image delivery performance
netlify-image-cdn FAQ
You're likely running a framework dev server (vite, next dev, astro dev) instead of netlify dev. The endpoint only exists under netlify dev or on deployed sites. Start with netlify dev.
Yes, but you must allowlist them first in netlify.toml under [images] remote_images with regex patterns. Remote sources must be publicly accessible; credential-bearing headers (Authorization, Cookie) are not forwarded.
fm=blurhash returns a text string, not image bytes. Fetch it ahead of time, decode it client-side with a BlurHash library, and load the real image as a separate request without fm=blurhash.
Angular (NgOptimizedImage), Astro (<Image />), Gatsby (with NETLIFY_IMAGE_CDN=true env var), Next.js 13.5+, and Nuxt (nuxt/image module) all use it automatically. Configure the remote allowlist in the framework's config file.
Create a redirect or rewrite in _redirects or netlify.toml that maps a friendly path to /.netlify/images with fixed parameters, e.g., /transform-small/* /.netlify/images?url=/:splat&w=50&h=50 200.
Full instructions (SKILL.md)
Source of truth, from netlify/context-and-tools.
name: netlify-image-cdn description: Transforms images on demand via Netlify Image CDN's /.netlify/images endpoint with query parameters for resizing/cropping/format/quality. Use when adding image optimization or responsive images, converting formats (WebP/AVIF/PNG), generating thumbnails or blur placeholders, serving remote/third-party images through the CDN, allowlisting remote domains in netlify.toml, setting up image redirects or cache headers, building user-uploaded image pipelines, or debugging a 404 on /.netlify/images. Also covers framework image handling for Angular/Astro/Gatsby/Next.js/Nuxt.
Netlify Image CDN
Transform images by requesting the endpoint with a url query parameter. This is the current and only documented surface — there is no legacy form.
GET /.netlify/images?url=<source>[&w=][&h=][&fit=][&position=][&fm=][&q=]
# resize a deployed image to 50px wide
curl -vs 'https://mysitename.netlify.app/.netlify/images?url=/owl.jpeg&w=50'
url is required; all other parameters are optional.
Query parameters
| Parameter | Purpose | Values | Default |
|---|---|---|---|
url | Source asset (required) | Relative path or remote URL | — |
w | Width in pixels | Integer | — |
h | Height in pixels | Integer | — |
fit | Resize behavior | contain, cover, fill | contain |
position | Crop anchor when fit=cover | top, bottom, left, right, center | center |
fm | Output format | avif, jpg, png, webp, gif, blurhash | content-negotiated |
q | Quality for lossy output | Integer 1–100 | 75 |
Common transformations
# resize + crop to a 50px square, retaining the left side
curl -vs 'https://mysitename.netlify.app/.netlify/images?url=/owl.jpeg&fit=cover&w=50&h=50&position=left'
# convert JPEG to PNG (response carries content-type: image/png)
curl -vs 'https://mysitename.netlify.app/.netlify/images?url=/owl.jpeg&fm=png'
# convert JPEG to AVIF at medium quality
curl -vs 'https://mysitename.netlify.app/.netlify/images?url=/owl.jpeg&fm=avif&q=50'
fit behavior
contain(default): maintains aspect ratio; one dimension may come back smaller than requested. Supply one dimension and the other is computed.cover: fills exactly, cropping excess. Requires BOTHwandh— omitting either is invalid. Usepositionto choose what's retained.fill: fills exactly, stretching/squishing if aspect ratios differ.
Format notes
qapplies only when output isavif,jpg,gif, orwebp.webpandgifcan be static or animated.- If
fmis omitted, format is content-negotiated from theAcceptheader:webpif accepted, elseavifif accepted, else the original format. A source-only request (no other params) still converts towebp/avifbut keeps size and shape.
Remote source images
Remote sources must be allowlisted in netlify.toml before transformation, or the request fails.
[images]
remote_images = ['https://my-images\.com/.*', 'https://animals.more-images.com/[bcr]at/.*']
Percent-encode remote source URLs before placing them in the url parameter with encodeURIComponent — a URL containing ? or & breaks otherwise.
const src = `/.netlify/images?url=${encodeURIComponent('https://my-images.com/owl.jpeg?v=2')}&w=400`;
Constraints:
- Remote sources must be publicly accessible.
- Credential-bearing headers (
Authorization,Cookie) are NOT forwarded when fetching a remote source. For authenticated sources, use URLs that carry their own authorization (e.g. S3 presigned URLs) and make sure yourremote_imagespatterns match those full URLs.
remote_images regex escaping
The only meaningful escape is the literal dot (\.). Forward slashes are NOT metacharacters — never write https:\/\/. In netlify.toml, use single-quoted literal strings ('https://example\.com/.*') or double the backslash in double-quoted strings ("https://example\\.com/.*"). A bare \. inside double quotes is invalid TOML.
Response codes
- Invalid transformation parameter values →
404. - Valid new transformation →
200with content and matchingcontent-type. - Previously transformed (cached) image →
304.
Reusing parameters across images
Map a friendly path to the endpoint with a redirect/rewrite.
_redirects:
/transform-small/* /.netlify/images?url=/:splat&w=50&h=50 200
netlify.toml:
[[redirects]]
from = "/transform-small/*"
to = "/.netlify/images?url=/:splat&w=50&h=50"
status = 200
Then GET /transform-small/owl.jpeg returns the transformed image. Cross-site redirects for transformations are NOT recommended — they can degrade site performance.
Caching headers
Apply custom headers to source images on the site's own domain; they carry through to the transformed output.
netlify.toml:
[[headers]]
for = "/source-images/*"
[headers.values]
Cache-Control = "public, max-age=604800, must-revalidate"
- Custom headers can be applied to source images on the site's domain only — NOT to remote source images (Netlify does respect cache headers the external domain sends).
Cache-Controlon source images applies only to browsers and CDNs in front of Netlify, NOT the Netlify Cache itself.
Blur placeholders (fm=blurhash)
fm=blurhash returns a BlurHash text string, not image bytes. Pointing an <img src> (or CSS background) at it renders nothing. Fetch the string ahead of time, decode it client-side with a BlurHash library (https://blurha.sh), and load the real image as a separate request without fm=blurhash.
Local development
The /.netlify/images endpoint, [images] allowlisting, and image redirects only exist under netlify dev (Netlify CLI). A local 404 on /.netlify/images almost always means a framework dev server (vite, next dev, astro dev) is running instead of netlify dev — the URL itself is usually fine. Start the local environment with netlify dev.
User-uploaded image pipelines
For pipelines composing Functions + Blobs + Image CDN (handling user-uploaded images), see references/user-uploads.md.
Framework image handling
Many frameworks route their built-in image optimization through Netlify Image CDN — use the framework's standard image component/syntax and only configure the remote allowlist. For unlisted frameworks, call /.netlify/images directly.
| Framework | Prerequisites | Remote allowlist location |
|---|---|---|
| Angular | None; NgOptimizedImage uses it automatically | [images] remote_images in netlify.toml |
| Astro | None; <Image /> uses it automatically | image.domains or image.remotePatterns in astro.config.mjs |
| Gatsby (both 5.13+ and 5.11 or earlier) | Set env NETLIFY_IMAGE_CDN=true; use Contentful/Drupal/WordPress source plugins | [images] remote_images in netlify.toml |
| Next.js | Next.js 13.5+ and Next.js adapter v5 | remotePatterns in next.config.js |
| Nuxt | None; nuxt/image module uses it automatically | image.domains in nuxt.config.ts |
Setup guides: Angular, Astro, Gatsby, Next.js, Nuxt.
Additional constraints
- Deploy behavior: transforms respect atomic deploys; changing a source image in a new deploy re-runs transforms on subsequent requests.
- Split Testing is NOT supported — image results may be inconsistent across split test branches.
- Netlify Image CDN is NOT part of Netlify's HIPAA-compliant hosting offering.
Interactive parameter playground: https://image-cdn-playground.netlify.app/
<!-- system: agent-context/image-cdn/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->Netlify house rules (image-cdn)
These are org conventions, not docs facts — merged into the rendered skill by ctx-gen and never generated. Owned by the skills maintainer.
- For user-uploaded image pipelines (Functions + Blobs + Image CDN
composed), see
references/user-uploads.mdin this skill — an authored guide with no single docs source. - Percent-encode remote source URLs before placing them in the
urlparameter (encodeURIComponent) — URLs containing?or&break otherwise. fm=blurhashreturns a BlurHash TEXT string, not image bytes. Pointing an<img src>(or CSS background) at it renders nothing — fetch the string ahead of time, decode it client-side with a BlurHash library, and load the real image as a separate request withoutfm=blurhash.- A local 404 on
/.netlify/imagesalmost always means a framework dev server (vite,next dev,astro dev) is running instead ofnetlify dev— the endpoint,[images]allowlisting, and image redirects only exist undernetlify dev. The URL itself is usually fine. - In
remote_imagespatterns, the meaningful regex escape is the dot; forward slashes are not metacharacters — do not writehttps:\/\/. Innetlify.toml, use a single-quoted literal string ('https://example\.com/.*') or double the backslash in a double-quoted string ("https://example\\.com/.*") — a bare\.inside double quotes is invalid TOML.
Related skills
More from netlify/context-and-tools and the wider catalog.

netlify-mcp-servers
Build and deploy secure MCP servers on Netlify Functions to expose your app's tools to AI agents like Claude and Cursor.

netlify-access-control
Route Netlify site protection to the right layer: Password Protection, Private projects, or Team SSO.

netlify-agent-runner
Run AI coding agents remotely on Netlify to automate development tasks on your site.

netlify-ai-gateway
Call OpenAI, Anthropic, Google Gemini, TypeSafe, or OpenRouter models from Netlify Functions with injected credentials.

context7
Fetch current library docs and API references via Context7 REST API when MCP server is unavailable.

android-testing
Comprehensive testing strategy involving Unit, Integration, Hilt, and Screenshot tests.