Storage Image Transformations
Transform images with Storage
Supabase Storage offers the functionality to optimize and resize images on the fly. Any image stored in your buckets can be transformed and optimized for fast delivery.
note
Image Resizing is currently enabled for Pro plan and above.
Get a public URL for a transformed image#
Our client libraries methods like getPublicUrl
and createSignedUrl
support the transform
option. This returns the URL that serves the transformed image.
_10supabase.storage.from('bucket').getPublicUrl('image.jpg', {_10 transform: {_10 width: 500,_10 height: 600,_10 },_10})
An example URL could look like this:
https://project_id.supabase.co/storage/v1/render/image/public/bucket/image.jpg?width=500&height=600
Signing URLs with transformation options#
To share a transformed image in a private bucket for a fixed amount of time, provide the transform option when you create the signed URL:
_10supabase.storage.from('bucket').createSignedUrl('image.jpg', 60000, {_10 transform: {_10 width: 200,_10 height: 200,_10 },_10})
The transformation options are embedded into the token attached to the URL — they cannot be changed once signed.
Downloading images#
To download a transformed image, pass the transform
option to the download
function.
_10supabase.storage.from('bucket').download('image.jpg', {_10 transform: {_10 width: 800,_10 height: 300,_10 },_10})
Automatic Image Optimisation (WebP)#
When using the image transformation API, Storage will automatically find the best format supported by the client and return that to the client, without any code change. For instance, if you use Chrome when viewing a jpeg image and using transformation options, you'll see that images are automatically optimized as webp
images.
As a result, this will lower the bandwidth that you send to your users and your application will load much faster.
note
We currently only support WebP. AVIF support will come in the near future.
Disabling automatic optimisation:
In case you'd like to return the original format of the image and opt-out from the automatic image optimization detection, you can pass the format=origin
parameter when requesting a transformed image, this is also supported in the JavaScript SDK starting from v2.2.0
_10await storage.from('bucket').download('image.jpeg', {_10 transform: {_10 width: 200,_10 height: 200,_10 format: 'origin',_10 },_10})
Next.js Loader#
You can use Supabase Image Transformation to optimize your Next.js images using a custom Loader.
To get started, create a supabase-image-loader.js
file in your Next.js project which exports a default function:
_10const projectId = '' // your supabase project id_10_10export default function supabaseLoader({ src, width, quality }) {_10 return `https://${projectId}.supabase.co/storage/v1/render/image/public/${src}?width=${width}&quality=${_10 quality || 75_10 }`_10}
In your nextjs.config.js
file add the following configuration to instruct Next.js to use our custom loader
_10module.exports = {_10 images: {_10 loader: 'custom',_10 loaderFile: './supabase-image-loader.js',_10 },_10}
At this point you are ready to use the Image
component provided by Next.js
_10import Image from 'next/image'_10_10const MyImage = (props) => {_10 return <Image src="bucket/image.png" alt="Picture of the author" width={500} height={500} />_10}
Transformation options#
We currently support a few transformation options focusing on resizing and cropping images.
Resizing#
You can use width
and height
parameters to resize an image to a specific dimension. If only one parameter is specified, the image will be resized and cropped, maintaining the aspect ratio.
Modes#
You can use different resizing modes to fit your needs, each of them uses a different approach to resize the image:
Use the resize
parameter with one of the following values:
-
cover
: resizes the image while keeping the aspect ratio to fill a given size and crops projecting parts. (default) -
contain
: resizes the image while keeping the aspect ratio to fit a given size. -
fill
: resizes the image without keeping the aspect ratio.
Example:
_10supabase.storage.from('bucket').download('image.jpg', {_10 transform: {_10 width: 800,_10 height: 300,_10 resize: 'contain', // 'cover' | 'fill'_10 },_10})
Limits#
- Width and height must be an integer value between 1-2500.
- The image size cannot exceed 25MB.
- The image resolution cannot exceed 50MP.
Supported Image Formats#
Format | Extension | Source | Result |
---|---|---|---|
PNG | png | ☑️ | ☑️ |
JPEG | jpg | ☑️ | ☑️ |
WebP | webp | ☑️ | ☑️ |
AVIF | avif | ☑️ | ☑️ |
GIF | gif | ☑️ | ☑️ |
ICO | ico | ☑️ | ☑️ |
SVG | svg | ☑️ | ☑️ |
HEIC | heic | ☑️ | ❌ |
BMP | bmp | ☑️ | ☑️ |
TIFF | tiff | ☑️ | ☑️ |
Self Hosting#
Our solution to image resizing and optimisation can be self-hosted as with any other Supabase product. Under the hood we use Imgproxy
Imgproxy Configuration:#
Simply deploy an imgproxy container with the following configuration:
_10imgproxy:_10 image: darthsim/imgproxy_10 environment:_10 - IMGPROXY_ENABLE_WEBP_DETECTION=true_10 - IMGPROXY_JPEG_PROGRESSIVE=true
Note: make sure that this service can only be reachable within an internal network and not exposed to the public internet
Storage API Configuration:#
Once Imgproxy is deployed we need to configure a couple of environment variables in your self-hosted storage-api service as follows:
_10ENABLE_IMAGE_TRANSFORMATION=true_10IMGPROXY_URL=yourinternalimgproxyurl.internal.com