Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Next.js Image is the framework’s enhanced <img> component. It can optimize compatible images, reserve layout space, generate responsive candidates, lazy-load off-screen content, and integrate with local files or approved remote hosts. The correct implementation depends on where the file lives, how large it renders, whether it is authenticated, and whether it is likely to be the page’s largest contentful paint (LCP) image.

This guide covers the current App Router and Pages Router guidance available in 2026, with version-sensitive notes for Next.js 16.

Use the component in the right order

  1. Install or use an existing Next.js project.
  2. Import the component: import Image from 'next/image'.
  3. Choose a local path, static import, remote URL, or a custom loader.
  4. Provide intrinsic dimensions or use fill.
  5. Match sizes to the actual responsive layout.
  6. Configure narrowly allowed remote or local paths.
  7. Choose loading, placeholder, format, and caching behavior for the image’s role.

Local images and static imports

Files in the public directory

A file in public is addressed from the site root. For example, public/images/hero.jpg becomes /images/hero.jpg:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import Image from 'next/image'

export default function Hero() {
  return (
    <Image
      src="/images/hero.jpg"
      alt="A mountain landscape at sunrise"
      width={1600}
      height={900}
    />
  )
}

width and height describe the source image’s intrinsic aspect ratio. They reserve space and reduce layout shift; they do not force those pixels as the rendered CSS size. Use CSS or a class to control display dimensions.

Static imports

Importing an image from the project gives Next.js build-time metadata, including intrinsic dimensions and, where available, blur metadata:

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

export default function Profile() {
  return <Image src={portrait} alt="Profile portrait" />
}

Static imports are useful when assets are part of the application bundle and their dimensions are known at build time. They avoid manually repeating width and height.

Remote images

Remote files cannot be inspected during your build. Supply dimensions yourself unless you use fill, and allow the exact source with remotePatterns. The older domains option has been deprecated since Next.js 14 in favor of patterns that can constrain protocol, hostname, port, path, and query matching.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.example.com',
        port: '',
        pathname: '/catalog/**',
      },
    ],
  },
}

module.exports = nextConfig
import Image from 'next/image'

export default function Product() {
  return (
    <Image
      src="https://images.example.com/catalog/item-42.jpg"
      alt="Blue running shoe"
      width={1200}
      height={800}
    />
  )
}

Keep patterns narrow. A permissive hostname or query rule can make unintended URLs eligible for optimization. Add only hosts and paths your application actually needs. Local sources can similarly be constrained with localPatterns when you want to limit which project paths are accepted.

Responsive layouts: width, height, fill, and sizes

Fixed or known dimensions

Use intrinsic dimensions when the image has a predictable display box. CSS can scale it while preserving the ratio:

<Image
  src="/images/card.jpg"
  alt="A desk with a laptop"
  width={1200}
  height={800}
  className="cardImage"
/>
.cardImage {
  width: 100%;
  height: auto;
}

Fill a positioned parent

fill makes the image expand to its parent. The parent must establish a containing block with position: relative, fixed, or absolute:

<div className="tile">
  <Image
    src="https://images.example.com/catalog/item-42.jpg"
    alt="Blue running shoe"
    fill
    sizes="(max-width: 700px) 100vw, 33vw"
    style={{ objectFit: 'cover' }}
  />
</div>
.tile {
  position: relative;
  aspect-ratio: 4 / 3;
}

Use object-fit: cover when cropping is acceptable, or contain when the complete image must remain visible. Without a positioned parent, the fill layout will not have the intended geometry.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why sizes matters

For responsive or fill images, sizes tells the browser how wide the image will probably render at each viewport width. Without it, the browser assumes 100vw and may download a substantially larger candidate than the layout needs.

<Image
  src="/images/article.jpg"
  alt="A city skyline"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 70vw, 840px"
  style={{ objectFit: 'cover' }}
/>

Write sizes from the layout, not from the source file. If a desktop card is one third of a 1,200-pixel viewport, a value near 33vw is more accurate than 100vw.

Loading, LCP, and placeholders

Lazy loading

The documented default is lazy loading. Images outside the initial viewport are requested as they approach the viewport, reducing initial work. Use loading="eager" only when an image must be fetched immediately.

Preload for a clear hero image

For one image that is clearly above the fold and likely to be LCP, use preload. Starting with Next.js 16, priority is deprecated in favor of preload. Do not preload several competing images when the LCP candidate is uncertain; eager loading or high fetch priority may be more appropriate in some layouts.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<Image
  src="/images/home-hero.jpg"
  alt="People collaborating around a table"
  width={1920}
  height={1080}
  preload
/>

Blur placeholders

A blur placeholder requires a blurDataURL. Static imports can provide blur metadata in supported cases; remote URLs generally require you to supply the data yourself:

<Image
  src="https://images.example.com/catalog/item-42.jpg"
  alt="Blue running shoe"
  width={1200}
  height={800}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
/>

Do not use a placeholder without a usable blur data URL; the image cannot render the intended low-quality preview.

Formats and unoptimized delivery

The documentation recommends WebP for most uses. AVIF can produce smaller files but generally takes longer to encode, so the first request and subsequent cache hits can have different trade-offs. Choose based on your delivery path and cache behavior rather than assuming one format always wins.

Set unoptimized for cases where transformation is unnecessary or unsuitable, such as some animated GIFs, small images, and SVG files:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<Image
  src="/icons/mark.svg"
  alt="Company mark"
  width={96}
  height={96}
  unoptimized
/>

SVG is not optimized by default. If you enable SVG serving, apply an appropriate content security policy and content-disposition setting, because SVG can contain active content.

Authentication, headers, and custom loaders

The default image optimizer does not forward authentication headers when it fetches a source image. A private origin that requires a bearer token or session cookie may therefore fail. Options include making a properly secured public transformation endpoint, using unoptimized with a URL your browser can authenticate against, or implementing a custom loader that fits your architecture. Do not expose origin credentials in client-side code.

A custom loader is also useful when images already live behind a transformation or CDN service. Keep the loader’s URL construction deterministic and continue validating source hosts and paths.

Cache and operational defaults

  • The documented default image quality is 75.
  • When no other configuration or upstream cache directive changes it, the default minimum cache TTL is four hours (14,400 seconds).
  • The optimizer follows up to three redirects by default.
  • The documented default maximum source response body is 50 MB (50,000,000 bytes).
  • There is no documented cache-invalidation mechanism. With a long TTL, change the source path or clear the relevant cache when replacing an image.

These are documented defaults and examples; verify them against the Next.js version and deployment you install. Large originals, redirect chains, and frequently changing URLs increase origin and transformation work.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common errors and fixes

“Invalid src prop” for a remote URL

Cause: the host, protocol, port, pathname, or query does not match remotePatterns.
Fix: add the narrow pattern that describes the actual URL, restart the development server, and avoid a catch-all rule.

Missing width and height

Cause: a URL source has no intrinsic metadata and does not use fill.
Fix: provide the source dimensions, use a static import, or redesign the box with a positioned parent and fill.

Image is cropped or overflows

Cause: the parent has the wrong dimensions or object-fit does not match the desired behavior.
Fix: set an explicit parent aspect ratio or height, ensure the parent is positioned, then choose cover or contain.

Downloads are much larger than the card

Cause: missing or inaccurate sizes; the browser falls back to 100vw.
Fix: describe the real rendered width at mobile, tablet, and desktop breakpoints.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Private image returns 401 or 403

Cause: the default optimizer does not forward origin authentication headers.
Fix: use a secure public image endpoint, a suitable custom loader, or an architecture that can safely deliver the asset without relying on forwarded client secrets.

Updated source is not visible

Cause: a cached optimized response remains valid under the configured TTL.
Fix: change the source filename or URL, clear the applicable cache, or use a shorter TTL when frequent replacement is required.

Remote fetch fails or times out

Cause: the origin is unavailable, too large, redirects excessively, or blocks the optimizer.
Fix: test the source directly, remove unnecessary redirects, keep the response below the documented 50 MB default, and consider a controlled transformation endpoint.

Complete examples

Article card grid

import Image from 'next/image'

export function Card({ image, title }) {
  return (
    <article>
      <div className="cardMedia">
        <Image
          src={image}
          alt=""
          fill
          sizes="(max-width: 700px) 100vw, (max-width: 1100px) 50vw, 33vw"
          style={{ objectFit: 'cover' }}
        />
      </div>
      <h2>{title}</h2>
    </article>
  )
}
.cardMedia {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
}

Remote source with a fixed ratio

<Image
  src="https://images.example.com/catalog/item-42.jpg"
  alt="Blue running shoe"
  width={1200}
  height={800}
  sizes="(max-width: 700px) 100vw, 600px"
  style={{ width: '100%', height: 'auto' }}
/>

Or skip the browser setup

If your goal is a clean screenshot of a rendered Next.js page rather than an in-app image component, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the ScreenshotNeo documentation for all options, including viewport and device presets, full-page capture, selector capture, dark mode, custom CSS and JavaScript, request blocking, cookies, headers, geolocation, signed links, asynchronous jobs, bulk capture, and PDF output.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

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)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

FAQ

Does width and height control the displayed size?

No. They communicate intrinsic dimensions and reserve aspect-ratio space. CSS controls the rendered size.

Can I use a remote URL without configuration?

No. The host and path must match an allowed remotePatterns entry, unless you use another supported delivery architecture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should every image use preload?

No. Reserve preload for a clear above-the-fold or LCP candidate; ordinary images should normally remain lazy.

When is fill preferable?

Use it when the image must occupy a parent-defined box, such as a card thumbnail or hero background. The parent must be positioned and have meaningful dimensions.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.