ScreenshotNeo

BlogGuides

Next.js Image

Use Next.js Image with local and remote sources, responsive layouts, and the right loading and security settings.

By the ScreenshotNeo team1 October 20268 min read

Next.js Image

Next.js Image extends the HTML <img> element with image optimization. Use it with a local path, a remote URL, or a static import. For remote URLs, allow only the hosts and paths your app needs. Supply intrinsic dimensions or use fill, and add an accurate sizes value for responsive layouts so the browser can choose an appropriately sized image.

1. Install and import Image

The component is included with Next.js. Import it from next/image in either the App Router or Pages Router:

import Image from 'next/image'

The examples below are React components. Put them in a component rendered by your route. The image configuration examples belong in the project-root next.config.js or next.config.mjs; restart the development server after changing configuration.

2. Choose a source: local, static import, or remote

Local file in public

Files inside public can be referenced from the site root. Provide the image’s original dimensions unless you use fill.

A narrow remote pattern controls which image sources the Next.js optimizer can fetch.
A narrow remote pattern controls which image sources the Next.js optimizer can fetch.
import Image from 'next/image'

export default function Logo() {
  return <Image src="/images/logo.png" alt="Acme logo" width={320} height={80} />
}

Static import

Importing a local image lets Next.js obtain its intrinsic dimensions from the file metadata. This is convenient for layout stability and can provide blur metadata for supported image formats when configured or generated by the build.

import Image from 'next/image'
import landscape from './landscape.jpg'

export default function Landscape() {
  return <Image src={landscape} alt="Mountain landscape at sunrise" />
}

Remote URL

Next.js cannot inspect a remote image during the build. Provide width and height that describe its intrinsic aspect ratio, or use fill. Allow the remote source in remotePatterns.

// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.example.com',
        port: '',
        pathname: '/products/**',
      },
    ],
  },
}

export default nextConfig
import Image from 'next/image'

export default function ProductPhoto() {
  return (
    <Image
      src="https://images.example.com/products/chair.jpg"
      alt="Blue upholstered chair"
      width={1200}
      height={900}
    />
  )
}

Use a narrow pattern: protocol, hostname, optional port, and pathname can constrain which URLs the optimizer fetches. Avoid broadly allowing remote paths or arbitrary query strings. The older domains option is deprecated since Next.js 14 in favor of remotePatterns.

3. Set dimensions and layout

width and height describe the source image’s intrinsic size and reserve its aspect ratio to reduce layout shift. They do not set the rendered CSS size. They are required for ordinary URL sources, except when using a static import or fill.

Responsive width and height

Let CSS determine the display width while keeping the aspect ratio. Set sizes to describe the actual layout at the relevant breakpoints.

<Image
  src="/images/article.jpg"
  alt="A notebook beside a cup of coffee"
  width={1600}
  height={1000}
  sizes="(max-width: 700px) 100vw, (max-width: 1100px) 70vw, 800px"
  style={{ width: '100%', height: 'auto' }}
/>

Without sizes, the browser assumes 100vw. If the image renders in a smaller column, that can cause an unnecessarily large download. Match the value to the rendered width rather than copying a generic value.

Fill a positioned parent

Use fill when the image should expand to its container. The parent must establish positioning, such as relative. Use objectFit to crop with cover or keep the entire image visible with contain.

<div style={{ position: 'relative', width: '100%', aspectRatio: '4 / 3' }}>
  <Image
    src="https://images.example.com/products/chair.jpg"
    alt="Blue upholstered chair"
    fill
    sizes="(max-width: 700px) 100vw, 50vw"
    style={{ objectFit: 'cover' }}
  />
</div>

With fill, the image is positioned within its parent. Give the parent a deliberate size or aspect ratio so it has space to display the image.

4. Loading, priority, placeholders, and formats

  • Default lazy loading: below-the-fold images generally do not need a loading override.
  • loading="eager": use when an image needs to load immediately but is not a clear preload candidate.
  • preload: for Next.js 16 and later, use for a clear above-the-fold or likely LCP image. The priority property is deprecated in favor of preload. Do not preload several images when it is unclear which is the LCP image; eager loading or high fetch priority may be more appropriate.
  • Blur placeholder: use placeholder="blur" when you have a blurDataURL. Static imports can provide blur metadata in supported cases; remote sources need blur data supplied separately.
  • Formats: WebP is recommended for most use cases. AVIF can produce smaller files but generally encodes more slowly, so first-request cost and cache behavior matter.
  • unoptimized: consider it for animated GIFs, small images, and SVGs where optimization is not useful or appropriate.
<Image
  src="/images/hero.jpg"
  alt="A city skyline at dawn"
  width={1800}
  height={900}
  sizes="100vw"
  preload
/>

For versions before Next.js 16, check the installed version’s reference for its supported loading and priority props. Version-specific defaults and options should be checked against the version deployed by your project.

5. Configure local sources and optimizer behavior

Use localPatterns to restrict which local paths the image optimizer accepts. Keep the patterns as narrow as practical, particularly when query strings are involved.

// next.config.mjs
const nextConfig = {
  images: {
    localPatterns: [
      { pathname: '/images/**', search: '' },
    ],
    formats: ['image/webp', 'image/avif'],
    minimumCacheTTL: 14400,
  },
}

export default nextConfig

The documented defaults include quality 75, a four-hour minimum cache TTL when no configuration or upstream cache directive changes it, up to three redirects, and a 50 MB maximum source response body. These are defaults, not performance guarantees; verify them against your installed Next.js version and deployment. The optimizer has no cache invalidation mechanism, so if a source changes before its cached version expires, change the source path or clear the relevant cache through your deployment setup.

SVG is not optimized by default. If you enable SVG serving, follow the documentation’s security guidance, including content security policy and content disposition settings. The default optimizer does not forward request headers to the image origin. An authenticated image source may therefore need unoptimized delivery or a different architecture that can access the image securely.

6. Common implementation patterns

Fixed-size thumbnail

<Image src="/images/avatar.png" alt="Sam's profile" width={96} height={96} />

Remote image with responsive fill

<div className="photo">
  <Image
    src="https://images.example.com/products/chair.jpg"
    alt="Blue upholstered chair"
    fill
    sizes="(max-width: 700px) 100vw, 33vw"
    style={{ objectFit: 'cover' }}
  />
</div>
/* CSS */
.photo {
  position: relative;
  aspect-ratio: 4 / 3;
}

Keep an animated or externally optimized file unchanged

<Image
  src="https://images.example.com/animation.gif"
  alt="A cat waving"
  width={480}
  height={270}
  unoptimized
/>

7. Troubleshooting

Symptom Likely cause Fix
Remote image host is not configured The URL does not match an allowed remotePatterns entry. Add the exact protocol, hostname, port, and pathname pattern; restart the server.
Image width and height are required A remote or public path source has no intrinsic dimensions and does not use fill. Provide the source’s true dimensions, use a static import for a local asset, or use fill inside a sized, positioned parent.
Image appears too large or downloads too much data sizes is missing or does not match the layout; without it the browser assumes 100vw. Set a breakpoint-aware sizes string based on the rendered column width.
Filled image has no visible height or covers the wrong region The parent has no dimensions or positioning, or the chosen object fit is unsuitable. Give the parent a size or aspect ratio and positioning; choose cover to crop or contain to show the whole image.
Private remote image fails through the optimizer The optimizer does not forward authentication headers to the origin. Use unoptimized when browser access is appropriate, or serve through an architecture that can authenticate without exposing credentials.
SVG is refused or not transformed SVG optimization is disabled by default and SVG handling has security implications. Serve it directly where appropriate, or enable SVG only with the documented security settings.
Updated source still shows an old image The optimized result remains cached; there is no built-in cache invalidation mechanism. Use a versioned source path or clear the relevant deployment cache.
Large or redirecting source fails The response may exceed the documented 50 MB default limit or exceed the three-redirect default. Reduce the source payload or redirects, or review version-specific image configuration for the deployment.

8. Performance, reliability, and cost considerations

Choose dimensions and sizes from the actual layout: that controls whether browsers can select useful candidates without fetching an image much larger than its rendered box. Lazy loading is a sensible default for images outside the initial viewport. Reserve preload for a likely LCP image because unnecessary preloads compete for bandwidth. AVIF’s smaller output can come with slower encoding; the practical tradeoff depends on first-request encoding and subsequent cache use.

Remote origins and the image optimizer add dependencies to image delivery. Restrict accepted hosts and paths, keep source images within configured response and redirect limits, and plan source URL versioning for updates. The framework documentation gives no comparative performance benchmark or guaranteed speed or ranking improvement. Operational and hosting cost depends on where the app runs and how often distinct optimized variants are requested; measure that in your deployment.

9. Capture a page that uses Next.js Image

If you need a visual check of a rendered page, use a browser screenshot tool after the route is available. A screenshot can reveal layout, cropping, and loading-state issues at a chosen viewport; it does not replace checking network requests, accessibility, or responsive behavior across breakpoints.

A capture flow can clear common overlays before saving a page screenshot.
A capture flow can clear common overlays before saving a page screenshot.

10. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server by Yorker Media. It can capture a page as PNG, JPEG, WebP, or PDF. One GET request returns the capture:

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 docs for request options. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Learn more at ScreenshotNeo.

Sign up for 1,000 free screenshots a month, with no card required.

11. FAQ

Does Next.js Image work in both routers?

Yes. It is available through next/image in both the App Router and Pages Router. Check the reference for the router and installed Next.js version you use.

Do width and height control the display size?

No. They describe intrinsic dimensions and reserve the aspect ratio. CSS controls the rendered size.

Can the default optimizer fetch an image that requires an Authorization header?

It does not forward headers to the origin. Use an approach that can access the source securely, or disable optimization when direct browser access is appropriate.

Should every above-the-fold image be preloaded?

No. Reserve preload for a likely LCP image; eager loading or high fetch priority may fit other cases.

References