images Configurations

You can configure the Image Component in next.config.js. The following options are available:


1. localPatterns

Use localPatterns in your next.config.js file to allow images from specific local paths to be optimized and block all others.

module.exports = { images: { localPatterns: [ { pathname: '/assets/images/**', search: '', }, ], }, }

The example above will ensure the src property of next/image must start with /assets/images/ and must not have a query string. Attempting to optimize any other path will respond with 400 Bad Request error.


2. remotePatterns

Use remotePatterns in your next.config.js file to allow images from specific external paths and block all others. This ensures that only external images from your account can be served.

module.exports = { images: { remotePatterns: [new URL('https://example.com/account123/**')], }, }

If using a version prior to 15.3.0, you can configure remotePatterns using the object:

module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/account123/**', search: '', }, ], }, }

The example above will ensure the src property of next/image must start with https://example.com/account123/ and must not have a query string. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request.

Wildcard Patterns: Wildcard patterns can be used for both pathname and hostname and have the following syntax:

module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: '**.example.com', port: '', search: '', }, ], }, }

This allows subdomains like image.example.com. Query strings and custom ports are still blocked.

Good to know: When omitting protocol, port, pathname, or search then the wildcard ** is implied. This is not recommended because it may allow malicious actors to optimize URLs you did not intend.

Query Strings: You can also restrict query strings using the search property:

module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'assets.example.com', search: '?v=1727111025337', }, ], }, }

The example above will ensure the src property of next/image must start with https://assets.example.com and must have the exact query string ?v=1727111025337. Any other protocol or query string will respond with 400 Bad Request.


3. loaderFile

loaderFile allows you to use a custom image optimization service instead of Next.js.

module.exports = { images: { loader: 'custom', loaderFile: './my/image/loader.js', }, }

The path must be relative to the project root. The file must export a default function that returns a URL string:

'use client' export default function myImageLoader({ src, width, quality }) { return `https://example.com/${src}?w=${width}&q=${quality || 75}` }

4. deviceSizes

deviceSizes allows you to specify a list of device width breakpoints. These widths are used when the next/image component uses sizes prop to ensure the correct image is served for the user's device.

If no configuration is provided, the default below is used:

module.exports = { images: { deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], }, }

5. imageSizes

imageSizes allows you to specify a list of image widths. These widths are concatenated with the array of device sizes to form the full array of sizes used to generate image srcset.

If no configuration is provided, the default below is used:

module.exports = { images: { imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], }, }

imageSizes is only used for images which provide a sizes prop, which indicates that the image is less than the full width of the screen. Therefore, the sizes in imageSizes should all be smaller than the smallest size in deviceSizes.


6. qualities

qualities allows you to specify a list of image quality values.

module.exports = { images: { qualities: [25, 50, 75], }, }

In the example above, only three qualities are allowed: 25, 50, and 75. If the quality prop does not match a value in this array, the image will fail with a 400 Bad Request.


7. formats

formats allows you to specify a list of image formats to be used.

module.exports = { images: { // Default formats: ['image/webp'], }, }

Next.js automatically detects the browser's supported image formats via the request's Accept header in order to determine the best output format.

If the Accept header matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is animated), it will use the original image's format.

You can enable AVIF support, which will fallback to the original format of the src image if the browser does not support AVIF:

module.exports = { images: { formats: ['image/avif'], }, }

Good to know:


8. minimumCacheTTL

minimumCacheTTL allows you to configure the Time to Live (TTL) in seconds for cached optimized images. In many cases, it's better to use a Static Image Import which will automatically hash the file contents and cache the image forever with a Cache-Control header of immutable.

If no configuration is provided, the default below is used.

module.exports = { images: { minimumCacheTTL: 60, // 1 minute }, }

You can increase the TTL to reduce the number of revalidations and potentially lower cost:

module.exports = { images: { minimumCacheTTL: 2678400, // 31 days }, }

The expiration (or rather Max Age) of the optimized image is defined by either the minimumCacheTTL or the upstream image Cache-Control header, whichever is larger.

If you need to change the caching behavior per image, you can configure headers to set the Cache-Control header on the upstream image (e.g. /some-asset.jpg, not /_next/image itself).

There is no mechanism to invalidate the cache at this time, so it is best to keep minimumCacheTTL low. Otherwise you may need to manually change the src prop or delete the cached file <distDir>/cache/images.


9. disableStaticImages

disableStaticImages allows you to disable static image imports.

The default behavior allows you to import static files such as import icon from './icon.png' and then pass that to the src property. In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.

You can disable static image imports inside your next.config.js:

module.exports = { images: { disableStaticImages: true, }, }

10. dangerouslyAllowSVG

dangerouslyAllowSVG allows you to serve SVG images.

module.exports = { images: { dangerouslyAllowSVG: true, }, }

By default, Next.js does not optimize SVG images for a few reasons:

We recommend using the unoptimized prop when the src prop is known to be SVG. This happens automatically when src ends with ".svg".

<Image src="/my-image.svg" unoptimized />

In addition, it is strongly recommended to also set contentDispositionType to force the browser to download the image, as well as contentSecurityPolicy to prevent scripts embedded in the image from executing.

module.exports = { images: { dangerouslyAllowSVG: true, contentDispositionType: 'attachment', contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, }

11. contentDispositionType

contentDispositionType allows you to configure the Content-Disposition header.

module.exports = { images: { contentDispositionType: 'inline', }, }

By default, the loader sets the Content-Disposition header to attachment for added protection since the API can serve arbitrary remote images.

The default value is attachment which forces the browser to download the image when visiting directly. This is particularly important when dangerouslyAllowSVG is true.

You can optionally configure inline to allow the browser to render the image when visiting directly, without downloading it.

The images configuration option in next.config.js allows you to customize how Next.js handles loading.

If you prefer to use a cloud provider to optimize images instead of Next.js's built-in Image Optimization API, you can configure a custom image loader by setting the loader and loaderFile options.

// next.config.js module.exports = { images: { loader: 'custom', loaderFile: './my/image/loader.js', }, }

The loaderFile path is relative to the root of your Next.js project. This file must export a default function that returns the URL string for the image source with optional width and quality parameters, for example:

// my/image/loader.js 'use client' export default function myImageLoader({ src, width, quality }) { return `https://example.com/${src}?w=${width}&q=${quality || 75}` }

Alternatively, you can pass a custom loader function via the loader prop directly on each next/image component instance.

Good to know: Customizing the image loader requires using Client Components to serialize the provided function properly.




Example Loaders for Popular Providers

Below are some example custom loaders adapted for various cloud image providers. Replace https://example.com with your actual CDN or image service base URL.


1. Akamai   2256  
export default function akamaiLoader({ src, width, quality }) { return `https://example.com/${src}?imwidth=${width}` }
2. AWS CloudFront   27  
export default function cloudfrontLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) url.searchParams.set('format', 'auto') url.searchParams.set('width', width.toString()) url.searchParams.set('quality', (quality || 75).toString()) return url.href }
3. Cloudinary   944  
export default function cloudinaryLoader({ src, width, quality }) { const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`] return `https://example.com/${params.join(',')}${src}` }
4. Cloudflare   10  
export default function cloudflareLoader({ src, width, quality }) { const params = [`width=${width}`, `quality=${quality || 75}`, 'format=auto'] return `https://example.com/cdn-cgi/image/${params.join(',')}/${src}` }
5. Contentful   5571  
export default function contentfulLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) url.searchParams.set('fm', 'webp') url.searchParams.set('w', width.toString()) url.searchParams.set('q', (quality || 75).toString()) return url.href }
6. Fastly   8594  
export default function fastlyLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) url.searchParams.set('auto', 'webp') url.searchParams.set('width', width.toString()) url.searchParams.set('quality', (quality || 75).toString()) return url.href }
7. Gumlet   89785  
export default function gumletLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) url.searchParams.set('format', 'auto') url.searchParams.set('w', width.toString()) url.searchParams.set('q', (quality || 75).toString()) return url.href }
8. ImageEngine 
export default function imageengineLoader({ src, width, quality }) { const compression = 100 - (quality || 50) const params = [`w_${width}`, `cmpr_${compression}`] return `https://example.com${src}?imgeng=/${params.join('/')}` }
9. Imgix   2810  
export default function imgixLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) const params = url.searchParams params.set('auto', params.getAll('auto').join(',') || 'format') params.set('fit', params.get('fit') || 'max') params.set('w', params.get('w') || width.toString()) params.set('q', (quality || 50).toString()) return url.href }
10. PixelBin   74424  
export default function pixelBinLoader({ src, width, quality }) { const name = '<your-cloud-name>' const opt = `t.resize(w:${width})~t.compress(q:${quality || 75})` return `https://cdn.pixelbin.io/v2/${name}/${opt}/${src}?f_auto=true` }
11. Sanity   4962  
export default function sanityLoader({ src, width, quality }) { const prj = 'zp7mbokg' const dataset = 'production' const url = new URL(`https://cdn.sanity.io/images/${prj}/${dataset}${src}`) url.searchParams.set('auto', 'format') url.searchParams.set('fit', 'max') url.searchParams.set('w', width.toString()) if (quality) { url.searchParams.set('q', quality.toString()) } return url.href }
12. Sirv   21056  
export default function sirvLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) const params = url.searchParams params.set('format', params.getAll('format').join(',') || 'optimal') params.set('w', params.get('w') || width.toString()) params.set('q', (quality || 85).toString()) return url.href }
13. Supabase   25095  
export default function supabaseLoader({ src, width, quality }) { const url = new URL(`https://example.com${src}`) url.searchParams.set('width', width.toString()) url.searchParams.set('quality', (quality || 75).toString()) return url.href }
14. Thumbor   955  
export default function thumborLoader({ src, width, quality }) { const params = [`${width}x0`, `filters:quality(${quality || 75})`] return `https://example.com${params.join('/')}${src}` }
15. ImageKit.io   11464  
export default function imageKitLoader({ src, width, quality }) { const params = [`w-${width}`, `q-${quality || 80}`] return `https://ik.imagekit.io/your_imagekit_id/${src}?tr=${params.join(',')}` }
16. Nitrogen AIO   197136  
export default function aioLoader({ src, width, quality }) { const url = new URL(src, window.location.href) const params = url.searchParams const aioParams = params.getAll('aio') aioParams.push(`w-${width}`) if (quality) { aioParams.push(`q-${quality.toString()}`) } params.set('aio', aioParams.join(';')) return url.href }