English
English
Appearance
English
English
Appearance
Transform and optimize images served from IPFS on-the-fly using query parameters. This is a public endpoint that requires no authentication.
GET https://api.ipfs.ninja/image/:cid
Returns the image at the given CID, transformed according to the provided query parameters. If no transform parameters are supplied, the request 302-redirects to the original image on the IPFS gateway.
| Parameter | Type | Required | Description |
|---|---|---|---|
cid | string | Yes | The IPFS content identifier of the image. |
| Parameter | Type | Default | Description |
|---|---|---|---|
w | integer | — | Output width in pixels. Range: 1–4096. Values ≤ 0 or non-numeric are ignored. |
h | integer | — | Output height in pixels. Range: 1–4096. Values ≤ 0 or non-numeric are ignored. |
format | string | — | Output format: webp, jpeg, png, or avif. Case-sensitive (lowercase). Unknown values are ignored. |
quality | integer | 80 | Compression quality, 1–100. Applies to webp, jpeg, and avif only. png is lossless and ignores this. |
fit | string | cover | How the image should fit the dimensions: cover, contain, fill, inside, or outside. |
Note: the parameter is
quality, notq. Common shorthand aliases (q,width,height,fmt) are not recognized.
A request that supplies none of w, h, or format is treated as a no-op and 302-redirects to the original image. quality and fit alone do not trigger a transform.
| Mode | Behavior |
|---|---|
cover | Crop to cover both dimensions (default). |
contain | Fit within both dimensions, preserving aspect ratio. May leave empty space (transparent or black depending on format). |
fill | Stretch to fill both dimensions exactly. May distort the image. |
inside | Like contain, but only scales down, never up. |
outside | Like cover, but only scales down, never up. |
The transformer never enlarges an image beyond its source dimensions. If you request w=2000 for a 1200px-wide source, the output will be 1200px wide. This applies to all fit modes.
| Status | When | Body |
|---|---|---|
200 | Transform produced on this request. | Binary image bytes. Content-Type matches the requested format. |
302 | No transform params supplied, or a previously transformed result is already cached. | Location header points to the original image or the cached result on https://ipfs.ninja/image-cache/.... |
400 | cid path parameter missing. | { "error": "cid required" } |
404 | CID not found on the gateway. | { "error": "CID not found" } |
500 | Unexpected error (corrupt image, transform failure, etc.). | { "error": "<message>" } |
All 200 and 302-cache responses are served with Cache-Control: public, max-age=31536000, immutable. See Caching below.
Resize to 400px wide, convert to WebP:
curl "https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=400&format=webp"Resize and crop to 200×200 thumbnail as JPEG at 60% quality:
curl "https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=200&h=200&format=jpeg&quality=60&fit=cover"Square thumbnail with letterboxing instead of cropping:
curl "https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=200&h=200&format=png&fit=contain"Convert format only, no resize (useful for serving AVIF/WebP versions of legacy JPEGs):
curl "https://api.ipfs.ninja/image/QmXmCX9S6ANV...?format=avif&quality=70"Cap maximum width without forcing height (preserves aspect ratio):
curl "https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=1200&format=webp"Reference optimized images directly in img tags:
<img
src="https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=webp&quality=75"
alt="Optimized IPFS image"
/>Serve different sizes with srcset:
<img
srcset="
https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=400&format=webp 400w,
https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=webp 800w,
https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=1200&format=webp 1200w
"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
src="https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=webp"
alt="Responsive IPFS image"
/>Modern format negotiation with <picture> (AVIF → WebP → JPEG fallback):
<picture>
<source
type="image/avif"
srcset="https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=avif&quality=60"
/>
<source
type="image/webp"
srcset="https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=webp&quality=75"
/>
<img
src="https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=800&format=jpeg&quality=80"
alt="IPFS image with format fallback"
/>
</picture>CSS background-image:
.hero {
background-image: url("https://api.ipfs.ninja/image/QmXmCX9S6ANV...?w=1600&format=webp&quality=70");
}As a custom loader for next/image:
// loaders/ipfs.js
export default function ipfsLoader({ src, width, quality }) {
return `https://api.ipfs.ninja/image/${src}?w=${width}&format=webp&quality=${quality || 75}`;
}import Image from "next/image";
import ipfsLoader from "@/loaders/ipfs";
<Image
loader={ipfsLoader}
src="QmXmCX9S6ANV..."
alt="IPFS image"
width={800}
height={600}
/>;Responses are served with Cache-Control: public, max-age=31536000, immutable. Since IPFS content is content-addressed, the same CID with the same parameters always produces the same output, so browsers and CDNs can cache responses indefinitely.
Cached transforms are stored in S3 keyed by the full parameter set (cid, w, h, format, quality, fit). Subsequent requests with the same parameters return a 302 redirect to the CloudFront-fronted cache (https://ipfs.ninja/image-cache/...) rather than re-running the transform. Different parameter combinations produce different cache entries.
Image optimization is available on all plans, including the free Dharma plan.