使用ガイド
ChatGPTのリンク、エクスポートパッケージ、gen_id から画像をダウンロードする方法
リンクがまだ開ける、エクスポートパッケージしかない、リンクが期限切れ、gen_id しか残っていない——4つの状況それぞれで元画像をどう取り戻すか。
ChatGPTのリンクから画像をダウンロードするには、リンクがまだ開けるうちにファイルを保存しておく必要があります。ChatGPTの画像リンクは一時的なもので、期限が切れた後は gen_id があっても元画像を取り戻せません。
まず手元に何が残っているかを確認し、対応する方法を選んでください:
| 手元に残っているもの | 取り戻し方 | 結果 |
|---|---|---|
| まだ開ける画像リンク、または元の会話 | 画像を開き、ファイルをダウンロードして自分のストレージに保存 | 通常は元画像を保持できる |
完全なChatGPTデータエクスポート(conversations.json と画像ファイル) |
file-service:// 内のIDを使ってエクスポートフォルダ内を探す |
エクスポートパッケージにこの画像があれば取り戻せる |
すでに期限切れの backend-api または oaiusercontent リンク |
元の会話に戻る、完全なエクスポートを調べる、または再生成する | リンク自体を書き換えても再び有効にはならない |
gen_id だけが残っている |
元のプロンプトで再生成する | 元画像のピクセルは取り戻せない |
| 繰り返しバッチで画像を生成するフロー | ドキュメントのあるAPIで生成し、ダウンロード後に自分のアドレスへ保存 | 今後の画像はすべて自分の手元に残る |
重要な違いはこうです:有効な署名付きリンクならファイルをダウンロードできますが、gen_id は会話内の一つの番号にすぎず、何もダウンロードできません。
リンクがまだ開ける:直接ダウンロード
元の会話が残っているなら、生成された画像を開き、ChatGPT標準のダウンロードボタンを使います。画像リンクをコピーした場合は、完全なリンクで開いてください(? 以降のパラメータ文字列を削除しないこと)。そしてすぐに保存します。
ダウンロード後は、成功と判断する前に次の点を確認してください:
- HTTP 200 が返る;
- コンテンツタイプが画像(例えば
image/pngやimage/webp); - ファイルサイズが正常で、数百バイトではない;
- 開けて、しかも欲しかった画像である。
現在のブラウザでしか開けないリンクは、長期アドレスとして使えません:ブラウザにはログイン状態や発行直後の署名が残っている可能性があります。ファイルをダウンロードして自分のストレージにアップロードし、ChatGPTのリンクをそのまま送ったり製品に書き込んだりしないでください。
ChatGPTの画像リンクが期限切れになる理由
生成された1枚の画像には、ChatGPT内部で複数の参照が存在する場合があります:
gen_id:会話内の某一回の生成の番号。file-service://file-...:内部のファイルポインタであり、URLではない。chatgpt.com/backend-api/...とfiles.oaiusercontent.com/...:一時的な署名付きダウンロードリンク。
それぞれ役割が異なり、永久に公開される画像アドレスは一つもありません。
コピーしたリンクが開けない場合、よくあるのは次の2パターンです:
HTTP 422
missing query fields such as p or ts
リンクのコピーが不完全で署名パラメータが欠けている、または貼り付け時に何らかのツールが ? 以降の部分を削除した。
HTTP 404
ResourceNotFound
署名またはファイルがすでに期限切れ、ファイルが削除された、またはリクエストがリンク発行時のコンテキストから外れている。gen_id でそれらしいパスを組み立てても、署名と画像は復元できません。
完全なデータエクスポートから画像を取り戻す
ChatGPTの設定でデータエクスポートを申請すると、完全なエクスポートパッケージには conversations.json と個別の画像ファイルが含まれます。JSON内の1枚の画像はおおよそ次のようになります:
{
"content_type": "image_asset_pointer",
"asset_pointer": "file-service://file-A1b2C3d4E5f6",
"size_bytes": 1417238,
"width": 1024,
"height": 1024,
"metadata": {
"dalle": {"gen_id": "aBcD3fGh1jKl"}
}
}
有用なのは file-service:// の後ろの file-... の部分で、これがエクスポートパッケージ内のファイル名と一致します。gen_id はファイル名でもダウンロードの凭证でもありません。
1. エクスポートパッケージを完全に解凍する
元のディレクトリ構造を保持してください。conversations.json だけを開くと、照合すべきもう半分の画像ファイルを失います。
2. 画像ポインタを見つける
conversations.json 内で "content_type": "image_asset_pointer" を検索し、目的の会話と画像を見つけて、完全な asset_pointer をコピーします。
3. ファイルIDを取り出す
先頭の内部プレフィックスだけを削除します:
file-service://file-A1b2C3d4E5f6
└─ file-A1b2C3d4E5f6
file-service:// を https:// に置き換えてcurlしないでください。これは公網アドレスではありません。
4. エクスポートファイル内を検索する
macOS または Linux:
find . -type f -iname '*file-A1b2C3d4E5f6*'
エクスポートパッケージがファイル名を変更している、またはより深いディレクトリに置いている場合は、IDの中で最も識別しやすい部分で検索してください。size_bytes、width、height があれば、候補ファイルと照合します。
5. 確認して自分の場所に保存する
候補ファイルをローカルで開き、これが目的の画像であることを確認してから、自分のS3、R2、CDN、またはアプリのストレージにアップロードし、この長期アドレスを記録します。
画像が多い場合は、以下のスクリプトでエクスポートパッケージ内のすべての画像IDをローカルで一覧表示できます。ChatGPTには接続しません:
import json
from pathlib import Path
data = json.loads(Path("conversations.json").read_text())
seen = set()
def walk(value):
if isinstance(value, dict):
if value.get("content_type") == "image_asset_pointer":
pointer = value.get("asset_pointer", "")
if pointer.startswith("file-service://"):
seen.add(pointer.removeprefix("file-service://"))
for child in value.values():
walk(child)
elif isinstance(value, list):
for child in value:
walk(child)
walk(data)
for file_id in sorted(seen):
print(file_id)
ポインタがあっても、その会話でかつてこの画像が参照されていたことしか分からず、エクスポートパッケージにこのファイルがあるとは限りません。完全に解凍しても対応ファイルが見つからない場合、file-service:// も gen_id も元画像を復元できません。
gen_id しか残っていない場合
gen_id をPNG、WebP、または新しい署名付きリンクに変換できる公開インタフェースはありません。元の会話、使えるリンク、エクスポートパッケージ内のファイルがすべて失われた場合、元のプロンプトと当時のコンテキストで再生成するしかありません。
無効になったIDは調査記録として残しておくだけにしてください。今後長期保存する画像には、次のものを記録します:
- プロンプトと生成パラメータ;
- どのサービスのどのモデルを使ったか;
- サービス側のタスクID(調査やサポート問い合わせに便利);
- 自分のストレージ内のファイルパスまたは長期アドレス。
APIで自動ダウンロードフローを構築する
バッチで画像を生成して保存するには、もともと画像ファイルを返すAPIを使います。HiAPIでは、安定したフローは「送信、ポーリング、ダウンロード、検証、転送保存」です。
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2/text-to-image",
"input": {
"prompt": "晨光里,书桌上放着一只纸鹤",
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
taskId を取得したら GET /v1/tasks/{taskId} をポーリングし、成功後に data.output[0].url と expireAt を読み取ります:
curl -s "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
-H "Authorization: Bearer $HIAPI_API_KEY"
curl -s -o generated-image.webp "<data.output[0].url>"
APIが返すアドレスも同様に一時的ですが、有効期限が返却結果に書かれている(expireAt)ため、期限内に処理できます。期限前にダウンロードし、受け取ったのがHTMLやJSONのエラーではなく画像であることを確認してから、ファイルを自分のストレージにアップロードします。
gpt-image-2/text-to-image は1Kで1枚 $0.03、2Kで $0.04、4Kで $0.06 です。パラメータとオンライン試用はGPT Image 2 モデルページ、リクエスト形式はタスク作成ドキュメントをご覧ください。
リンク切れに強いストレージの実践
成功した各タスクごとに:
- ポーリングの前にタスクIDを保存しておけば、workerがリトライしても重複送信や二重課金が発生しない。
- 署名付きアドレスが有効なうちにファイルをダウンロードする。
- ステータスコード、コンテンツタイプ、ファイルサイズを確認し、画像であることを確かめてから受け取る。
- 自分で決めたファイルパスでアップロードする。
- データベースには自分のアドレスを保存し、一時アドレスは短期間の調査用にのみ残す。
よくある質問
ChatGPTのリンクから画像をダウンロードするには?
リンクがまだ開けるうちに、完全なリンク(署名パラメータ付き)で開き、画像ファイルをダウンロードして自分のストレージに保存します。ログインしているブラウザでしか開けないリンクは、すべて一時リンクとして扱ってください。
公式の gen_id ダウンロードAPIはありますか?
ありません。ChatGPTは「gen_id を渡すと画像を返す」APIを一切公開しておらず、この番号は元の会話内でのみ意味を持ちます。
ChatGPTの画像リンクが422を返すのはなぜ?
通常は署名付きリンクに必要なパラメータが欠けています。パスだけをコピーした、または使用したツールが ? 以降の部分を削除したため、リンクが無効になっています。
同じリンクが後で404になるのはなぜ?
署名付きリンクとファイル自体はどちらも一時的です。期限切れ後に ResourceNotFound が返るのは正常で、gen_id でも期限を延長できません。
エクスポートパッケージ内の file-service:// 画像はどう探す?
file-service:// の後ろのファイルIDをコピーし、完全に解凍したエクスポートパッケージ内でこのIDを含むファイル名を検索し、さらにファイルサイズと幅・高さで照合します。
永久の画像アドレスを得るには?
ソースファイルがまだダウンロードできるうちに、自分のストレージにアップロードし、自分のアドレスを保存します。永久かどうかは、サービス側の一時ダウンロードリンクではなく、自分のストレージ次第です。