DEV Community

Lucas Him
Lucas Him

Posted on Originally published at qiita.com

How to Turn ChatGPT Images 2.5 into an API

I could already ask my agent to generate an image through MCP. But I wanted to try something less conversational: send a prompt from a script and get a file back.

That was the gap I wanted a ChatGPT image generation API to fill. No agent choosing a tool for me, and no manual download at the end. Just a request my code could submit and a result it could retrieve.

The answer was in the BrowserAct ChatGPT image template I had already been using. Its published Bot could be called through HTTP as well as MCP. I tested that route with a perfume-bottle prompt and downloaded the resulting PNG.

What interested me was having one reusable image tool: I could call it from code, use it from a compatible agent, and keep the ChatGPT login in one configured browser environment.

I Wanted the Image Workflow in My Code

My earlier MCP walkthrough was about requesting images inside an agent. This time, I wanted to handle the inputs, waiting, and files myself.

For a script, “generate an image” needs a little more structure. Has the job been accepted? Is it still running? Where is the actual image, rather than a message saying it exists?

The template is named ChatGPT Image 2.5 API (Copy Before Use). BrowserAct runs the ChatGPT web task using the session saved in the personal Bot's browser environment. Its API gives my code a way to start that task and retrieve the result.

My code talks to BrowserAct, which runs the image task on the ChatGPT website. That means using BrowserAct's endpoints and task responses rather than the OpenAI SDK. For me, the appeal was reusing the image workflow I already had.

Setting Up the Bot and Getting an API Key

I already had my personal Bot published from the MCP setup. To start from the public ChatGPT image template, follow these steps:

  1. Click Create Editable Duplicate to make your own Bot.
  2. Keep a consistent browser environment. If you use a proxy, choose a static one before logging in rather than repeatedly changing it.
  3. Open Build → Improve and restore your ChatGPT login without rebuilding the Bot.
  4. Publish the personal Bot, then use its ID for the API request.

Here is the setup-to-image path, including both ways to call the published Bot:

Flow from copying the ChatGPT image template and restoring login to publishing a Bot, calling it through HTTP or MCP, and downloading the image

The login instruction from my earlier setup was:

My login session is no longer available. I need to log in again. Do not rebuild or refactor the Bot. Keep the existing workflow, inputs, and outputs unchanged.
Enter fullscreen mode Exit fullscreen mode

The setup walkthrough with screenshots covers those pages. If ChatGPT asks you to log in again later, return to Improve to restore the session.

Once the Bot is published, get a BrowserAct API key for your script. The API key guide shows the screens:

  1. In the BrowserAct dashboard, open Integrations → Manage API Keys.
  2. Select Create New API Key, give it a name, leave Confirmation Required selected for CLI actions, and click Confirm.
  3. Copy the key and store it as an environment variable, such as BROWSERACT_API_KEY, rather than putting it in source code.

Use that key in the request's Authorization: Bearer header, together with your published personal Bot's ID—not the public template ID. The ChatGPT login stays with the Bot; the HTTP request does not need your ChatGPT password.

One POST Started the Image Task

I started with a Node.js HTTP client and a simple product-photo prompt:

Create a cinematic product photo of a transparent glass perfume bottle on dark green stone
Enter fullscreen mode Exit fullscreen mode

There was no reference image. These were the request fields:

{
  "input": {
    "prompt": "Create a cinematic product photo of a transparent glass perfume bottle on dark green stone",
    "reference_images": "none",
    "max_prompt_characters": 4000,
    "max_reference_images": 4,
    "max_reference_image_mb": 10
  }
}
Enter fullscreen mode Exit fullscreen mode

I set reference_images to none for text-to-image and left the prompt-length and reference-image limits at their defaults.

Here are the request details to use in your own HTTP client. Replace {BOT_ID} and {BROWSERACT_API_KEY} with your personal Bot ID and key at runtime.

The request went to:

POST https://api.browseract.com/v3/bots/{BOT_ID}/runs
Authorization: Bearer {BROWSERACT_API_KEY}
Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode

The response was HTTP 200 with status: "created" and a task_id. I saved that ID locally: it was how my script would follow the image job while ChatGPT worked on it.

From there, the integration had three separate jobs:

Step Request What my script did with it
Submit POST /v3/bots/{BOT_ID}/runs Saved the returned task ID
Check GET /v3/bots/runs/{TASK_ID}/status Waited for a terminal state
Retrieve GET /v3/bots/runs/{TASK_ID} Read the output and download information

All three requests use the same BrowserAct key. My script waits for finished before retrieving the image; failed or canceled should stop the wait and surface the task status.

Waiting for the Image and Downloading the Result

I watched the task move from created to running, then finished. I chose to check every 15 seconds and set a timeout so the script would not wait indefinitely.

A small implementation tip: save the task ID before polling. If a status request is interrupted, check that same task again rather than submitting another image job. If the initial POST times out before returning an ID, check the Bot's task history before retrying.

Once the task finished, I fetched its result. The image record in output.data looked like this:

{
  "image_file": "generated-image-1.png",
  "image_format": "png",
  "image_bytes": 2366709,
  "image_public_url": null,
  "mode": "text-to-image",
  "prompt": "Create a cinematic product photo of a transparent glass perfume bottle on dark green stone",
  "prompt_truncated": false
}
Enter fullscreen mode Exit fullscreen mode

To retrieve the image, I used the download URL for resources.zip in download_files. The archive contained generated-image-1.png alongside a JSON result file.

Download tip: use download_files for the image archive. An empty image_public_url does not necessarily mean there is no image. The JSON, CSV, Markdown, and XML entries in output_files are structured-result exports, not the PNG itself.

When I opened the PNG, there was the transparent perfume bottle on dark green stone, complete with a generated AETHER label. This was a new image made from my text prompt, not an edit of an existing product photo.

This image came back at 1370 × 1148 pixels, about 2.37 MB. Its task used 16 BrowserAct credits and took 71 seconds from creation to completion, before I downloaded it. I would use the usage shown for each job when tracking costs, since other prompts can take different amounts of time and credits.

I left image settings to the ChatGPT web experience. For a project that needs an exact model, API quality tier, or output size, I would compare those requirements with the official image API before choosing this route.

Why Reusing a Subscription Is Worth Considering

Getting the file back made the subscription angle more interesting to me. The image is generated through the ChatGPT web subscription, while BrowserAct charges for running the automation. I am reusing the web image tool rather than paying for that request through the separate OpenAI image API.

For recurring image work, I would compare ChatGPT subscription + BrowserAct plan and any additional credits with the official API bill for the same workload. If I already pay for ChatGPT, I would also look at what BrowserAct adds to my existing bill. At enough volume, a lower combined cost could make a meaningful difference month after month.

Before putting a large queue through it, I would try a small batch and check the usable images, credits spent, and time needed. ChatGPT's web usage limits still set the pace. That gives me a better basis for a budget than multiplying the cost of this one image by a few thousand.

There is also a practical way to let a trusted friend call the configured Bot without handing over my ChatGPT password. For HTTP, the caller needs the API key, personal Bot ID, and request details. For MCP, the Bot must be exposed to a server, and the caller connects with that server's URL and matching key. After setup, they can request images from their own code or compatible agent while the Bot uses its saved browser environment.

What I like about that arrangement is keeping the ChatGPT login in the Bot's browser environment instead of passing the password around. Before inviting someone, I would check both the key's permissions and whether the intended use is allowed by the services involved. The key may cover more than this Bot, and their calls would use my account's credits and limits.

What I Would Keep Before Building on This

The small script now had three useful pieces: save the task ID, wait with a timeout, and download the file into storage I control. I would keep that structure when adding more prompts.

One habit worth keeping: use the BrowserAct key only on BrowserAct API requests, not on the image-storage download request. Keep keys and temporary download links out of public code, and save the image before its download link expires.

Reference-image editing would be my next step—the Bot accepts reference images, and I have so far used this HTTP path for the text-only perfume prompt. After that, I would try a small queue of non-sensitive prompts before deciding how much work to send through it.

For now, I had the ChatGPT image generation API workflow I wanted: a prompt went out from my code, and an image file came back. MCP fits the times when I want an agent to choose the tool. HTTP gives me control over when to call it and where the finished file goes.

If that is the gap in your own workflow, make a personal copy of the ChatGPT image template, connect your login, and start with one prompt. I would get that first file back before thinking about a queue.

Top comments (0)