Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Set the Image API’s n parameter to the number of images you need, then iterate over the returned data array. One request can therefore produce several final images instead of making one request per image. The default is one image.
The direct Image API is the simplest workflow for this job. The Responses API can generate images inside a conversation, but its image-tool controls should be checked for the model and workflow you select.
Use n on the Image API
A multiple-image request has the same basic inputs as a one-image request: a model, a prompt, and output settings. Add n with an integer count and process every item returned in data. Do not assume that the response contains one object or that a particular model supports every value for every setting.
POST /v1/images/generations
{
"model": "YOUR_IMAGE_MODEL",
"prompt": "A red fox reading beside a rain-covered window, editorial illustration",
"n": 4,
"size": "1024x1024"
}
The currently available model identifiers and their controls can change. Keep the model in configuration, verify it against the current Images API reference, and avoid hard-coding a sample identifier without checking access for your organization.
#1 Best Overall
Python: request and save every image
This script uses the official Python SDK and is written for models that return base64 image data. GPT Image models return base64 data by default. Install the SDK, set OPENAI_API_KEY, and choose a model that your organization can use.
pip install openai
export OPENAI_API_KEY="your-api-key"
export OPENAI_IMAGE_MODEL="gpt-image-1"
import base64
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
model = os.environ.get("OPENAI_IMAGE_MODEL", "gpt-image-1")
count = int(os.environ.get("IMAGE_COUNT", "4"))
prompt = (
"A red fox reading beside a rain-covered window, "
"editorial illustration, warm indirect light"
)
result = client.images.generate(
model=model,
prompt=prompt,
n=count,
size="1024x1024",
)
Path("images").mkdir(exist_ok=True)
items = result.data
for index, item in enumerate(items, start=1):
encoded = getattr(item, "b64_json", None)
if not encoded:
raise RuntimeError(
"This response did not contain b64_json. "
"Handle its URL response according to the selected model and format."
)
output = Path("images") / f"image-{index}.png"
output.write_bytes(base64.b64decode(encoded))
print(f"wrote {output}")
print(f"received {len(items)} image(s); requested {count}")
The final line is useful in production: compare the number received with the number requested and decide whether your application should report a partial result or retry. A request can return fewer progress previews during streaming, but the completed response is the collection you should treat as final.
cURL: make one request and decode the array
cURL receives the JSON response. The following commands save it, then decode each base64 member into a separate PNG file. They assume a GPT Image response with b64_json.
curl https://api.openai.com/v1/images/generations
-H "Authorization: Bearer $OPENAI_API_KEY"
-H "Content-Type: application/json"
-d '{
"model": "gpt-image-1",
"prompt": "A red fox reading beside a rain-covered window, editorial illustration",
"n": 4,
"size": "1024x1024"
}'
-o response.json
mkdir -p images
i=1
jq -r '.data[] | .b64_json' response.json | while IFS= read -r image; do
printf '%s' "$image" | base64 --decode > "images/image-$i.png"
i=$((i + 1))
done
On systems whose base64 utility uses a different decode flag, replace --decode with that platform’s equivalent. If the response contains URLs rather than base64 fields, download those URLs instead of running the decoder.
Node.js: iterate over result.data
Node.js follows the same pattern. This example writes each returned base64 image to disk.
import OpenAI from "openai";
import { mkdir, writeFile } from "node:fs/promises";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const model = process.env.OPENAI_IMAGE_MODEL || "gpt-image-1";
const count = Number(process.env.IMAGE_COUNT || 4);
const result = await client.images.generate({
model,
prompt: "A red fox reading beside a rain-covered window, editorial illustration",
n: count,
size: "1024x1024",
});
await mkdir("images", { recursive: true });
for (const [index, item] of result.data.entries()) {
if (!item.b64_json) {
throw new Error("Response has no b64_json; implement the URL response path for this model.");
}
const bytes = Buffer.from(item.b64_json, "base64");
const filename = `images/image-${index + 1}.png`;
await writeFile(filename, bytes);
console.log(`wrote ${filename}`);
}
console.log(`received ${result.data.length} image(s); requested ${count}`);
Choose the output and request controls
These controls affect one request. Confirm the accepted values for the model you deploy; availability is model-specific and can change.
| Control | What it does | Practical guidance |
|---|---|---|
n |
Requests multiple final images in one Image API call. | Set it to the count you need and iterate over data. There is no universal maximum established for every model and endpoint. |
prompt |
Describes the requested image content and style. | Put shared requirements in one prompt; if you need controlled variation, state the variation explicitly rather than assuming that n creates a particular set of alternatives. |
size |
Chooses the image dimensions. | Use a value supported by the selected model and by your downstream layout. |
quality |
Requests a supported quality level where the model exposes that control. | Do not send a value copied from another model’s example without checking compatibility. |
format and compression |
Control the representation and, where supported, compression of the output. | Match the format to your storage and delivery pipeline. A response-format choice also determines whether you handle base64 data or URLs for models that support both. |
For GPT Image models, base64 image data is the default response form. DALL·E URL behavior depends on the response-format configuration. Your decoder must branch on the actual response shape instead of assuming every model behaves like GPT Image.
Do not confuse n with streaming previews
n controls how many final images you request. Streaming is a separate concern: the documented partial_images setting controls progress images while a generation is running, with a range from zero through three. The service may send fewer partial images if final generation finishes sooner. Those previews are not additional final outputs and should not be counted as the result of n.
If your interface displays previews, label them as temporary and replace them with the completed images from the final response. If you only need files, omit streaming and process the completed data array.
When the Responses API is the better workflow
Use the direct Image API when the job is simply “generate these images.” Use the Responses API image-generation tool when image creation is one step in a conversational workflow that also needs text reasoning, tool calls, or follow-up turns.
Rank #3
Those are different integration patterns. Do not assume that every Image API parameter, including n, is available unchanged in the Responses API tool. Check the tool controls for the model you select and test the exact request shape before building around it.
Free tools Windows power users keep installed
One-click scans. No signup required.
Why the Batch API is not the shortcut here
The Batch API accepts uploaded JSONL jobs for asynchronous processing and documents a 24-hour completion window. Its documented supported endpoint list does not include the Image API endpoint. For multiple images from one image-generation call, the directly supported mechanism is still the Image API’s n parameter, not a Batch submission.
Reliability, throughput, and cost decisions
Keep request groups within the model’s limits
Because no single maximum n value applies to every current model and endpoint, check the chosen model’s limits. If you need a large collection, divide it into groups that the model accepts and record which group produced each file.
Validate the completed count
Check that result.data exists and count its members. Store the prompt, model, requested count, and received count with the job so an operator can distinguish a complete run from a partial one.
Plan for all-or-nothing request failures
A single request is simpler than coordinating many calls, but a failed request can leave you with no completed set. For important jobs, persist the request parameters before sending, log the response metadata, and retry only according to your application’s error policy. If you retry without tracking attempts, you can create duplicate sets.
Rank #4
Measure usage with the service’s current pricing rules
The number of images, model, quality, and dimensions can affect usage. Pricing and limits are model-dependent and change over time, so consult the current account and model documentation before setting a production budget. The Image API guide does not establish one universal price or a universal maximum for n.
Troubleshooting common failures
“Invalid parameter” or a rejected count
The selected model may not accept the value, or the request may be using a control from another model. Verify the model identifier, supported count, size, quality, and format in the current reference. Do not infer a global maximum from one example.
The organization cannot use the GPT Image model
Some GPT Image access requires organization verification. Complete the required verification for the organization attached to your API key, or select a model your organization is eligible to use.
The code expects base64 but receives URLs
Inspect the first object in data. GPT Image models return base64 by default, while DALL·E URL responses depend on response-format configuration. Add a URL-download branch and preserve the response format you requested.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchOnly one file is written
Check that your loop iterates over result.data rather than reading only its first element. Also verify that the request actually sent n and that the saved JSON contains the expected number of objects.
Best Value
Preview count is lower than requested
If you are streaming, this can be normal: partial_images is a progress setting, and fewer previews may arrive when final generation completes quickly. Count final images only after the completed response arrives.
The request works in one environment but not another
Compare the API key’s organization, model configuration, SDK version, and serialized JSON. Keep the model and count in environment variables, log the non-secret request settings, and never print the API key.
Or skip the browser setup
If your next step is capturing a rendered web page or preview rather than generating pixels, ScreenshotNeo is the first service to try: it removes consent banners, popups, and chat widgets before capture, and only clean shots are billed.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Its API can capture a URL in one call. See the ScreenshotNeo API documentation for the current options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo also provides Python and Node.js equivalents:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. An MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does n guarantee that every image is a different variation?
It requests multiple outputs, but visual diversity is not a documented guarantee. If differences matter, describe the variation you need in the prompt and inspect the returned files.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsWhat should I store for a reproducible multi-image job?
Keep the model identifier, prompt, count, output settings, SDK or request version, and the received item count alongside the files. This makes a later partial result distinguishable from a complete set.
Can I use the same decoder for every image model?
No. GPT Image models return base64 data by default, while DALL·E URL responses depend on response-format configuration. Branch on the actual response fields.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

