Request
Two input modes, one endpoint. The mode is selected by the Content-Type header.
QUICKEST
GET with query param
GET /api/image?url=https://example.com/image.png
MODE 1
Parse from URL
POST /api/image
Content-Type: application/json
{ "url": "https://example.com/image.png" }
MODE 2
Parse from raw bytes
POST /api/image Content-Type: image/png <raw image bytes as the request body>
Response
Example for a 1280×720 PNG with EXIF (camera + GPS).
{
"success": true,
"source": "url",
"cache": "MISS",
"info": {
"format": "png",
"mime": "image/png",
"width": 1280,
"height": 720,
"bitDepth": 8,
"colorType": "rgba",
"hasAlpha": true,
"byteSize": 482133,
"exif": {
"make": "Canon",
"model": "Canon EOS 5D",
"datetime": "2024:01:02 03:04:05",
"orientation": 1,
"dpiX": 72,
"dpiY": 72,
"gps": { "latitude": 37.7749, "longitude": -122.4194 }
}
}
}
Schema
successboolean— request succeeded
source"url" | "body"— which input mode was used
cache"HIT" | "MISS"— URL mode only, KV cache state
info.format"png" | "jpeg" | "gif" | "webp"— detected from magic bytes
info.mimestring— e.g. image/png
info.width / heightnumber— pixel dimensions
info.bitDepth / colorTypenumber / string— PNG / JPEG detail
info.hasAlphaboolean— alpha channel present
info.animated / frameCountboolean / number— GIF / animated WebP
info.byteSizenumber— total size (remote, from headers)
info.exifobject— make, model, datetime, dpi, orientation, gps
Exif
make · model · datetime · orientation (1–8) · dpiX · dpiY · gps { latitude, longitude }
sources: JPEG APP1 / PNG eXIf / WebP EXIF chunks
Errors
400Missing or invalid url; non-http(s) scheme
413Input exceeded the size cap (head probe / full fallback)
422Not a supported image, or dimensions unreadable
502Upstream URL unreachable or non-200
500Internal error
Client examples
# quick GET (URL mode only)
curl 'https://your-worker.workers.dev/api/image?url=https://example.com/image.png'
# from a URL
curl -X POST https://your-worker.workers.dev/api/image \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/image.png"}'
# from raw bytes
curl -X POST https://your-worker.workers.dev/api/image \
-H 'Content-Type: image/png' \
--data-binary @image.png
// quick GET (URL mode only)
const res0 = await fetch('/api/image?url=' + encodeURIComponent(imageUrl));
// from a URL
const res = await fetch('/api/image', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: imageUrl }),
});
const { success, info } = await res.json();
// from a <input type="file"> File/Blob
const res2 = await fetch('/api/image', {
method: 'POST',
headers: { 'Content-Type': file.type || 'image/png' },
body: file,
});
import requests
# quick GET (URL mode only)
resp = requests.get(
"https://your-worker.workers.dev/api/image",
params={"url": "https://example.com/image.png"},
)
# from a URL
resp = requests.post(
"https://your-worker.workers.dev/api/image",
json={"url": "https://example.com/image.png"},
)
info = resp.json()["info"]
# from raw bytes
with open("image.png", "rb") as f:
resp = requests.post(
"https://your-worker.workers.dev/api/image",
data=f,
headers={"Content-Type": "image/png"},
)