Cloudflare Workers AI proxy with OpenAI-compatible /v1/models, /v1/chat/completions, and /v1/images/generations APIs.
This project turns Cloudflare Workers AI into a lightweight OpenAI API compatible service for OpenAI SDK clients, Cherry Studio, Chatbox, AI gateways, browser apps, and server-side tools.
- Features
- Supported Endpoints
- Deploy
- Configuration
- Use With OpenAI SDK
- HTTP Examples
- Model Compatibility
- Security
- Limitations
- Thanks
- License
- ⚡ Fast serverless proxy: runs on Cloudflare Workers, close to users, with no database and no persistent runtime dependency.
- 🔌 OpenAI-compatible API: supports
/v1/models,/v1/chat/completions, and/v1/images/generations. - 🧠 Dynamic Workers AI model discovery: reads Cloudflare
ai/models/searchinstead of hardcoding model lists. - 🧩 Schema-aware image model filtering: uses Cloudflare
ai/models/schemato expose prompt-only image generation models. - 🎨 Image generation support: handles JSON image models and multipart transport image models such as Flux-style Workers AI models.
- 🌊 Streaming compatibility: normalizes streaming chat chunks so strict OpenAI clients can parse them reliably.
- 🛡️ Safer model routing: filters or rejects img2img, inpainting, masks, upscaling, audio, embeddings, and other unsupported input modes.
- 🪶 Single-file Worker: easy to inspect, fork, deploy, and customize.
- 🆓 Free and open source friendly: no vendor lock-in beyond Cloudflare Workers AI.
| Endpoint | Method | Purpose |
|---|---|---|
/v1/models |
GET |
OpenAI-compatible model list with capability filtering. |
/v1/models?protocol=openai-chat |
GET |
List only chat-compatible Workers AI models. |
/v1/models?protocol=openai-images |
GET |
List only prompt-only image generation models. |
/v1/chat/completions |
POST |
Proxy chat requests to Cloudflare Workers AI OpenAI-compatible chat. |
/v1/images/generations |
POST |
Generate images through Cloudflare Workers AI and return OpenAI Images format. |
Deploy with Wrangler:
npx wrangler deploySet required Cloudflare credentials as secrets:
npx wrangler secret put CLOUDFLARE_API_TOKEN
npx wrangler secret put CLOUDFLARE_ACCOUNT_IDOptionally protect the public proxy with your own API key:
npx wrangler secret put PROXY_API_KEY| Name | Required | Default | Purpose |
|---|---|---|---|
CLOUDFLARE_ACCOUNT_ID |
Yes | unset | Cloudflare account ID. Prefer Wrangler Secret for public repos. |
CLOUDFLARE_API_TOKEN |
Yes | unset | Cloudflare API token with Workers AI access. Must be secret. |
PROXY_API_KEY |
No | unset | Optional bearer token required by this proxy. |
DEFAULT_IMAGE_MODEL |
No | unset | Fallback image model when /v1/images/generations omits model. |
DEFAULT_IMAGE_SIZE |
No | 1024x1024 |
Default image size. |
MAX_IMAGE_COUNT |
No | 1 |
Maximum allowed n for image generations. Hard max: 4. |
Never commit real credentials to GitHub.
import OpenAI from "openai";
const client = new OpenAI({
apiKey: "your-proxy-api-key",
baseURL: "https://your-worker.your-subdomain.workers.dev/v1",
});
const models = await client.models.list();
const chat = await client.chat.completions.create({
model: "@cf/meta/llama-4-scout-17b-16e-instruct",
messages: [{ role: "user", content: "Hello from Workers AI" }],
});
const image = await client.images.generate({
model: "@cf/black-forest-labs/flux-2-dev",
prompt: "a cinematic robot reading open source code",
response_format: "b64_json",
});Set your endpoint:
export BASE_URL="https://your-worker.your-subdomain.workers.dev"
export PROXY_API_KEY="your-proxy-api-key"List compatible models:
curl "$BASE_URL/v1/models" \
-H "Authorization: Bearer $PROXY_API_KEY"List image-generation models:
curl "$BASE_URL/v1/models?protocol=openai-images" \
-H "Authorization: Bearer $PROXY_API_KEY"Chat completion:
curl "$BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "@cf/meta/llama-4-scout-17b-16e-instruct",
"messages": [
{ "role": "user", "content": "Write one sentence about Cloudflare Workers AI." }
]
}'Image generation:
curl "$BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $PROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "@cf/black-forest-labs/flux-2-dev",
"prompt": "a clean open source dashboard UI, high detail",
"size": "1024x1024",
"response_format": "b64_json"
}'This proxy intentionally exposes only models that match the implemented OpenAI-compatible endpoints.
Chat models:
- Used by
/v1/chat/completions. - Discovered from Workers AI Text Generation models.
Image models:
- Used by
/v1/images/generations. - Prompt-only Text-to-Image models.
- Supports both JSON request models and multipart transport models.
Unsupported modes are filtered or rejected:
- img2img
- image editing
- inpainting
- masks
- upscaling
- audio
- embeddings
- object detection
- input-image-only models
- Never hardcode Cloudflare API tokens.
- Never commit
.dev.vars,.env,.wrangler, archives, or local build output. - Use
wrangler secret putforCLOUDFLARE_API_TOKENandPROXY_API_KEY. - Rotate any token that was pasted into a chat, issue, terminal log, or committed file.
- Use
PROXY_API_KEYwhen deploying a public Worker.
/v1/images/editsis not implemented./v1/embeddingsis not implemented./v1/audio/*is not implemented.- Image URLs are returned as data URLs when
response_format: "url"is requested; no R2 storage is required. - This proxy focuses on OpenAI-compatible chat and prompt-only image generation.
Thanks to Cloudflare for Workers AI, the OpenAI-compatible API ecosystem, and the open source community building tools around local and serverless AI workflows.
If this project helps you, consider starring the repository, sharing improvements, and keeping your fork free for others to use.
MIT License. See LICENSE.txt.