
In brief
Generated images arrive at full resolution and full weight. The API call is the easy half; resizing and re-encoding without a second lossy pass is what keeps them usable on a page.
FLUX 3 Image is served through a hosted API rather than something you run on a laptop, which means the interesting work happens after the request returns. The model hands back a fixed high-resolution image with no awareness of your page budget, so the difference between a fast site and a slow one is the pipeline you wrap around the call.
This guide covers the request and response shape most image APIs use, then the resize-and-encode step that turns the result into something you can actually ship.
01What a hosted image API changes about your pipeline
A local model returns a tensor or a file on disk. A hosted one returns either a URL or a base64 blob inside JSON, and each choice pushes cost to a different place. A URL keeps the API response small but usually expires within hours and forces you to download and re-host the bytes anyway. Base64 keeps everything in one response but inflates the transfer by about 33% and makes your request logs enormous.
Verify field names against the current docs
The request below follows the shape most image APIs use — a JSON body with a prompt and size, authenticated with a bearer token. Black Forest Labs publishes the exact FLUX 3 endpoint and parameter names, and those change; treat this as a template, not a frozen contract.
02Request an image from the API
Send a POST with a JSON body and an authorization header. Model and endpoint names differ between providers, so keep them in configuration rather than hard-coding them in ten places.
curl -X POST "$IMAGE_API_URL" \
-H "Authorization: Bearer $IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "isometric illustration of a filing cabinet, soft indigo palette",
"width": 1024,
"height": 1024,
"format": "png"
}'
Respect the aspect ratio you actually need. Generating a square and cropping to a banner throws away pixels you paid for, and asking for a very wide canvas wastes tokens on regions you will trim.
03Handle the response: URL or base64
The two response shapes need different code paths. The URL form is a short JSON body you fetch a second time; the base64 form is a large string you decode and write to disk.
{
"id": "req_9f3c1a",
"status": "ready",
"image": {
"url": "https://cdn.example.invalid/generations/req_9f3c1a.png",
"expires_at": "2026-10-04T12:00:00Z"
},
"seed": 812347
}
const res = await fetch(process.env.IMAGE_API_URL, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.IMAGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ prompt, width: 1024, height: 1024, format: 'png' }),
})
const data = await res.json()
const bytes = data.image.url
? Buffer.from(await (await fetch(data.image.url)).arrayBuffer())
: Buffer.from(data.image.b64, 'base64')
await fs.writeFile(`out/${data.id}.png`, bytes)
Persist the seed alongside the file. It is the only way to reproduce or riff on a result later, and regenerating from scratch is rarely identical.
04Resize before you compress
Order matters. If you compress first and resize second, the resize has to invent or discard pixels that the lossy encode already damaged. Resize to the display size first, then apply one lossy encode.
| Display target | Store | Notes |
|---|---|---|
| 600 px card | 1200 px | Covers 2× displays |
| 1200 px hero | 2000 px | Cap around 2000 px; beyond that, gains are invisible |
| Full-bleed background | 2560 px | Only if the layout truly spans the viewport |
For a typical blog or product card, a 1024-pixel API result is already larger than you need. Downscale to roughly twice the rendered width and stop.
05Pick the format and encode once
Generated images are usually PNGs, which are lossless and therefore heavy. For photographic output, convert to WebP; it supports transparency, so you do not lose alpha by switching. Choose AVIF only if you can serve a fallback, because encoder support and decode cost still vary across older devices.
# One lossy pass from the original, after resizing.
cwebp -q 82 -m 6 -resize 1200 0 source.png -o output.webp
Tune quality visually rather than by number. A quality setting is not a file-size percentage: the same value can halve one image and barely move another, depending on how much high-frequency detail the model produced.
Never re-encode an already-lossy file to fix its size
Running a JPEG through the encoder a second time to shrink it discards more detail at the same quality setting. Always keep the original PNG, adjust your parameters, and re-encode from that master.
06Wire it into a build or CMS
Run the pipeline once at ingest, not on every request. Generate the image, write the original to object storage, then produce two or three derivatives with fixed widths and serve whichever matches the viewport.
The stable set for most sites is 400, 800 and 1600 pixels wide, exposed through srcset. Store the seed, prompt and model name in your database next to the asset so you can audit where an image came from. If a page renders a generated image at full width without a width and height attribute, you also get layout shift on top of the weight problem.
07Common errors and fixes
| Symptom | Cause | Fix |
|---|---|---|
| Request returns 401 | Missing or wrong bearer token | Check the header is sent, not just stored |
| Response is enormous JSON | Base64 image inline in the payload | Request a URL, or decode to disk before logging |
| URL stops working after a day | Signed link expired | Download and re-host immediately |
| Output looks blurry | Upscaled beyond the generated resolution | Generate at the target size instead of enlarging |
| Transparency turned black | Converted a transparent PNG to JPEG | Keep WebP or PNG for images with alpha |
The rule of thumb: treat the API output as a master asset, never as the file you serve. Downscale once, encode once, and keep the untouched original so you can change your mind without asking the model for the same image twice.
Drop the API output in, resize and re-encode to WebP without uploading to a server.
Image CompressorFrequently asked questions
Why is the image my API returned so large?
Image models return a fixed high resolution, often 1024 pixels or more on the long edge, with no web-oriented encoding. Nothing in the API knows or cares about your page budget.
Should I request a URL or a base64 response?
A URL is smaller and easier to cache, but it expires and adds a second request. Base64 is self-contained but inflates the payload by roughly a third and bloats JSON logs.
Does converting PNG to WebP lose transparency?
No. WebP supports an alpha channel, so transparent PNG output converts cleanly. Only convert to JPEG when the image has no transparency and is photographic.
Why does re-compressing an image make it look worse each time?
Every lossy encode discards detail that the next encode cannot recover. Compress once from the highest-quality source you have instead of chaining lossy steps.
What resolution should I store for a website?
Store at the largest size you actually display, then generate smaller variants. Storing a 2048-pixel master for a 600-pixel card wastes bytes on every request.
Related articles
- How to compress images without losing quality
Quality settings, resizing order and the double-encoding trap.
- Create a QR code that scans every time
Another format where the last 5% of size decides whether it works.
Related tools
- Image Compressor
Resize and compress in the browser.
- PNG to WebP
Convert generated PNGs for the web.
- JPG to WebP
Re-encode JPEG output to a smaller format.
- WebP to JPG
Convert back when a downstream tool requires JPEG.
- PNG to JPG
Drop the alpha channel for photographic output.