想从 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 图片链接会过期
一张生成的图,ChatGPT 内部可能有好几种引用:
gen_id:对话里某次生成的编号。file-service://file-...:内部的文件指针,不是网址。chatgpt.com/backend-api/...和files.oaiusercontent.com/...:临时的签名下载链接。
它们各管各的事,没有一个是永久公开的图片地址。
复制来的链接打不开,常见两种情况:
HTTP 422
missing query fields such as p or ts
链接复制得不完整,缺了签名参数,或者粘贴时被某个工具把 ? 后面的部分删掉了。
HTTP 404
ResourceNotFound
签名或文件已经过期、文件被删了,或者请求已经脱离了签发链接时的上下文。拿 gen_id 拼一个看起来对的路径,也恢复不了签名和图片。
从完整的数据导出里找回图片
在 ChatGPT 设置里申请数据导出,完整的导出包里会有 conversations.json 和单独的图片文件。JSON 里一张图大概长这样:
{
"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 每张 $0.03,2K $0.04,4K $0.06。参数和在线试用见 GPT Image 2 模型页,请求格式见创建任务文档。
不怕链接过期的存储做法
每个成功的任务:
- 轮询之前先把任务 ID 存下来,worker 重试时就不会重复提交、重复扣费。
- 趁签名地址还有效,下载文件。
- 检查状态码、内容类型和文件大小,确认是图片再收下。
- 用你自己定的文件路径上传。
- 数据库里存你自己的地址;临时地址只留着短期排查用。
常见问题
怎么从 ChatGPT 链接下载图片?
趁链接还能打开,用完整的链接(带着签名参数)打开,下载图片文件,再存到自己的存储。只在你登录的浏览器里能打开的链接,都当成临时链接。
有没有官方的 gen_id 下载接口?
没有。ChatGPT 没有公开任何「传 gen_id 返回图片」的接口,这个编号只在原来的对话里有意义。
ChatGPT 图片链接为什么返回 422?
一般是签名链接缺了必要的参数。只复制了路径,或者用的工具把 ? 后面的部分删了,链接就失效了。
同一个链接后来为什么变成 404?
签名链接和文件本身都是临时的。过期后返回 ResourceNotFound 是正常的,gen_id 也续不了期。
导出包里的 file-service:// 图片怎么找?
复制 file-service:// 后面的文件 ID,在完整解压的导出包里搜包含这个 ID 的文件名,再用文件大小和宽高核对。
怎么得到一个永久的图片地址?
趁源文件还能下载,把它传到你自己的存储,保存你自己的地址。永久不永久,取决于你自己的存储,而不是服务方的临时下载链接。





