Use Next.js’s Image component as a safer, optimized replacement for a raw <img>. Give it a local path, static import, or an allowed remote URL; provide intrinsic dimensions (or use fill); match sizes to the CSS layout; and choose loading, format, and caching settings for the image’s role. The result is responsive image selection, reserved layout space, and automatic optimization without writing your own srcset.
What the Next.js Image component does
next/image extends the HTML <img> element. Next.js can generate appropriately sized, modern-format responses, lazy-load images by default, and reserve the image’s aspect ratio to reduce cumulative layout shift. It does not determine your visual layout: CSS, the parent container, and the values you pass still decide how large an image appears.
Import it in either router:
import Image from 'next/image';
The same component API is used in the App Router and Pages Router, but configuration defaults can change between Next.js releases. Check the reference for the version installed in your project, especially when upgrading to Next.js 16.
Choose a source: local file, static import, or remote URL
Local files in public
Place an image at public/images/hero.jpg and reference it from the site root:
#1 Best Overall
<Image src="/images/hero.jpg" alt="A dashboard on a laptop" width={1600} height={900} />
The URL is public-facing; do not include the public directory in src.
Static imports
Importing an image lets Next.js read intrinsic width, height, and (when available) blur metadata at build time:
import hero from '@/public/images/hero.jpg';
export default function Hero() {
return <Image src={hero} alt="A dashboard on a laptop" />;
}
Static imports are convenient for assets shipped with your application. You can still override display size with CSS or explicit props.
Remote images
A remote URL must match an explicit remotePatterns entry. Because the file is not available during the build, supply width and height, or use fill:
<Image
src="https://images.example.com/products/camera.jpg"
alt="Mirrorless camera"
width={1200}
height={800}
/>
Configure only the protocol, hostname, port, pathname, and (when necessary) query pattern you actually use. The older domains setting is deprecated in favor of remotePatterns (since Next.js 14). A narrow pattern prevents your image endpoint from becoming an open proxy.
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.example.com',
port: '',
pathname: '/products/**'
}
]
}
};
module.exports = nextConfig;
Use localPatterns similarly when local optimization should be limited to particular paths. A permissive query-string rule can allow unintended source URLs, so omit query matching unless it is required.
Rank #2
Dimensions, fill, and layout stability
Fixed or naturally sized images
width and height describe intrinsic dimensions and preserve the source aspect ratio; they are not CSS width and height. They are required for URL sources unless you use fill. Set the rendered size with CSS:
<Image
src="/images/avatar.png"
alt="Profile photograph"
width={400}
height={400}
className="avatar"
/>
/* app.css */
.avatar { width: 4rem; height: 4rem; border-radius: 50%; }
Images that fill a container
fill makes the generated image expand to its parent. The parent must establish positioning, and the image’s fit determines whether it crops:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<div className="card-media">
<Image
src="https://images.example.com/products/camera.jpg"
alt="Mirrorless camera"
fill
sizes="(max-width: 700px) 100vw, 33vw"
style={{ objectFit: 'cover' }}
/>
</div>
.card-media { position: relative; aspect-ratio: 4 / 3; }
.card-media img { object-position: center; }
Use object-fit: cover to crop into the box or contain to show the whole source (which may leave empty space).
Responsive sizing with sizes
When CSS makes an image responsive, tell the browser its likely rendered width:
<Image
src={hero}
alt="Analytics dashboard"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 600px"
style={{ objectFit: 'cover' }}
/>
Without sizes, the browser assumes 100vw. It can therefore download a much larger candidate than a two-column card needs. Write media conditions that mirror your actual breakpoints and container widths.
Loading, LCP, placeholders, and formats
Lazy, eager, and preload
The default loading mode is lazy. Use loading="eager" only when an image must start immediately. For one clearly identified above-the-fold/LCP image, use preload. Starting with Next.js 16, priority is deprecated in favor of preload; do not mark every image as preload.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #3
<Image
src={hero}
alt="Product overview"
width={1600}
height={900}
preload
/>
Preloading several possible LCP candidates can waste bandwidth. Prefer normal lazy loading for below-the-fold content.
Blur placeholders
A blur placeholder needs a blurDataURL. Static imports can provide blur metadata in supported cases; for a remote image, generate and provide a small data URL yourself:
<Image
src="https://images.example.com/portrait.jpg"
alt="Portrait"
width={1200}
height={1600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
/>
Do not use a placeholder without a valid blur value; it will produce a runtime error.
WebP, AVIF, GIF, and SVG
WebP is the documented general-purpose choice. AVIF can produce smaller files but usually takes longer to encode, so first-request latency and cache behavior matter. Animated GIFs, very small images, and SVGs are common cases for unoptimized. SVG is not optimized by default; if you enable SVG serving, add an appropriate content-security policy and content-disposition policy for your threat model.
<Image src="/icons/animated.gif" alt="Loading" width={32} height={32} unoptimized />
Authenticated sources and custom delivery
The default optimizer does not forward authentication headers when it fetches an origin image. A URL that works in your browser with cookies or an Authorization header may fail through the optimizer. Options are:
- Expose a narrowly scoped, signed or otherwise public image URL.
- Use
unoptimizedand deliver the protected response through your own server-side route. - Use a custom loader or image service that performs authentication before returning an image.
Do not put long-lived secrets in a client-visible image URL. Keep remote hosts and paths constrained even when the origin is yours.
Optimization configuration and operational defaults
These are documented defaults/examples and should be checked against the Next.js version and deployment you run:
| Setting | Documented value or behavior | Operational meaning |
|---|---|---|
| Default quality | 75 | A starting compression quality, not a measured performance guarantee. |
| Minimum cache TTL | 4 hours (14,400 seconds) when no other directive changes it | Transformed responses can remain cached; there is no built-in cache invalidation mechanism. |
| Maximum redirects | 3 | A source chain beyond this limit fails. |
| Maximum source response body | 50 MB (50,000,000 bytes) | Larger origin responses are rejected by the optimizer. |
When a source image changes but its URL does not, a long cache lifetime can keep the old transformation. Change the source path (for example, add a content hash) or clear the relevant deployment/CDN cache. These defaults are not benchmark results and can differ with configuration.
Recommended Free Tools
Complete examples
Responsive card component
import Image from 'next/image';
export function ProductCard({ product }) {
return (
<article>
<div style={{ position: 'relative', aspectRatio: '4 / 3' }}>
<Image
src={product.image}
alt={product.name}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 320px"
style={{ objectFit: 'cover' }}
/>
</div>
<h2>{product.name}</h2>
</article>
);
}
Remote URL with explicit dimensions
export default function ArticleImage() {
return (
<Image
src="https://images.example.com/articles/next-image.jpg"
alt="Code editor showing an Image component"
width={1800}
height={1200}
sizes="(max-width: 900px) 100vw, 900px"
/>
);
}
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting checklist
“Invalid src prop” or a blocked host
Cause: the URL does not match remotePatterns (including protocol, port, pathname, or query). Fix: add the narrow pattern you need, restart the development server, and verify the final URL.
Image is stretched or layout shifts
Cause: incorrect intrinsic dimensions or CSS that overrides only one axis. Fix: use the source aspect ratio for width/height, then set both CSS dimensions or use a positioned fill parent with an explicit aspect ratio.
A card downloads an unnecessarily large file
Cause: missing or inaccurate sizes. Fix: describe the card’s real width at each breakpoint.
The remote image returns 401/403
Cause: optimizer fetches do not forward your authentication headers. Fix: use a public signed source, a server-side proxy, unoptimized, or a custom loader.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsUpdated source is not visible
Cause: a transformed response remains in cache. Fix: version the source URL or clear the deployment/CDN cache; there is no general image-cache invalidation API.
SVG or animated content behaves unexpectedly
Cause: SVG is not optimized by default and animation may be altered by processing. Fix: serve these assets with an appropriate unoptimized strategy and apply SVG security headers when enabling SVG handling.
Or skip the browser setup
If you need screenshots of a page that demonstrates your Next.js images, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one request. Its cleaner capture accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. It also provides an MCP server for Claude, Cursor, and other MCP clients with take_screenshot, get_page_info, and capture_pdf.
cURL (see the ScreenshotNeo documentation):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://nextjs.org -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://nextjs.org"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://nextjs.org' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every feature is included on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Can I use a data URL as the Image source?
The documented source choices are local paths, static imports, and remote absolute URLs. For unusual data or generated content, render it through an appropriate route or use an unoptimized image strategy rather than assuming every data URL is accepted.
Does Image automatically improve search rankings?
The component supports technical practices such as dimensions, responsive candidates, and modern formats, but the documentation does not establish a specific SEO or ranking increase.
Should every image use preload?
No. Reserve preload for one clearly identified above-the-fold or LCP candidate; normal images should remain lazy or use the default loading behavior.
Quick Recap
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.

