<!-- Markdown twin of https://pixelvault.dev/blog/host-ai-generated-images -->

[← Back to blog](/blog)

By [PixelVault](/about) July 4, 2026

# How to host AI-generated images

The image your model just generated lives at a URL that expires in about an hour — or comes back as raw base64 with nowhere to go. Here's how to turn any generated image into a permanent CDN URL with a single API call.

You call the DALL·E or GPT Image API, get back a URL, drop it in your app — and an hour later it's a broken image. This surprises almost everyone the first time. The URLs image-generation APIs hand you are **short-lived by design**: OpenAI's image URLs expire roughly 60 minutes after generation. If you want the image to stick around, hosting it is _your_ job.

The usual advice — "download it and upload it to S3" — means IAM policies, a bucket, a CDN in front, and egress bills for every view. That's a lot of yak-shaving to make one generated image durable. Here's the lean version instead.

## The fix: grab the bytes, upload once

Fetch the generated image before its URL expires, then hand the bytes to PixelVault in a single POST. You get back a permanent CDN URL — no S3 bucket, no CloudFront distribution, no egress bill to wire up.

curl Node Python

\# DALL·E / GPT Image gave you a URL that dies in ~1 hour.  
\# 1. Grab the bytes before it expires:  
curl \-s \-o gen.png "https://oaidalleapiprodscus.blob.core.windows.net/.../gen.png"  
  
\# 2. Upload to PixelVault — permanent CDN URL back:  
curl \-s \-X POST https://api.pixelvault.dev/v1/images \\  
  \-H "Authorization: Bearer pv\_live\_xxx" \\  
  \-F "file=@gen.png" | jq \-r '.data.url'  
  
\# → https://img.pixelvault.dev/proj\_abc/img\_xyz.png — permanent URL

That returned URL is served from a global edge CDN, has zero egress fees, and is a permanent, immutable URL. Register once for an API key, and re-hosting each new generation is one upload call.

## When your model returns base64, not a URL

GPT Image can return `b64_json`, and local Stable Diffusion pipelines hand you raw bytes. There's nothing to download — you already have the image. Decode it and upload the bytes directly:

Node

\# Some models return base64 instead of a URL (e.g. GPT Image, Stable Diffusion).  
\# Send the bytes straight to PixelVault — no temp file, no S3 setup.  
const b64 = gen.data\[0\].b64\_json;  
const bytes = Buffer.from(b64, "base64");  
  
const form = new FormData();  
form.append("file", new Blob(\[bytes\], { type: "image/png" }), "gen.png");  
  
const res = await fetch("https://api.pixelvault.dev/v1/images", {  
  method: "POST",  
  headers: { "Authorization": \`Bearer ${process.env.PIXELVAULT\_API\_KEY}\` },  
  body: form,  
});  
const { url } = (await res.json()).data; // permanent CDN URL

## Works with every generator

The pattern is the same whichever model you use — download the bytes if you got a URL, upload them directly if you already have them:

-   **DALL·E 3 / GPT Image (OpenAI).** URLs expire in ~1 hour, or use `b64_json`. Re-host either way.
-   **Midjourney.** CDN links can rot and are tied to your account. Persist the ones you want to keep under your own URL.
-   **Flux / Nano Banana (via Replicate, fal, etc.).** Output URLs on inference hosts are temporary — re-host on generation.
-   **Stable Diffusion (local or hosted).** Raw bytes out; upload them directly and get a shareable link back.

## Why this matters for AI agents

If an agent is generating images — thumbnails, mockups, marketing assets — a URL that expires in an hour is useless downstream. The agent needs a durable link it can put in a PR, a doc, or a database. Because PixelVault registration and upload are both plain API calls, an agent can [host a generated image with no browser and no human](/blog/image-hosting-for-ai-agents) in the loop. It's the same two calls, just made by the model instead of you.

## Free to start

PixelVault's free tier includes 200 MB storage, 500 uploads/month, and 1 GB bandwidth — no credit card, no trial expiry. Enough to persist a lot of generated images before you pay a cent. Paid plans start at [$9/month](/pricing).

[Read the API docs →](/docs)
