Placeholder Image Services: The Complete Developer Guide
A placeholder image is a temporary stand-in — a sized rectangle that holds layout space while real assets are still in production. Every frontend developer reaches for one sooner or later, and the service you pick determines whether your mockup looks like a wireframe or something you can actually show a stakeholder.
This guide covers the four major placeholder image services, how to use each one in HTML, CSS, and JavaScript, and how to swap real images in at production dimensions using Pixotter's resize tool.
Why Placeholder Images Matter
Placeholder images solve a real problem: you are building a layout before the real photography, illustration, or product images exist. Without placeholders, you have two bad options — leave blank space that makes the design look broken, or use your own test images that may have wrong dimensions.
Good placeholder services give you:
- Exact dimensions on demand (no resizing needed in CSS)
- Realistic image content for visual fidelity (photo services)
- Custom colors and text for design annotations
- HTTPS by default (no mixed-content warnings)
- No rate limits for development traffic
The wrong service gives you HTTP-only URLs that break staging environments, limited size options, or placeholder text baked into images that confuses clients.
Try it yourself
Reduce file size without visible quality loss — free, instant, no signup. Your images never leave your browser.
The Four Services Worth Knowing
1. picsum.photos (Lorenzo Nicora, MIT License)
The best-looking option. Picsum serves real photographs from Unsplash, sized to any dimension you request. Your mockup looks like finished work instead of a grey box.
https://picsum.photos/800/600
Request a specific image by ID (stable across requests — useful for consistent mockups):
https://picsum.photos/id/237/800/600
Grayscale for wireframe-style mockups:
https://picsum.photos/800/600?grayscale
Blur (1–10):
https://picsum.photos/800/600?blur=2
Random vs. stable: Without an ID, picsum returns a random image on every request. This looks great in a gallery mockup but breaks screenshot-based visual regression tests. Use /id/{n}/ for stable, reproducible images.
Caveats: picsum does not support custom text overlays. If your design needs dimension labels or placeholder labels visible in the image, pick placehold.co instead.
2. placehold.co (Free, no affiliation required)
The most flexible option. placehold.co generates text-annotated placeholders with custom colors, fonts, and dimensions. Good when you need to label sections or annotate dimensions for handoff.
https://placehold.co/800x600
Custom colors (hex, without the #):
https://placehold.co/800x600/1a1a2e/ffffff
Custom text:
https://placehold.co/800x600?text=Product+Image
Retina (2x) — append @2x:
https://placehold.co/400x300@2x/png
Format support: PNG (default), JPEG, WebP, SVG, GIF. The SVG format is vector — it scales without pixelation at any screen density. Useful for prototyping.
3. placeholder.com (placeholder.com)
The classic. Simple URL scheme, instant gray boxes with dimension labels, no setup. It has been around since 2012 and loads fast on a CDN.
https://via.placeholder.com/800x600
Custom background and text color:
https://via.placeholder.com/800x600/3d5a80/ffffff
Custom text:
https://via.placeholder.com/800x600?text=Hero+Banner
Format support: PNG, GIF, JPEG, WebP. Request with extension:
https://via.placeholder.com/800x600.webp
Note on HTTPS: HTTPS is supported. Always use https:// — some older documentation shows HTTP URLs.
4. dummyimage.com
Functionally similar to placeholder.com but with a slightly different URL scheme. Useful as a fallback if placeholder.com is rate-limiting during CI builds.
https://dummyimage.com/800x600/cccccc/000000
Format in URL:
https://dummyimage.com/800x600/cccccc/000000.png
Service Comparison
| Service | URL Pattern | Photo Content | Custom Text | HTTPS | SVG | Max Size | License |
|---|---|---|---|---|---|---|---|
| picsum.photos | /800/600 |
Yes (real photos) | No | Yes | No | 5000×5000 | MIT |
| placehold.co | /800x600 |
No | Yes | Yes | Yes | 4000×4000 | Free to use |
| placeholder.com | /800x600 |
No | Yes | Yes | No | 4000×4000 | Free to use |
| dummyimage.com | /800x600/hex/hex |
No | Yes | Yes | No | 4000×4000 | Free to use |
Which to pick:
- Showing to stakeholders or doing visual testing → picsum.photos (real photos, believable content)
- Need labeled sections or annotated dimensions → placehold.co (text overlays, SVG option)
- Just need fast gray boxes for internal development → placeholder.com (simple, reliable)
- CI/CD fallback → dummyimage.com (good uptime, alternative URL scheme)
Using Placeholder Images in Code
HTML <img> tag
<!-- Real photo, fixed dimensions -->
<img src="https://picsum.photos/800/600" alt="Product image placeholder" width="800" height="600">
<!-- Stable image (won't change on reload) -->
<img src="https://picsum.photos/id/237/400/300" alt="Dog placeholder" width="400" height="300">
<!-- Annotated placeholder for wireframe -->
<img src="https://placehold.co/800x400?text=Hero+Banner" alt="Hero banner placeholder" width="800" height="400">
Always include width and height attributes. This prevents layout shift (CLS) while the placeholder loads — important even for development builds where you want accurate measurements to carry over to production.
Responsive images with srcset
<img
src="https://picsum.photos/800/600"
srcset="
https://picsum.photos/400/300 400w,
https://picsum.photos/800/600 800w,
https://picsum.photos/1200/900 1200w
"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
alt="Product image placeholder"
width="800"
height="600"
>
Using stable IDs keeps this consistent across page reloads:
<img
src="https://picsum.photos/id/10/800/600"
srcset="
https://picsum.photos/id/10/400/300 400w,
https://picsum.photos/id/10/800/600 800w,
https://picsum.photos/id/10/1200/900 1200w
"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
alt="Forest placeholder"
width="800"
height="600"
>
CSS background-image
/* Hero section placeholder */
.hero {
background-image: url('https://picsum.photos/1920/1080');
background-size: cover;
background-position: center;
width: 100%;
height: 600px;
}
/* Card thumbnail placeholder */
.card-thumbnail {
background-image: url('https://placehold.co/400x300/e2e8f0/94a3b8?text=Card+Image');
background-size: cover;
background-position: center;
width: 400px;
height: 300px;
}
Using CSS custom properties for easy swapping:
:root {
/* Swap this one variable to switch from placeholder to real image */
--hero-image: url('https://picsum.photos/id/1015/1920/1080');
}
.hero {
background-image: var(--hero-image);
background-size: cover;
background-position: center;
}
When the real image is ready, update the custom property. One change, reflected everywhere.
JavaScript / Fetch
Loading a placeholder image and inserting it dynamically:
// Vanilla JS — no external dependencies required
async function insertPlaceholder(container, width, height) {
const url = `https://picsum.photos/${width}/${height}`;
const img = document.createElement('img');
img.src = url;
img.width = width;
img.height = height;
img.alt = 'Placeholder image';
img.loading = 'lazy'; // defer off-screen placeholders
container.appendChild(img);
}
// Usage
const gallery = document.getElementById('photo-gallery');
for (let i = 0; i < 9; i++) {
insertPlaceholder(gallery, 400, 300);
}
For a grid of stable, unique images using picsum's list API:
async function loadPlaceholderGrid(container, count = 9) {
// picsum.photos/v2/list returns an array of photo objects
const response = await fetch(`https://picsum.photos/v2/list?page=1&limit=${count}`);
const photos = await response.json();
photos.forEach(photo => {
const img = document.createElement('img');
img.src = `https://picsum.photos/id/${photo.id}/400/300`;
img.width = 400;
img.height = 300;
img.alt = `Photo by ${photo.author}`;
img.loading = 'lazy';
container.appendChild(img);
});
}
loadPlaceholderGrid(document.getElementById('gallery'));
React component
// PlaceholderImage.jsx
// React 18.x — no external image library required for basic usage
function PlaceholderImage({ width, height, id, text, className }) {
const src = id
? `https://picsum.photos/id/${id}/${width}/${height}`
: text
? `https://placehold.co/${width}x${height}?text=${encodeURIComponent(text)}`
: `https://picsum.photos/${width}/${height}`;
return (
<img
src={src}
width={width}
height={height}
alt={text || 'Placeholder image'}
className={className}
loading="lazy"
/>
);
}
// Usage
<PlaceholderImage width={800} height={600} id={237} />
<PlaceholderImage width={400} height={300} text="Product Photo" />
Need exact dimensions for production?
Drop your image into Pixotter, set the exact size, and download — free, no upload, runs in your browser.
Swapping Placeholders for Real Images
The whole point of placeholder images is that they go away. Here is how to make that swap smooth.
Step 1: Know your target dimensions before you start
Placeholders lock in your layout dimensions. Before you write picsum.photos/800/600, confirm those are the actual production dimensions — not rough estimates. If your real product image will be 1200×900, use picsum.photos/1200/900 as the placeholder. Mismatched dimensions cause layout shift when you swap.
Check your design system. Common standard sizes:
| Context | Common Dimensions |
|---|---|
| Hero banner (desktop) | 1920×1080, 1440×810 |
| Product card thumbnail | 400×400, 600×400 |
| Blog post header | 1200×630 |
| Open Graph / social share | 1200×630 |
| Avatar / profile photo | 200×200, 400×400 |
| Sidebar widget | 300×250 |
If you are unsure what size the real image should be, read image size for website for a complete breakdown by context.
Step 2: Resize real images to exact dimensions
When the real images arrive from your designer or photographer, they almost never match exactly. A raw photo is 3000×2000. Your layout needs 1200×630. Cropping and resizing those to exact spec before deploying prevents the most common CLS-related performance regressions.
Pixotter's resize tool handles this client-side — no upload, no account. Drop the image, set 1200×630, choose fit mode (cover crop vs. contain with letterbox), download. Processed in your browser using WASM.
If you are converting formats at the same time — raw JPEG to WebP, for example — use Pixotter's convert tool after resizing, or do both in one step. For high-traffic images where file size matters, run through the compress tool after.
Step 3: Replace the URL, keep the attributes
When swapping:
<!-- Before: placeholder -->
<img src="https://picsum.photos/id/237/800/600" alt="Dog placeholder" width="800" height="600">
<!-- After: real image, same dimensions, update alt text -->
<img src="/images/product-hero.webp" alt="Pixotter interface showing image compression" width="800" height="600">
The width and height attributes stay the same — that is the whole point of using placeholder images at correct dimensions. The only things that change are src and alt.
Using Placeholder Images in Figma and Design Tools
Most design tools can pull placeholder images directly into frames:
Figma: Use the Unsplash plugin (built by Figma, free). It pulls real photos at exact frame dimensions. Same photographic realism as picsum, direct in the canvas.
Framer: Built-in placeholder system auto-fills frames with stock photography at the correct aspect ratio.
Storybook: Use the @storybook/addon-backgrounds package (Storybook 8.x) and pass placeholder URLs as story args for visual regression testing.
Performance Considerations
Placeholder images are temporary, but they still affect development and staging performance:
Avoid using placeholder images in production even for a day. External service dependencies are a single point of failure — if picsum.photos has a brief outage, your production site shows broken images. Always swap to locally-hosted or CDN-hosted real images before deploying to production.
Lazy loading: Add loading="lazy" to placeholder images below the fold. This applies during development too — it prevents browser DevTools from showing 40 image requests on first load, which makes performance profiling harder.
Image format for placeholders: picsum returns JPEG by default. placehold.co returns PNG. The format difference rarely matters in development, but if you want to test how your layout handles WebP specifically, placehold.co supports .webp extension in the URL.
For a deeper look at which formats matter and when, see what is image resolution and best image format for web.
FAQ
What is a placeholder image? A placeholder image is a temporary image used in web development or design mockups to fill layout space before real images are ready. It has specific dimensions that match the final design, so the layout is accurate during development.
Which placeholder image service is the best? picsum.photos for realistic-looking mockups (uses real photos). placehold.co if you need custom text, colors, or SVG format. placeholder.com for the simplest URL scheme with no setup. All three are free and HTTPS-only.
Can I use placeholder images in production? No. Placeholder services are for development and staging only. They are external dependencies — an outage at the service breaks your site. Always swap to self-hosted or CDN-hosted images before going live.
How do I prevent layout shift when swapping placeholder images?
Always specify width and height attributes on your <img> tags, and use placeholder images at the exact dimensions of the final image. When you swap src, the browser already knows the dimensions and does not need to recalculate layout.
What size should my placeholder images be? The same size as your final production images. Check your design specs first. Common sizes: 1200×630 for blog headers and OG images, 400×400 for product thumbnails, 1920×1080 for hero banners. See image size for website for a full reference.
Does picsum.photos cost money? No. picsum.photos is free and open source (MIT license). It is hosted and maintained by Lorenzo Nicora and contributors. For high-traffic applications where you need SLA guarantees, self-host it — the source code is on GitHub.
How do I get a stable (non-random) placeholder image from picsum?
Use the ID-based URL: https://picsum.photos/id/237/800/600. The ID stays consistent across requests. Browse available IDs and their images at picsum.photos/images.
Can I use placeholder images in CSS background-image?
Yes. Use the full URL in your CSS: background-image: url('https://picsum.photos/1920/1080'). For predictable results in staging environments, use an ID-based URL so the image does not change between builds.
Quick Reference
# Real photos (random)
https://picsum.photos/{width}/{height}
# Real photos (stable)
https://picsum.photos/id/{id}/{width}/{height}
# Real photos (grayscale)
https://picsum.photos/{width}/{height}?grayscale
# Color blocks with text
https://placehold.co/{width}x{height}
https://placehold.co/{width}x{height}/{bg-hex}/{text-hex}
https://placehold.co/{width}x{height}?text=Your+Label
# Classic gray boxes
https://via.placeholder.com/{width}x{height}
https://via.placeholder.com/{width}x{height}/{bg-hex}/{text-hex}
# Dummyimage fallback
https://dummyimage.com/{width}x{height}/{bg-hex}/{text-hex}
When the real images are ready: resize them to exact spec with Pixotter's resize tool, convert to WebP with the convert tool, compress for production with the compress tool, and swap the src. Three tools, one tab, no upload.
Try it yourself
Resize to exact dimensions for any platform — free, instant, no signup. Your images never leave your browser.