# GPT Image 2 API in Python: a complete example

By SeedRouter · Published 2026-09-23 · Updated 2026-09-23

To use the GPT Image 2 API from Python, POST your request to `https://api.seedrouter.ai/v1/images/generations` with the `requests` library, keep the task `id` it returns, poll `/v1/tasks/{id}` until the task is `completed`, and download the image URLs it lists. The script below does all four steps in about 40 lines and saves the images to disk.

It runs as-is once `SEEDROUTER_API_KEY` is set. If you do not have a key yet, [get one first](https://seedrouter.ai/blog/gpt-image-2-api-key).

## What does a complete GPT Image 2 script look like?

```python
import os
import time
import requests

API = "https://api.seedrouter.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['SEEDROUTER_API_KEY']}"}


def submit(body):
    response = requests.post(f"{API}/images/generations", headers=HEADERS, json=body, timeout=60)
    if response.status_code >= 400:
        error = response.json()["error"]
        raise RuntimeError(f"{response.status_code} {error['code']}: {error['message']}")
    return response.json()["id"]


def wait(task_id, limit_seconds=600):
    deadline = time.monotonic() + limit_seconds
    while time.monotonic() < deadline:
        task = requests.get(f"{API}/tasks/{task_id}", headers=HEADERS, timeout=30).json()
        if task["status"] == "completed":
            return [image["url"] for image in task["output"]["data"]]
        if task["status"] == "failed":
            raise RuntimeError(f"{task['error']['code']}: {task['error']['message']}")
        time.sleep(3)
    raise TimeoutError(f"Still running. Resume polling task {task_id}.")


def download(urls, prefix):
    paths = []
    for index, url in enumerate(urls):
        path = f"{prefix}-{index}.png"
        with open(path, "wb") as file:
            file.write(requests.get(url, timeout=60).content)
        paths.append(path)
    return paths


task_id = submit({
    "model": "gpt-image-2",
    "prompt": "A matte ceramic vase on a sunlit table, soft shadows",
    "size": "1024x1024",
    "quality": "low",
    "n": 2,
})
print("task", task_id)
print(download(wait(task_id), "vase"))
```

Run it with `python example.py`. It prints the task ID first, then the paths of two PNG files, `vase-0.png` and `vase-1.png`.

## What does each function do?

**`submit`** sends the request and returns the task ID. An error response always carries an `error` object with a numeric `code` and a `message`, so the exception tells you what to fix. A 400 with code `20001` and the message "Check the size parameter against the API documentation.", for instance, means the size broke one of the rules in the [parameter guide](https://seedrouter.ai/blog/gpt-image-2-api-parameters).

**`wait`** polls every three seconds until the task finishes. A deadline on your side stops the loop, not the task: the render keeps going, and you can resume polling the same ID later. A task that ends `failed` raises with its error code and is not charged.

**`download`** fetches every URL the task returned and writes it to disk. Result URLs are a delivery handoff, not permanent storage, so save what you want to keep. The example uses `requests` for downloads as well as API calls; keep one HTTP client throughout rather than mixing in the standard library's `urllib`.

## How do you change the image settings?

Everything is in the request body. The fields most people change first:

| Field           | Example         | Effect                                          |
| --------------- | --------------- | ----------------------------------------------- |
| `size`          | `"1536x1024"`   | Output dimensions; `auto` lets the model choose |
| `quality`       | `"medium"`      | `low`, `medium`, `high` or `auto`               |
| `n`             | `4`             | Number of images, 1 to 10                       |
| `output_format` | `"jpeg"`        | `png` or `jpeg`                                 |
| `background`    | `"transparent"` | Needs `png`                                     |

If you change `output_format`, change the `.png` extension in `download` to match. The full list of fields and limits is in the [GPT Image 2 API reference](https://seedrouter.ai/docs/gpt-image-2).

## How do you edit an image from Python?

Pass reference images as URLs in the same call. There is no separate edit endpoint; adding `images` makes the request an edit, and a `mask` limits the change to one region:

```python
task_id = submit({
    "model": "gpt-image-2",
    "prompt": "Make the vase deep blue. Keep the table and the light unchanged.",
    "images": [{"image_url": "https://example.com/vase.png"}],
})
```

The URLs must be public HTTPS links to PNG, JPEG or WebP files. You can send up to 16. Local files and base64 strings are rejected, so upload the image to your own storage first and pass its URL.

## What should the script do when submission times out?

Do not submit again straight away. A timeout on the POST does not prove the request was rejected; the task may already be running and charged. Check your recent tasks, or retry the request only after confirming no task was created. The [task guide](https://seedrouter.ai/docs/api/tasks) explains how to tell the two apart.

Polling is different: a timeout while polling is harmless. Call `wait` again with the same ID.

## Frequently asked questions

### Can I use the OpenAI Python SDK instead?

Not directly. This API delivers results asynchronously through a task ID, while the SDK's image call expects the finished image in the response. A few lines of `requests`, as above, cover the whole flow.

### How do I run several prompts?

Submit each prompt, store all the task IDs, then poll them. The [batch guide](https://seedrouter.ai/blog/gpt-image-2-batch-generation) shows a version that survives restarts without paying twice.

### Does `gpt-image-2-official` need different code?

No. Change the `model` string and nothing else. The two IDs accept the same fields and return the same task response; only billing differs.

## Keep the task ID, and the rest is plumbing

Submit, store the ID, poll with a deadline, and download what comes back. That pattern is the whole integration. Try a prompt without code in the [GPT Image 2 Playground](https://seedrouter.ai/models/gpt-image-2#playground) before you script it.
