Resize, crop, convert and compress stored images on the fly with a URL, on every plan. Each size is made once and served from cache.
Any image in a bucket can be served at another size, fit, format or quality by changing its URL: no copies to upload, no image service to run. Images are resized on your project's server; public ones are cached there, so each size is made once.
#Resize with the SDK
// Public bucket: a URL you can put in <img src>
const { data } = stitchdb.storage.from('avatars').getPublicUrl('ann.png', {
transform: { width: 200, height: 200, resize: 'cover', quality: 75 },
})
// data.publicUrl → https://<project-ref>.p.stitchdb.com/storage/v1/render/image/public/avatars/ann.png?width=200&height=200&resize=cover&quality=75
// Private bucket: a signed URL, or download the resized bytes
const { data: s } = await stitchdb.storage.from('invoices').createSignedUrl('scan.jpg', 3600, { transform: { width: 800 } })
const { data: blob } = await stitchdb.storage.from('invoices').download('scan.jpg', { transform: { width: 800, format: 'origin' } })In Studio, open an image in a public bucket and choose Resized URL to build and preview one.
#Options
| Parameter | Values | Default |
|---|---|---|
width, height | 1 to 2000 pixels (larger values are capped). Give one to keep the aspect ratio. | The original size |
resize | cover (fill the box, crop the rest), contain (fit inside the box), fill (stretch) | cover |
quality | 20 to 100 | 80 |
format | webp, avif, or origin to keep the original format. Without it, browsers that accept WebP get WebP. | Automatic |
The URLs are /storage/v1/render/image/public/<bucket>/<path> (public buckets), /render/image/sign/… (signed URLs) and /render/image/authenticated/… (with the user's access token, checked against your access policies). Originals stay at /storage/v1/object/…. Source images can be up to 25 MB and 16.8 megapixels; PNG, JPEG, WebP, GIF, AVIF, HEIC, BMP and TIFF are read.
#Caching and what counts
- Public renders are cached on your project's server for an hour, separately per size, fit, quality and format. A cached image does not count; the response header
X-Cache: HITshows it. After you replace a file under the same name, its resized versions follow within the hour (add a query like&v=2to see the new one at once). - Signed and authenticated renders are made on every request (they are private), so each one counts. Cache them in your app if you show them often.
- After replacing a file, add a version to its URL (the SDK's
cacheNonceoption, or&v=2) to get the new image at once.
#Limits
| Limit | Free | Pro | Scale | Enterprise |
|---|---|---|---|---|
| Image transformations per month | 1,000 images | 25,000 images | 100,000 images | 1,000,000 images |
The number is image transformations per calendar month (UTC), per project. When a project reaches it, resized URLs answer 429 until the next month while the original files keep working; upgrade the plan for more. Studio shows this month's use in the Resized URL dialog.