Placeholder Image API Documentation

A free, open-access placeholder image API — no sign-up, no API key, no rate limit. Generate placeholder images for any size, color, text, font, and format directly via URL.

Free Forever No API Key CORS: * Global CDN Cache-Control: 1yr

Base URL

https://placeholderimage.co/

URL Structure

Full syntax
/{width}x{height}[@2x|@3x]/{bg-color}/{text-color}[.format|/format]?text={label}&font={font}
Segment Required Description Example
{width}x{height} Yes Image dimensions in pixels. Height optional (defaults to width = square). Range: 10–4000. 600x400 or 400
@2x / @3x No Retina multiplier. Appended directly to the size. All formats supported. 600x400@2x
{bg-color} No Background color as HEX (3/6/8-digit) or CSS color name. Default: cccccc. 1c1c1e or coral
{text-color} No Text color. Must be used together with bg-color. Auto-calculated if omitted. 22c55e or white
.format / /format No Output format. Can be file extension or path segment. Default: svg. .png or /webp
?text= No Custom label text. Use + for spaces, \n for line breaks. Default: WxH. ?text=Hello+World
?font= No Font family. Use hyphenated names. Default: lato. ?font=playfair-display

Response Headers

Content-Type: image/svg+xml (or image/png, image/jpeg, etc.)
Cache-Control: public, max-age=31536000, immutable
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff

Supported Formats

SVG .svg
Default. Scalable vector. Perfect for all sizes. Smallest file size.
image/svg+xml
PNG .png
Lossless raster. Supports transparency.
image/png
JPEG .jpg
Lossy compressed. Best for photographs.
image/jpeg
WebP .webp
Modern format. Smaller than PNG/JPEG.
image/webp
AVIF .avif
Next-gen format. Best compression. CF Pages fallback to PNG.
image/avif
GIF .gif
Legacy format. CF Pages fallback to PNG.
image/gif

Available Fonts

Live API Examples

Basic placeholder image — 600×400 SVG, default gray
Basic placeholder image — 600×400 SVG, default gray
https://placeholderimage.co/600x400
Square placeholder — 400×400 SVG
Square placeholder — 400×400 SVG
https://placeholderimage.co/400
Custom background and text color
Custom background and text color
https://placeholderimage.co/600x400/1c1c1e/22c55e
CSS color names with custom text
CSS color names with custom text
https://placeholderimage.co/600x400/coral/white?text=Error
Transparent background — SVG/PNG only
Transparent background — SVG/PNG only
https://placeholderimage.co/600x400/transparent/333333
PNG format via path segment
PNG format via path segment
https://placeholderimage.co/600x400/1c1c1e/22c55e/png
PNG format via path segment
PNG format via path segment
https://placeholderimage.co/600x400/1c1c1e/22c55e/png
Retina @2x — outputs 600×600 PNG
Retina @2x — outputs 600×600 PNG
https://placeholderimage.co/300x300@2x/1c1c1e/22c55e/png
Custom text and font
Custom text and font
https://placeholderimage.co/600x400?text=Hello+World&font=playfair-display
Multi-line text using \n
Multi-line text using \n
https://placeholderimage.co/600x400?text=Line+One%5CnLine+Two

Code Examples

HTML
<!-- Basic placeholder image -->
<img
  src="https://placeholderimage.co/600x400"
  width="600"
  height="400"
  alt="placeholder image"
/>

<!-- Custom color and text -->
<img
  src="https://placeholderimage.co/600x400/1c1c1e/22c55e?text=My+Project"
  width="600"
  height="400"
  alt="custom placeholder"
/>
React
// Standard img tag
function PlaceholderImg({ width = 600, height = 400 }) {
  return (
    <img
      src={`https://placeholderimage.co/${width}x${height}`}
      width={width}
      height={height}
      alt="placeholder image"
    />
  );
}

// With fallback on error
function SafeImg({ src, fallbackSize = "400x300" }) {
  return (
    <img
      src={src}
      onError={(e) => {
        e.target.src = `https://placeholderimage.co/${fallbackSize}`;
      }}
      alt="image"
    />
  );
}
Next.js
import Image from 'next/image';

// Using as placeholder src
export default function Card() {
  return (
    <Image
      src="https://placeholderimage.co/600x400/0f172a/22c55e"
      width={600}
      height={400}
      alt="placeholder image"
    />
  );
}

// next.config.js — allow external domain
module.exports = {
  images: {
    remotePatterns: [{
      protocol: 'https',
      hostname: 'placeholderimage.co',
    }],
  },
};
Vue
<template>
  <!-- Basic placeholder -->
  <img
    :src="`https://placeholderimage.co/${width}x${height}`"
    :width="width"
    :height="height"
    alt="placeholder image"
  />
</template>

<script setup>
defineProps({
  width: { type: Number, default: 600 },
  height: { type: Number, default: 400 },
});
</script>
CSS
/* Background placeholder image */
.placeholder-bg {
  background-image: url('https://placeholderimage.co/1200x400/EEEEEE/31343C.svg');
  background-size: cover;
  background-position: center;
  width: 100%;
  height: 400px;
}

/* CSS-only skeleton loader */
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
Tailwind CSS
<!-- Placeholder with Tailwind -->
<img
  src="https://placeholderimage.co/800x400"
  class="w-full h-48 object-cover rounded-lg"
  alt="placeholder image"
/>

<!-- Responsive placeholder card -->
<div class="bg-gray-100 rounded-lg overflow-hidden">
  <img
    src="https://placeholderimage.co/600x400/EEEEEE/31343C"
    class="w-full aspect-video object-cover"
    alt="placeholder"
  />
  <div class="p-4">
    <div class="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
    <div class="h-3 bg-gray-200 rounded w-1/2"></div>
  </div>
</div>
Flutter
// Basic network placeholder image
Image.network(
  'https://placeholderimage.co/400x300/1c1c2e/22c55e',
  width: 400,
  height: 300,
  fit: BoxFit.cover,
  loadingBuilder: (context, child, progress) {
    if (progress == null) return child;
    return Container(
      color: Colors.grey[200],
      child: const Center(child: CircularProgressIndicator()),
    );
  },
)
Angular
<!-- app.component.html -->
<img
  [src]="'https://placeholderimage.co/' + width + 'x' + height"
  [attr.width]="width"
  [attr.height]="height"
  alt="placeholder image"
  (error)="onImgError($event)"
/>

<!-- app.component.ts -->
export class AppComponent {
  width = 600;
  height = 400;

  onImgError(event: Event) {
    (event.target as HTMLImageElement).src =
      'https://placeholderimage.co/400x300';
  }
}
WordPress / PHP
<?php
// Functions.php — filter to add placeholder when no featured image
function placeholder_image_fallback($html, $post_id) {
    if (empty($html)) {
        $width  = 800;
        $height = 450;
        $html   = '<img src="https://placeholderimage.co/'
                . $width . 'x' . $height
                . '/EEEEEE/31343C" width="'
                . $width . '" height="' . $height
                . '" alt="placeholder image" />';
    }
    return $html;
}
add_filter('post_thumbnail_html', 'placeholder_image_fallback', 10, 2);
?>
Markdown
<!-- Standard markdown image -->
![placeholder image](https://placeholderimage.co/600x400)

<!-- With custom color and text -->
![custom placeholder](https://placeholderimage.co/600x400/0f172a/22c55e?text=My+Blog)

<!-- GitHub README banner -->
![banner](https://placeholderimage.co/1200x300/1c1c1e/22c55e?text=Project+Name)
Shopify / Liquid
{% comment %} Product card with placeholder fallback {% endcomment %}
{% if product.featured_image %}
  <img
    src="{{ product.featured_image | img_url: '400x400' }}"
    alt="{{ product.title }}"
    width="400" height="400"
  />
{% else %}
  <img
    src="https://placeholderimage.co/400x400/f3f4f6/374151?text=No+Image"
    alt="{{ product.title }}"
    width="400" height="400"
  />
{% endif %}
Python / requests
import requests

# Fetch a PNG placeholder image
url = "https://placeholderimage.co/600x400/1c1c1e/22c55e.png"
response = requests.get(url)

with open("placeholder.png", "wb") as f:
    f.write(response.content)

print("Downloaded:", response.headers["Content-Type"])
# → image/png

API FAQ

Do I need an API key?
No. PlaceholderImage.co is a free, open-access API. Simply construct the URL and use it directly — no registration, no API keys, no rate limit headers required.
What CORS headers does the API return?
All responses include Access-Control-Allow-Origin: * so you can use placeholder image URLs directly from any domain, including client-side JavaScript and front-end frameworks.
Are images cached?
Yes. All generated images are served with Cache-Control: public, max-age=31536000, immutable, meaning they are cached by browsers and CDN edges for up to 1 year. This ensures extremely fast delivery for repeat requests.
Can I use this API in production?
Yes. The service is built on Cloudflare Pages with global edge delivery, making it suitable for production use. For very high-traffic applications, consider self-hosting using the open-source codebase.

Related

Copied!