You can run a free AI image generation API on Cloudflare Workers AI with up to 100,000 requests per day—no GPU rental, no credit card, and no per-image invoice for typical side projects. This guide is the exact setup: Worker code, API key, Workers AI binding, then curl and JavaScript examples that return PNG bytes.
I kept paying for image API credits on side projects that barely shipped. Then I found Cloudflare Workers AI: a single worker that turns text prompts into images on the free tier.
No GPU needed. No monthly bill. No credit card required before you can test an idea.
What you actually get
You write a worker.js file. You paste it into a Cloudflare Worker, add an API key as an environment variable, bind Workers AI, and you are done.
| Piece | What it does |
|---|---|
| Cloudflare Worker | Receives POST requests, checks your API key, forwards the prompt |
| Workers AI | Runs the model (Stable Diffusion XL by default) |
| Your API key | Keeps random people off your 100k daily quota |
The free tier limit is 100,000 AI requests per day. For a personal app, internal tooling, or early prototypes, that is a lot of headroom. Cloudflare's pricing page has the details if you outgrow it.
Before you start
You need:
- A Cloudflare account (free is fine)
- Ten minutes and a text editor
- A secret API key you invent yourself (not your Cloudflare password)
You do not need to write new backend code unless you want to change models or add rate limiting.
Step 1: Create the worker
Open the Workers dashboard and click Create application, then Create Worker.
Name it something like free-image-generation-api. Deploy the default Hello World worker first so the URL exists. You will replace the code in the next step.
Step 2: Paste the worker code
In the worker editor, delete the Hello World snippet and paste your worker code. Here is a simple example:
export default { async fetch(request, env) { if (request.method !== "POST") { return new Response("POST only", { status: 405 }); } const apiKey = request.headers.get("Authorization"); if (apiKey !== `Bearer ${env.API_KEY}`) { return new Response("Invalid API key", { status: 401 }); } const { prompt } = await request.json(); const response = await env.AI.run("@cf/stabilityai/stable-diffusion-xl-base-1.0", { prompt: prompt, }); return new Response(response, { headers: { "content-type": "image/png" }, }); }, };
Click Save and Deploy.
Step 3: Set your API key
Go to Settings > Variables > Environment Variables.
Add one variable:
- Name:
API_KEY - Value: a long random string (a password generator works)
This is what clients send as Authorization: Bearer <key>. Treat it like a production secret. Rotate it if it leaks.
Save and deploy again.
Step 4: Enable Workers AI
In the dashboard, open Workers & Pages > AI and enable Workers AI for your account. The free tier is enough for this walkthrough.
If AI is not enabled, every request will fail with an opaque error and you will waste twenty minutes checking your API key for no reason. Ask me how I know.
Step 5: Bind Workers AI to the worker
Back in your worker: Settings > Variables, scroll to Service bindings, click Add binding.
- Variable name:
AI - Service: Workers AI
Save and deploy.
⚠️ Without this binding, the worker cannot reach Cloudflare's models. The code expects env.AI. Skip this step and nothing generates, no matter how good your prompt is.
Step 6: Note your URL
Your endpoint looks like:
https://<worker-name>.<your-subdomain>.workers.dev
The dashboard shows the exact URL. That is your image API base.

Call it from the terminal
Replace the URL and key with yours:
curl -X POST https://your-worker.your-subdomain.workers.dev \ -H "Authorization: Bearer your-secret-api-key" \ -H "Content-Type: application/json" \ -d '{"prompt": "A cute robot cooking breakfast"}' \ --output image.jpg
Open image.jpg. If you see a robot at a stove, the stack works.
Call it from JavaScript
const res = await fetch("https://your-worker.your-subdomain.workers.dev", { method: "POST", headers: { Authorization: "Bearer your-secret-api-key", "Content-Type": "application/json", }, body: JSON.stringify({ prompt: "A futuristic city in the clouds" }), }); const blob = await res.blob(); const img = document.createElement("img"); img.src = URL.createObjectURL(blob); document.body.appendChild(img);
Same pattern in Node if you use fetch or undici. The response body is the image bytes, not JSON.
Swapping models
The default in worker.js targets Stable Diffusion XL. Cloudflare adds and retires models over time, so read the comments in the file and the Workers AI model list before you change the model ID.
Smaller models are faster and cheaper against your daily quota. Larger models look better but burn through 100k faster if you expose the endpoint publicly.
Security notes that matter
- Never commit your
API_KEYto public code repositories. - Do not expose the endpoint in frontend code without a proxy. Anyone can read browser network tabs.
- If you need public access, put the worker behind your own backend or add Cloudflare rate limiting.
For internal tools and local scripts, Bearer auth in the header is fine.
When this is worth it vs paid APIs
I still use paid APIs when I need a specific fine-tuned model, guaranteed SLA, or img2img with tight control. For "generate a thumbnail from a sentence" or "prototype a feature that needs images," this setup has been enough.
100k calls per day is not infinite. A leaked key on a public repo can burn through it. Monitor usage in the Cloudflare dashboard if the endpoint leaves your laptop.
FAQ
Is there a free AI image generation API?
Yes. Cloudflare Workers AI lets you run Stable Diffusion behind a Worker endpoint with up to 100,000 free AI requests per day. You invent your own API key, bind Workers AI, and POST a text prompt to receive PNG image bytes.
Do I need a GPU or a credit card?
No. Models run on Cloudflare's infrastructure. A free Cloudflare account is enough to deploy the worker, enable Workers AI, and call the endpoint from curl or JavaScript.
How do I secure the free image API?
Store a long random API_KEY as a Worker environment variable and require Authorization: Bearer <key> on every request. Never put that key in frontend code, and add rate limiting if the URL is public.
When should I use a paid image API instead?
Use a paid API when you need a specific fine-tuned model, a guaranteed SLA, or tight img2img control. For thumbnails, prototypes, and internal tools, the Workers AI free tier is usually enough.
Wrapping up
You now have a self-hosted text-to-image API on Cloudflare's edge: no GPU rental, no per-image invoice for the first 100k daily requests. Deploy the worker, bind AI, and send a prompt.
What would you build with 100k free generations a day?

