GPT-6 Sol・Claude Opus 5.5 提供開始GPT-6 Sol の料金は 5.6 Sol の半額

GPT Image 2.5 API:Python で画像を生成・編集する方法

POST を1回送ればタスクができ、GET を1回送れば結果が返ります。実行したリクエストコード、2026年10月29日に試したサイズ、編集のビフォーアフターをまとめました。

Kiki, OmniaKey COO読了目安 7分
このページの内容

https://api.omniakey.com/v1/media/tasks に POST を1回送り、model に gpt-image-2.5-flare を指定し、返ってきたタスク id をポーリングして、status が succeeded になったら assets[0].url をダウンロードします。2026年10月29日に 1K、2K、1536x1024 の3サイズで生成し、カフェの写真を1枚編集しました。ファイルはすべて開いて実寸を読み取り、1024×1024、2048×2048、1536×1024、1024×682 でした。1K の生成は 29.5 秒、2K は 45.2 秒です。

2.5 のモデル id はどれを使うか

gpt-image-2.5-flare を使います。以下のすべての実行で呼び出した id です。GPT-Image 2.5 Flare のモデルページ(2026年10月29日確認)には、プロバイダーが OpenAI であること、テキストからの画像生成と画像編集に対応していることが書かれ、さらに「Guide updated 2026-10-27」という注記があります。同じページには2つ目の 2.5 の id、gpt-image-2.5-sunburst も載っています。

Flare は生成と編集の両方をこなします。生成はプロンプトだけを送り、編集はプロンプトに元画像を1枚添えて送ります。品質は low、medium、high の3段階で、同じページには段階が価格を変えないと書かれています。ここでの実行はすべて medium です。sunburst、low と high、4K と 3840x2160、マスク、複数の参照画像は試していないので、まずは Flare と medium、元画像1枚の構成で計画を立て、残りはご自身で試してから判断してください。

リクエストコード

以下のスクリプトは実際に実行したもので、変更は加えていません。ヘルパー関数が2つ、そのあとに生成の呼び出しが1回、編集の呼び出しが1回です。Python の標準ライブラリだけを使い、キーは OMNIAKEY_API_KEY から読み、各 PNG はスクリプトを実行したフォルダに書き出します。

python
import base64
import json
import os
import time
import urllib.request
import uuid

API = "https://api.omniakey.com/v1/media/tasks"
KEY = os.environ["OMNIAKEY_API_KEY"]
MODEL = "gpt-image-2.5-flare"

def request(method, url, body=None, extra_headers=None):
    headers = {"Authorization": f"Bearer {KEY}", "User-Agent": "omniakey-example/1"}
    data = None
    if body is not None:
        headers["Content-Type"] = "application/json"
        data = json.dumps(body).encode()
    headers.update(extra_headers or {})
    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    with urllib.request.urlopen(req, timeout=120) as resp:
        return json.load(resp)

def run_task(body, out_path):
    task = request("POST", API, body, {"Idempotency-Key": str(uuid.uuid4())})["id"]
    for _ in range(150):
        time.sleep(4)
        state = request("GET", f"{API}/{task}")
        if state["status"] not in ("queued", "processing"):
            break
    if state["status"] != "succeeded":
        raise RuntimeError(state.get("error") or state["status"])
    asset_url = state["assets"][0]["url"]  # 署名付きリンク:有効期限は約1時間なので、すぐにダウンロードする
    req = urllib.request.Request(asset_url, headers={"User-Agent": "omniakey-example/1"})
    with urllib.request.urlopen(req, timeout=120) as resp, open(out_path, "wb") as f:
        f.write(resp.read())
    return task

def generate_image(prompt, out_path, size="1K", quality="medium"):
    body = {
        "model": MODEL,
        "type": "image",
        "operation": "generate",
        "input": {"prompt": prompt},
        "parameters": {"size": size, "quality": quality},
    }
    return run_task(body, out_path)

def edit_image(source_path, prompt, out_path, size="1K", quality="medium"):
    with open(source_path, "rb") as f:
        image = base64.b64encode(f.read()).decode()
    body = {
        "model": MODEL,
        "type": "image",
        "operation": "edit",
        "input": {"prompt": prompt, "image": {"data": image, "mime_type": "image/jpeg"}},
        "parameters": {"size": size, "quality": quality},
    }
    return run_task(body, out_path)

if __name__ == "__main__":
    task = generate_image(
        "A small glass greenhouse on a hillside at sunrise, morning fog in the valley, "
        "soft watercolor style, a wooden bench outside the door, no people, no text.",
        "greenhouse.png",
    )
    print("generate task", task)
    task = edit_image(
        "cafe-base.jpg",
        "Change the red bicycle to matte black. Keep everything else exactly the same: "
        "the table, the cup, the window frame and the daylight. Photorealistic, no text, no logos.",
        "cafe-edited.png",
    )
    print("edit task", task)

Authorization: Bearer <key> はどの呼び出しにも付けます。作成の呼び出しにはさらに Idempotency-Key が必要で、スクリプトは新しい UUID を入れています。ボディでは type を "image"、operation を "generate" または "edit" にし、プロンプトは input.prompt、サイズと品質は parameters に入れます。API は n も受け付けますが、有効なのは 1 だけなので、スクリプトでは省略しています。作成は HTTP 202 とタスク id を返し、status は queued から始まり、ループは4秒おきに確認して、作業中の2つの状態を抜けるまで待ちます。

編集では JPEG を input.image にインラインの Base64 オブジェクトとして、MIME タイプとともに入れます。リクエストボディは Base64 を含めて 1 MiB までなので、スクリプトは約 230 KB の 1024 ピクセル JPEG を送っています。

実行したサイズと返ってきた結果

実行は4回、すべて品質 medium、日付は 2026年10月29日です。3回はリクエストしたサイズで返ってきました。1K の編集だけは、2回のうち1回で違うサイズになっています。

  • 1K、生成 — ファイルから読み取ったピクセル: 1024×1024; 日付: 2026年10月29日
  • 2K、生成 — ファイルから読み取ったピクセル: 2048×2048; 日付: 2026年10月29日
  • 1536x1024、生成 — ファイルから読み取ったピクセル: 1536×1024; 日付: 2026年10月29日
  • 1K、編集 — ファイルから読み取ったピクセル: 1024×682; 日付: 2026年10月29日

下の温室は、上のコードと同じリクエストボディで生成した 1K の画像です。

日の出の丘の上に建つ水彩画風のガラス温室。谷には霧が立ちこめ、扉の外に木のベンチがある。
2026年10月29日に GPT-Image 2.5 Flare を OmniaKey API 経由で生成。サイズ 1K、品質 medium。

このリストから言えることは2つです。1つ目は、サイズはダウンロードしたファイルから読むということです。1K の編集は正方形を指定したのに 1024×682 で返り、それは送った 1024×683 の JPEG と同じ形でした。同じ編集をもう一度 1K で実行すると、今度は 1024×1024 で返っています。2つ目は、画像 API のドキュメント(2026年10月29日確認)のサイズ一覧には auto、1K、2K、4K、3840x2160 が載っていて、一覧にないサイズは課金前に断ると書かれているのに、2026年10月29日の 1536x1024 の呼び出しは断られず、1536×1024 が返ってきたことです。1つのサイズを前提にレイアウトを組む前に、実際のファイルを確認してください。

編集ではシーンを残し、変えるのは1か所だけ

編集で答えるべきは2つです。何を変えるのか、何を残すのか。ここでは変更を1つだけ頼み、残すものを名指ししました。

プロンプト:"Change the red bicycle to matte black. Keep everything else exactly the same: the table, the cup, the window frame and the daylight. Photorealistic, no text, no logos."

左:カフェの窓の外に止まった赤い自転車。右:同じ窓を編集したあとで、自転車が濃い色になっている。
左:送った元の写真。右:2026年10月29日の編集1回の出力。サイズ 1K、品質 medium。変えたのは自転車だけで、テーブル、カップ、植物はそのままの位置に残っています。

自転車は濃い色になり、テーブル、カップ、植物、窓枠も画面に残りました。元画像は 1024×683 の JPEG で、出力は 1024×682、実行時間は 38.0 秒でした。残したいもののリストは毎回書いてください。プロンプトの組み立て方全般は、GPT Image 2 プロンプトガイド で解説しています。

エラーと制限

ピクセルが1つも生まれる前に効いてくるのは2つのヘッダーです。Bearer トークンと、一意な Idempotency-Key です。この2つを正しくしておけば、残りの呼び出しは単純に再試行できます。

送る内容返ってくるもの
キーなしで作成を呼び出す400 missing_idempotency_key
同じキーと同じボディで2回200 と既存のタスク。新たな課金はなし
同じキーでボディを変更409 idempotency_key_reused

キーは最大 255 文字です(2026年10月29日確認のドキュメントによる)。同じボディでの再利用が安全な再試行になります。既存のタスクが返り、新たに課金されることはありません。ボディは Base64 を含めて 1 MiB 未満に収めてください。元画像は送る前に縮小するか圧縮してください。

タスクが成功すると、assets[0].url は署名付きリンクになります。ドキュメントによれば有効期限は約1時間なので、すぐにダウンロードするか、同じタスクをもう一度ポーリングして新しいリンクを取得してください。タスクの記録は24時間保持されます。

2026年10月29日、ヘッダー1つに引っかかりました。Python の urllib が既定で送る User-Agent で POST すると、Cloudflare から HTTP 403 とボディ「error code: 1010」が返ってきました。同じ POST を自前の User-Agent: omniakey-example/1 ヘッダー付きで送ると API に届き、空のボディに対して 400 invalid_request が返り、課金は発生しませんでした。ドキュメントに名前があるのは Authorization と Idempotency-Key だけなので、クライアント側で User-Agent を設定してください。

API 開発なら GPT Image 2.5 と GPT Image 2 のどちらか

試した 2.5 の id は Flare です。GPT Image 2 は GPT Image 2 モデルページ にあるとおり、id は gpt-image-2 です。その id で必要な画像が出ているスクリプトなら、変える理由はありません。

シーンを保ったまま1つの物体だけを変えたい写真には、Flare と medium の組み合わせが、2026年10月29日の実行でカバーできた範囲です。生成3サイズと 1024×682 の編集がそれにあたります。GPT Image 2.5 と GPT Image 2 の比較 には両モデルのサイズと同一プロンプトでの結果があるので、数字を見ながら選べます。最新の料金は料金ページにあります。

よくある質問

gpt-image-2.5-flare と gpt-image-2.5-sunburst のどちらを使うべきですか?

ここまでの実行はすべて Flare で、編集では残すよう指定したシーンがそのまま残りました。モデルページには2つ目の 2.5 の id として Sunburst が載っています。まずは Flare から始め、自分のいちばん難しい編集を Sunburst でも通せてから切り替えてください。

1536x1024 のような横長サイズは指定できますか?

2026年10月29日の 1536x1024 の生成は 1536×1024 で返ってきました。画像 API のドキュメントのサイズ一覧には、このモデルでその値が載っていないので、本番で頼る前にファイルを読み、ドキュメントも確認してください。

編集の結果が指定したサイズと違うのはなぜですか?

同じ 1K の編集が、ある実行では 1024×682、別の実行では 1024×1024 で返りました。指定するサイズは約束ではなくリクエストだと考えてください。配置する前に PNG を開いて幅と高さを読んでください。

User-Agent ヘッダーは必要ですか?

2026年10月29日、Python の既定の User-Agent を使ったリクエストは HTTP 403 と Cloudflare のエラー 1010 で返されました。自前の User-Agent ヘッダーを付けた同じリクエストは API に届いたので、付けて送ってください。

画像のリンクはどのくらい有効ですか?

ドキュメントによると署名付きリンクの有効期限は約1時間です。新しいリンクが欲しいときはタスクをもう一度ポーリングし、タスクが成功したらすぐにファイルをダウンロードしてください。

この記事で紹介しているモデル

GPT Image 2.5画像APIPython画像編集API

関連記事

最近の記事