Getting started

Integration & migration

Image & video API

Video Player SDK

DAM user guide

API overview

Account

Astro ImageKit SDK

Real-time image & video resizing, automatic optimization, and file uploading in Astro using ImageKit.io.


Astro's built-in image pipeline runs every image through a local sharp process at build time (or through your server's /_image endpoint at request time). That works for a handful of static assets, but it falls apart once you have a large media library, user-uploaded content, or videos: builds get slow, your server does the resizing on every request, and there is no CDN in front of the output.

The Astro ImageKit SDK fixes this by registering a custom image service that emits ImageKit URLs instead. You keep using Astro's native <Image />, <Picture />, and getImage() from astro:assets exactly as before, but the rendered URLs now point at ik.imagekit.io, with transformations, responsive srcset, format conversion, and CDN caching handled by ImageKit. Local imports keep flowing through sharp, so existing pages don't break.

The SDK also ships a <Video> component, an <OgImage> helper for social cards, and a server-side helper for client-side uploads. It works with Astro 3.2 and above. You can view the source code on GitHub.

How it works

The image service is host-aware. For each image, it inspects the src and routes the request to one of two backends:

  1. ImageKit fast path. When src is an ImageKit URL (your urlEndpoint host, any additionalEndpoints host, or a bare/relative path like "folder/photo.jpg"), the service builds an ImageKit URL with the requested transformations and points the browser straight at https://ik.imagekit.io/.... There is no /_image round trip, just a CDN-cached URL with ?tr=... parameters.
  2. Sharp fallback. When src is a local Astro asset (import of an image, or markdown ![](../foo.jpg)) or an absolute URL on a non-ImageKit host, the service delegates to Astro's bundled sharp service, exactly as if you had no integration installed.

You can drop the integration into an existing Astro project without breaking any local-asset usage.

Installation and Setup

Install the Astro SDK via npm, pnpm, or yarn:

Copy
npm install @imagekit/astro
# or
pnpm add @imagekit/astro
# or
yarn add @imagekit/astro

If you also call utilities from @imagekit/javascript directly (e.g. buildSrc, upload), install it explicitly so strict package managers (e.g. pnpm) can resolve it:

Copy
npm install @imagekit/javascript

Configure the Integration

Add the ImageKit integration to your Astro config:

Copy
// astro.config.mjs
import { defineConfig } from 'astro/config';
import imagekit from '@imagekit/astro/integration';

export default defineConfig({
  integrations: [imagekit()],
});

Provide your ImageKit URL endpoint either via the IMAGEKIT_URL_ENDPOINT environment variable in .env:

Copy
IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id

or by passing it directly to the integration:

Copy
// astro.config.mjs
import { defineConfig } from 'astro/config';
import imagekit from '@imagekit/astro/integration';

export default defineConfig({
  integrations: [
    imagekit({
      urlEndpoint: 'https://ik.imagekit.io/your_imagekit_id',
    }),
  ],
});

Get your URL endpoint from the ImageKit dashboard.

The integration sets image.service to @imagekit/astro/image-service. ImageKit URLs are returned directly from the image service and skip Astro's /_image endpoint, so you don't need to add ImageKit hosts to image.domains or image.remotePatterns.

Full list of integration options:

Option Description
urlEndpointThe ImageKit URL endpoint. If omitted, falls back to the IMAGEKIT_URL_ENDPOINT environment variable.
transformationPositionWhere to place transformations in the URL: "query" (default, ?tr=...) or "path" (/tr:.../).

additionalEndpoints

Extra ImageKit URL endpoints (other accounts or custom domains). Hostnames listed here are recognized by the image service so absolute URLs on those hosts also get ImageKit transformations applied.

Example: additionalEndpoints: ['https://ik.imagekit.io/another_account']

TypeScript support

The integration uses Astro's injectTypes() helper to register ImageKit-specific props (urlEndpoint, transformation, queryParameters, transformationPosition) on Astro's Astro.CustomImageProps namespace. You get full autocomplete and type-checking on <Image />, <Picture />, and getImage() for these props.

Run astro sync (or start the dev server) once after installing so Astro picks up the injected types.

Image Component

There is no separate Image component in @imagekit/astro. Continue using Astro's built-in <Image /> (and <Picture />) from astro:assets. Once the integration is installed, every render flows through the ImageKit image service.

In addition to all standard Astro Image props, the integration adds the following ImageKit-specific props:

Notes

  1. src should be a relative path (appended to urlEndpoint) or an absolute ImageKit URL. Local statically-imported images and absolute URLs on non-ImageKit hosts are routed through Astro's sharp service.
  2. The component-level width and height control the rendered HTML dimensions. To force a server-side resize, pass them inside transformation.
Parameter Description and Example

urlEndpoint

The base URL endpoint from your ImageKit dashboard. Overrides the value passed to imagekit({ urlEndpoint }) in astro.config.mjs and the IMAGEKIT_URL_ENDPOINT env var for this image only.

Example: https://ik.imagekit.io/your_imagekit_id

src
(Required)

A relative or absolute path to the image.

  • If a relative path is provided, it is appended to the urlEndpoint.
  • If an absolute path on an ImageKit host is provided, it is used as-is and the urlEndpoint is ignored.
  • Do not include query parameters directly in the src. Use the queryParameters prop instead.
  • When using a Web Proxy, you can pass the full source URL prepended with a /, e.g. /https://example.com/image.jpg.

Examples:
Relative: /default-image.jpg
Absolute: https://ik.imagekit.io/demo/default-image.jpg
Web Proxy: /https://example.com/image.jpg

transformation

An array of transformation objects. Each object can include properties like width, height, rotation, overlays, and advanced effects.

Example: [{ width: 300, height: 300 }]

See all supported transformations.

queryParameters

An object with additional query parameters to append to the URL.

Example: { v: 2 }

transformationPosition

Specifies whether the transformation string is included in the URL path or as a query parameter. Defaults to "query".

Example: "query" or "path"

Basic Usage

Copy
---
import { Image } from 'astro:assets';
---

<Image
  src="/default-image.jpg"
  alt="A sample image"
  width={400}
  height={300}
/>

When IMAGEKIT_URL_ENDPOINT is configured (or you pass urlEndpoint to imagekit() in astro.config.mjs), urlEndpoint does not need to be set per image. To override it for a single image:

Copy
---
import { Image } from 'astro:assets';
---

<Image
  urlEndpoint="https://ik.imagekit.io/another_account"
  src="/default-image.jpg"
  alt="A sample image"
  width={400}
  height={300}
/>

Image with Transformations

Copy
---
import { Image } from 'astro:assets';
---

<Image
  src="/default-image.jpg"
  alt="Resized image"
  width={600}
  height={400}
  transformation={[{ width: 600, height: 400, focus: 'auto' }]}
/>

Astro-Specific Props

All Astro <Image /> props work as documented:

Copy
---
import { Image, Picture } from 'astro:assets';
---

<!-- Quality presets (low | mid | high | max) map to ImageKit q-25/50/75/100 -->
<Image src="/photo.jpg" alt="" width={800} height={600} quality="high" />

<!-- Density-based srcset -->
<Image src="/icon.png" alt="" width={100} height={100} densities={[1.5, 2]} />

<!-- Explicit widths with sizes -->
<Image
  src="/photo.jpg"
  alt=""
  widths={[240, 540, 720]}
  sizes="(max-width: 360px) 240px, (max-width: 720px) 540px, 720px"
  width={720}
  height={480}
/>

<!-- Layout modes (Astro 5+) -->
<Image src="/hero.jpg" alt="" width={1200} height={630} layout="full-width" />

<!-- Loading and priority -->
<Image src="/hero.jpg" alt="" width={1200} height={630} loading="eager" fetchpriority="high" />

<!-- <Picture> works the same way -->
<Picture src="/photo.jpg" alt="" widths={[400, 800, 1200]} formats={['avif', 'webp']} />

Astro's format prop is honored and emitted as f-<format> on the final transformation chain step, so <Picture /> correctly requests one URL per format (f-avif, f-webp, etc.) and <Image format="..."> works as expected. When format is unset, no f- parameter is emitted and ImageKit's default f-auto negotiation applies. Note: imported local assets cause Astro to auto-fill format from the file extension — to force f-auto in that case, override via transformation: [{ format: 'auto' }].

Astro's fit and position props are still ignored — pass crop, focus, etc. via the transformation prop instead.

Delivering Public Media via Web Proxy

If your source files already live on a public URL (for example, assets on another domain), you can use ImageKit Web Proxy and still use Astro's <Image /> for transformations and optimization. Set up a Web Proxy origin and attach it to your URL endpoint by following the Web Proxy guide, then pass the original public URL as part of src (prepended with a /):

Copy
<Image
  src="/https://www.example.com/images/hero.jpg"
  alt="Hero image from web proxy"
  width={1200}
  height={630}
  transformation={[{ width: 1200, height: 630 }]}
/>

With IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/your_imagekit_id, the generated URL pattern is:

Copy
https://ik.imagekit.io/your_imagekit_id/https://www.example.com/images/hero.jpg?tr=w-1200,h-630

You can also use path-style transformations by setting transformationPosition="path":

Copy
<Image
  src="/https://www.example.com/images/banner.jpg"
  alt="Banner from web proxy"
  width={900}
  height={400}
  transformation={[{ width: 900, height: 400 }]}
  transformationPosition="path"
/>

Video Component

The Video component wraps the HTML <video> element and generates ImageKit-optimized video URLs with transformations. It supports all HTML video attributes and also accepts the ImageKit-specific props: urlEndpoint, transformation, transformationPosition, and queryParameters. For the definition of these props, refer to the Image component section.

Copy
---
import { Video } from '@imagekit/astro';
---

<Video
  src="/sample-video.mp4"
  width={640}
  height={360}
  controls
/>

The component-level width and height are HTML attributes only. To resize the video on ImageKit's side, pass them via the transformation prop.

Video with Transformations

Copy
<Video
  src="/sample-video.mp4"
  transformation={[{ width: 640, height: 360 }]}
  width={640}
  height={360}
  controls
/>

Video with HTML Attributes

Copy
<Video
  src="/sample-video.mp4"
  width={640}
  height={360}
  controls
  autoplay
  loop
  muted
  preload="none"
  poster="https://ik.imagekit.io/your_imagekit_id/video-thumbnail.jpg"
/>

Lazy Loading Videos

To lazy load a video, set preload to none and specify a poster image. You can use buildSrc from @imagekit/javascript to generate a thumbnail URL from the video:

Copy
---
import { Video } from '@imagekit/astro';
import { buildSrc } from '@imagekit/javascript';

const posterUrl = buildSrc({
  urlEndpoint: 'https://ik.imagekit.io/your_imagekit_id',
  src: '/video.mp4/ik-thumbnail.jpg',
});
---

<Video
  src="/video.mp4"
  controls
  preload="none"
  poster={posterUrl}
  width={640}
  height={360}
/>

Refer to the create thumbnail documentation for more details on generating a thumbnail from a video.

Height and Width Transformations

Resize images on the fly using the width and height transformation properties:

Copy
---
import { Image } from 'astro:assets';
---

<Image
  src="/profile.png"
  alt="Profile picture"
  width={500}
  height={500}
  transformation={[{ width: 500, height: 500 }]}
/>

The width and height props on the component control the rendered HTML dimensions. The width and height inside transformation control the ImageKit server-side resize. These can differ. For example, you might want a 1200px server resize but a 600px rendered width for retina displays.

Responsive Images

Astro's <Image /> and <Picture /> already provide responsive image generation, and the ImageKit image service plugs into it. Use the standard Astro props to control how srcset and sizes are generated:

Copy
<!-- Density-based srcset for fixed-size elements like icons or logos -->
<Image src="/icon.png" alt="App icon" width={100} height={100} densities={[1, 1.5, 2]} />

<!-- Explicit widths + sizes for fluid images -->
<Image
  src="/photo.jpg"
  alt="Gallery image"
  width={800}
  height={600}
  widths={[300, 600, 900, 1200]}
  sizes="(max-width: 640px) 300px, (max-width: 1024px) 600px, 900px"
/>

<!-- Layout-based responsive (Astro 5+) -->
<Image src="/hero.jpg" alt="" width={1920} height={1080} layout="full-width" />
<Image src="/article.jpg" alt="" width={800} height={600} layout="constrained" />

Each generated srcset entry is rewritten through ImageKit. To prevent upscaling beyond the source asset, the service appends a final c-at_max step (along with the requested width and quality) to every URL.

If you have enabled the "Restrict unnamed transformations" setting (see Basic Security Features), the auto-generated width/crop transformations may cause request failures. Either disable that setting, or render images without responsive variants by setting both widths and densities to undefined (or use a layout that does not generate variants).

Lazy Loading Images

Astro's <Image /> lazy-loads images by default. You can control this behaviour using the loading and fetchpriority attributes:

Copy
<!-- Default: lazy loading -->
<Image src="/profile.png" alt="Lazy loaded" width={500} height={500} />

<!-- Eager loading for above-the-fold images -->
<Image
  src="/hero.jpg"
  alt="Hero image"
  width={1200}
  height={630}
  loading="eager"
  fetchpriority="high"
  decoding="sync"
/>

Lazy Loading with Placeholder

You can show a low-quality, blurred placeholder while the full image loads by using ImageKit's buildSrc utility to generate a placeholder URL and setting it as a background-image on the <Image> element. Then use the onload attribute to remove the background image once the actual image has loaded.

Copy
---
import { Image } from 'astro:assets';
import { buildSrc } from '@imagekit/javascript';

const placeholderUrl = buildSrc({
  urlEndpoint: 'https://ik.imagekit.io/your_imagekit_id',
  src: '/default-image.jpg',
  transformation: [{ quality: 10, blur: 90 }],
});

const placeholderStyle = `background-image: url(${placeholderUrl}); background-size: cover; background-repeat: no-repeat; background-position: center;`;
---

<Image
  src="/default-image.jpg"
  alt="Image with placeholder"
  width={400}
  height={400}
  loading="lazy"
  style={placeholderStyle}
  onload="this.style.backgroundImage='none'"
/>

Chained Transformations

You can chain multiple transformations by passing an array of transformation objects. Each object in the array creates a separate chained transformation step:

Copy
---
import { Image } from 'astro:assets';
---

<Image
  src="/photo.jpg"
  alt="Chained transformations"
  width={400}
  height={300}
  transformation={[
    { width: 400, height: 300 },  // First: resize
    { rotation: 90 },             // Then: rotate
  ]}
/>

Adding Overlays

You can add overlays to images and videos. The overlay can be text, image, video, subtitle, or solid color.

Image Overlay

Copy
<Image
  src="/background.jpg"
  alt="Background with image overlay"
  width={600}
  height={400}
  transformation={[
    { overlay: { type: 'image', input: 'logo.png' } }
  ]}
/>

With independent overlay transformations:

Copy
<Image
  src="/background.jpg"
  alt="Background with resized overlay"
  width={600}
  height={400}
  transformation={[
    {
      overlay: {
        type: 'image',
        input: 'logo.png',
        transformation: [{ width: 100, height: 100 }],
      },
    },
  ]}
/>

Image overlays support a wide range of transformations. Check reference for the complete list of transformations supported on image overlays.

Text Overlay

Copy
<Image
  src="/background.jpg"
  alt="Background with text"
  width={600}
  height={400}
  transformation={[
    {
      overlay: {
        type: 'text',
        text: 'Hello, ImageKit!',
        transformation: [{ fontSize: 20, fontColor: 'FF0000' }],
      },
    },
  ]}
/>

Check the text overlay transformations section for more options related to styling the text.

Solid Color Overlay

Copy
<Image
  src="/background.jpg"
  alt="Background with color overlay"
  width={600}
  height={400}
  transformation={[
    {
      overlay: {
        type: 'solidColor',
        color: 'FF0000',
        transformation: [{ width: 100, height: 100 }],
      },
    },
  ]}
/>

For more options related to styling the solid color overlay, check the solid color overlay transformations section.

Video Overlay (on videos)

Copy
<Video
  src="/background.mp4"
  controls
  transformation={[
    {
      overlay: {
        type: 'video',
        input: 'overlay.mp4',
        timing: { start: 5, duration: 10 },
      },
    },
  ]}
/>

All supported video transformations can also be applied to overlay videos. If you're overlaying an image on a base video, refer to this list for all the transformations supported on image overlays.

Subtitle Overlay (on videos)

Copy
<Video
  src="/background.mp4"
  controls
  transformation={[
    {
      overlay: {
        type: 'subtitle',
        input: 'subtitle.srt',
      },
    },
  ]}
/>

The subtitle overlay can be styled with various properties such as font size, color, and outline. See the subtitle overlay transformations section for all styling options.

For more details on overlay options, positioning, encoding, and styling, see the overlay reference section.

Background Removal Using AI

Copy
<Image
  src="/photo.jpg"
  alt="Background removed"
  width={500}
  height={500}
  transformation={[{ aiRemoveBackground: true }]}
/>

ImageKit supports multiple AI-powered transformations including upscaling, drop shadow, generative fill, and more:

Copy
<!-- AI Drop Shadow -->
<Image
  src="/product.jpg"
  alt="Product with drop shadow"
  width={500}
  height={500}
  transformation={[{ aiDropShadow: true }]}
/>

<!-- AI Upscale -->
<Image
  src="/small-photo.jpg"
  alt="Upscaled photo"
  width={500}
  height={500}
  transformation={[{ aiUpscale: true }]}
/>

Arithmetic Expressions

You can use arithmetic expressions to dynamically compute transformation values:

Copy
<Image
  src="/photo.jpg"
  alt="Half-width image"
  width={300}
  height={200}
  transformation={[{ width: 'iw_div_2' }]}
/>

Check out the Arithmetic Expressions reference for more examples.

OG Image Component

The OgImage component renders OpenGraph and Twitter Card <meta> tags pointing at an ImageKit-optimized image. Use it inside the <head> of your layout. Only src and a title (one of title, ogTitle, or twitterTitle) are required. width and height default to 1200 × 630 and are automatically applied as an ImageKit transformation on top of any extra transformation you pass.

Copy
---
import { OgImage } from '@imagekit/astro';
---

<html>
  <head>
    <OgImage
      src="/og-banner.jpg"
      title="My Page Title"
      description="Preview description for social cards"
      alt="OG image description"
    />
  </head>
  <body>...</body>
</html>

Generated Meta Tags

The component emits the following tags (when applicable):

Copy
<meta property="og:title" content="..." />
<meta property="og:description" content="..." />
<meta property="og:type" content="website" />
<meta property="og:image" content="..." />
<meta property="og:image:secure_url" content="..." />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="..." />
<meta name="twitter:title" content="..." />
<meta name="twitter:description" content="..." />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="..." />
<meta name="twitter:image:alt" content="..." />

ImageKit serves the optimal format automatically based on the requesting client (no format option needed).

Component Props

Option Description
src (Required)Relative path or absolute ImageKit URL for the OG image.
titleShared title for both OG and Twitter tags. At least one of title, ogTitle, or twitterTitle is required.
ogTitle / twitterTitlePlatform-specific title overrides. Falls back to title.
descriptionShared description. Can be overridden with ogDescription or twitterDescription.
ogDescription / twitterDescriptionPlatform-specific description overrides. Falls back to description.
typeOpenGraph object type. Default: "website". Common values: website, article, book, profile.
twitterCardTwitter card type. Default: summary_large_image. Options: summary, summary_large_image, app, player.
altAlt text emitted as both og:image:alt and twitter:image:alt.
urlEndpointOverrides the integration / env var URL endpoint for this OG image only.
transformationOptional array of ImageKit transformations to apply to the OG image. The component always appends a final { width, height } step (using the values below), so you only need to pass transformation for additional effects (overlays, filters, etc.).
queryParametersAdditional query parameters to append to the OG image URL.
transformationPosition"path" or "query" (default).
width / heightOG image dimensions. Defaults: 1200 × 630. Used both for the og:image:width / og:image:height meta tags and as the final ImageKit resize transformation.

getOgImageUrl Helper

If you prefer to render meta tags manually, use the getOgImageUrl helper to build just the URL:

Copy
---
import { getOgImageUrl } from '@imagekit/astro';

const ogImage = getOgImageUrl({
  src: '/og-banner.jpg',
  transformation: [{ width: 1200, height: 630 }],
});
---

<meta property="og:image" content={ogImage} />

Uploading Files

Client-side uploads are powered by the upload function from @imagekit/javascript (install it directly). The function leverages the Upload V1 API, accepting an options object and returning a promise that resolves with the upload response.

For the complete list of upload parameters, the response shape, and SDK validation rules, refer to the JavaScript SDK upload reference.

The Astro SDK provides a server-side helper, getUploadAuthParams, exported from @imagekit/astro/server, to generate the authentication parameters (signature, token, expire) required by the upload endpoint. Use it inside an Astro API route, never on the client.

Upload Flow Overview

  1. Client requests auth parameters. Your client-side code calls an Astro API endpoint to fetch the authentication parameters. You can implement your own application logic in this endpoint to authenticate the user before generating credentials.
  2. File upload. Once the client has the auth parameters, it calls upload() with the file and credentials.

Generating Authentication Parameters

Add your ImageKit keys to .env:

Copy
IMAGEKIT_PRIVATE_KEY=your_private_key
IMAGEKIT_PUBLIC_KEY=your_public_key

Create a server-side API endpoint in Astro that returns the auth parameters. Make sure to add an adapter to your Astro project and render the upload endpoint on demand.

Copy
// src/pages/api/upload-auth.ts
import type { APIRoute } from 'astro';
import { getUploadAuthParams } from '@imagekit/astro/server';

export const prerender = false;

export const GET: APIRoute = async () => {
  // Your application logic to authenticate the user
  // For example, you can check if the user is logged in or has the necessary permissions
  // If the user is not authenticated, you can return an error response

  const authParams = getUploadAuthParams({
    privateKey: import.meta.env.IMAGEKIT_PRIVATE_KEY, // Never expose this on client side
    publicKey: import.meta.env.IMAGEKIT_PUBLIC_KEY,
    // expire: 30 * 60, // Optional. Expiry in seconds; max 1 hour in the future. Default: 30 minutes.
    // token: 'random-token', // Optional. Auto-generated UUID if omitted.
  });

  return new Response(JSON.stringify(authParams), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  });
};

getUploadAuthParams accepts these parameters:

Parameter Type Required Description
privateKeystringYesYour ImageKit private key.
publicKeystringYesYour ImageKit public key.
tokenstringNoCustom token. Auto-generated UUID if omitted.
expirenumberNoExpiry timestamp in seconds. Defaults to 30 minutes from now.

It returns an object with token, signature, expire, and publicKey.

getUploadAuthParams must only be called on the server. Never expose your private key to the client.

Upload Example and Error Handling

The example below demonstrates how to use the upload function on the client to upload a file, including error handling for the various upload scenarios. Copy and paste this code into a .astro page and customize as needed.

Copy
---
// src/pages/upload.astro
---

<html>
  <body>
    <input type="file" id="file-input" />
    <button id="upload-btn">Upload</button>
    <div>Upload progress: <progress id="upload-progress" value="0" max="100"></progress></div>
    <pre id="result"></pre>

    <script>
      import {
        upload,
        ImageKitAbortError,
        ImageKitInvalidRequestError,
        ImageKitServerError,
        ImageKitUploadNetworkError,
      } from '@imagekit/javascript';

      const fileInput = document.getElementById('file-input') as HTMLInputElement;
      const uploadBtn = document.getElementById('upload-btn') as HTMLButtonElement;
      const progressBar = document.getElementById('upload-progress') as HTMLProgressElement;
      const result = document.getElementById('result') as HTMLPreElement;

      // Create an AbortController instance to provide an option to cancel the upload if needed.
      const abortController = new AbortController();

      /**
       * Authenticates and retrieves the necessary upload credentials from the server.
       */
      const authenticator = async () => {
        const response = await fetch('/api/upload-auth');
        if (!response.ok) {
          const errorText = await response.text();
          throw new Error(`Request failed with status ${response.status}: ${errorText}`);
        }
        const data = await response.json();
        const { signature, expire, token, publicKey } = data;
        return { signature, expire, token, publicKey };
      };

      uploadBtn.addEventListener('click', async () => {
        const file = fileInput.files?.[0];
        if (!file) {
          alert('Please select a file to upload');
          return;
        }

        // Retrieve authentication parameters for the upload.
        let authParams;
        try {
          authParams = await authenticator();
        } catch (authError) {
          console.error('Failed to authenticate for upload:', authError);
          return;
        }
        const { signature, expire, token, publicKey } = authParams;

        try {
          const response = await upload({
            // Authentication parameters
            expire,
            token,
            signature,
            publicKey,
            file,
            fileName: file.name,
            // Progress callback to update upload progress
            onProgress: (event) => {
              progressBar.value = (event.loaded / event.total) * 100;
            },
            // Abort signal to allow cancellation of the upload if needed.
            abortSignal: abortController.signal,
          });
          console.log('Upload response:', response);
          result.textContent = JSON.stringify(response, null, 2);
        } catch (error) {
          // Handle specific error types provided by the ImageKit SDK.
          if (error instanceof ImageKitAbortError) {
            console.error('Upload aborted:', error.reason);
          } else if (error instanceof ImageKitInvalidRequestError) {
            console.error('Invalid request:', error.message);
          } else if (error instanceof ImageKitUploadNetworkError) {
            console.error('Network error:', error.message);
          } else if (error instanceof ImageKitServerError) {
            console.error('Server error:', error.message);
          } else {
            console.error('Upload error:', error);
          }
        }
      });
    </script>
  </body>
</html>

Loading Images from Your ImageKit Media Library

You can use Astro Content Collections together with the @imagekit/nodejs SDK to power gallery and listing pages directly from your ImageKit Media Library, without hand-maintaining a list of URLs.

Install the Node SDK as a dev dependency (it's only used at build time):

Copy
npm install -D @imagekit/nodejs

Define a collection backed by client.assets.list(). The Node SDK returns an array of File | Folder objects directly, so pass type: 'file' to exclude folders and fileType: 'image' to limit results to images. Shape each entry as { id, ...data }. Astro's content layer treats the top-level id as the entry key and validates everything else against your schema:

Copy
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod';
import ImageKit from '@imagekit/nodejs';
import type { Files } from '@imagekit/nodejs/resources/files/files';

const client = new ImageKit({
  privateKey: import.meta.env.IMAGEKIT_PRIVATE_KEY,
});

const gallery = defineCollection({
  loader: async () => {
    const assets = await client.assets.list({
      type: 'file',       // exclude folders
      fileType: 'image',  // only image files
      skip: 0,
      limit: 50,
    });

    return assets
      .filter((asset): asset is Files.File =>
        asset.type === 'file' && !!asset.fileId && !!asset.url
      )
      .map((asset) => ({
        id: asset.fileId ?? '',
        url: asset.url ?? '',
        width: asset.width ?? 0,
        height: asset.height ?? 0,
        name: asset.name ?? '',
        tags: asset.tags ?? [],
      }));
  },
  schema: z.object({
    url: z.string().url(),
    width: z.number(),
    height: z.number(),
    name: z.string(),
    tags: z.array(z.string()),
  }),
});

export const collections = { gallery };

After adding the collection, run astro sync (or start the dev server) so Astro generates the collection types used by getCollection().

Render with <Image> from astro:assets. The integration's image service generates the ImageKit CDN URL with the correct transformations:

Copy
---
import { Image } from 'astro:assets';
import { getCollection } from 'astro:content';

const photos = await getCollection('gallery');
---

{photos.map(({ data }) => (
  <Image
    src={data.url}
    width={data.width}
    height={data.height}
    alt={data.name}
    transformation={[{ width: 400, height: 300, focus: 'auto' }]}
  />
))}

Keep your privateKey in a server-only env var (e.g. IMAGEKIT_PRIVATE_KEY in .env, never prefixed with PUBLIC_). Collection loaders run at build time (or in SSR endpoints), never in the browser.

Supported Transformations

The SDK gives a name to each transformation parameter (e.g. height maps to h, width maps to w). If the property does not match any of the following supported options, it is added as is in the URL.

If you want to generate transformations without any modifications, use the raw parameter. For example, the SDK doesn't provide a nice way to write conditional transformations, so you can use the raw parameter to add them as is.

Check transformation documentation for a complete reference on all transformations supported by ImageKit.

Transformation NameURL Parameter
widthw
heighth
aspectRatioar
qualityq
aiRemoveBackgrounde-bgremove (ImageKit powered)
aiRemoveBackgroundExternale-removedotbg (Using third party)
aiUpscalee-upscale
aiRetouche-retouch
aiVariatione-genvar
aiDropShadowe-dropshadow
aiChangeBackgrounde-changebg
cropc
cropModecm
xx
yy
xCenterxc
yCenteryc
focusfo
formatf
radiusr
backgroundbg
borderb
rotationrt
blurbl
namedn
dprdpr
progressivepr
losslesslo
trimt
metadatamd
colorProfilecp
defaultImagedi
originalorig
videoCodecvc
audioCodecac
grayscalee-grayscale
contrastStretche-contrast
shadowe-shadow
sharpene-sharpen
unsharpMaske-usm
gradiente-gradient
flipfl
opacityo
zoomz
pagepg
startOffsetso
endOffseteo
durationdu
streamingResolutionssr
overlayGenerates the correct layer syntax for image, video, text, subtitle, and solid color overlays.
rawThe string provided in raw will be added in the URL as is.

Handling Unsupported Transformations

If you specify a transformation parameter that is not explicitly supported by the SDK, it is added as-is in the generated URL. This provides flexibility for using new or custom transformations without waiting for an SDK update. Add @ts-ignore to avoid TypeScript errors, or use the raw parameter.

Copy
<Image
  src="/photo.jpg"
  alt="Custom transformation"
  width={500}
  height={500}
  transformation={[
    // @ts-ignore
    { unsupportedTransformation: 'value' },
  ]}
/>

Or use the raw parameter:

Copy
<Image
  src="/photo.jpg"
  alt="Raw transformation"
  width={500}
  height={500}
  transformation={[
    { raw: 'unsupportedTransformation-value' },
  ]}
/>

Overlay Reference

This SDK provides overlay as a transformation parameter. The overlay can be a text, image, video, subtitle, or solid color.

Overlays in ImageKit are applied using layers, allowing you to stack multiple overlays on top of each other. Each overlay can be styled and positioned independently. For more details, refer to the layer documentation.

The SDK automatically generates the correct layer syntax for image, video, text, subtitle, and solid color overlays. You can also specify the overlay position, size, and other properties.

The table below outlines the available overlay configuration options:

Option Description and Example
type
(Required)
Specifies the type of overlay. Supported values: text, image, video, subtitle, solidColor. Example: type: "text"
text
(Required for text overlays)
The text content to display. Example: text: "ImageKit"
input
(Required for image, video, or subtitle overlays)
Relative path to the overlay asset. Example: input: "logo.png" or input: "overlay-video.mp4"
color
(Required for solidColor overlays)
RGB/RGBA hex code or color name for the overlay color. Example: color: "FF0000"
encodingAccepted values: auto, plain, base64. Check this for more details. Example: encoding: "auto"
transformationAn array of transformation objects to style the overlay independently of the base asset. Each overlay type has its own set of supported transformations.
  • For example, for text overlays, you can specify fontSize, fontColor, background, etc. Example: transformation: [{ fontSize: 20, fontColor: "FF0000" }]. Check out the text overlay transformations section for more options.
  • For image overlays, you can specify width, height, radius, etc. Example: transformation: [{ width: 100, height: 100 }]. Check reference for complete list of transformations supported on image overlays.
  • For video overlays, you can specify width, height, rotation, etc. Example: transformation: [{ width: 100, height: 100 }]. Check reference for complete list of transformations supported on video overlays.
  • For subtitle overlays, you can specify fontSize, fontColor, background, etc. Example: transformation: [{ fontSize: 20, fontColor: "FF0000" }]. Check out the subtitle overlay transformations section for more options.
  • For solid color overlays, you can specify width, height, radius, etc. Example: transformation: [{ width: 100, height: 100 }]. Check out the solid color overlay transformations section for more options.
positionSets the overlay’s position relative to the base asset. Accepts an object with x, y, or focus. Example: position: { x: 10, y: 20 } or position: { focus: "center" }
timing(For video base) Specifies when the overlay appears using start, duration, and end (in seconds); if both duration and end are set, duration is ignored. Example: timing: { start: 5, duration: 10 }

Encoding Options

Overlay encoding options define how the overlay input is converted for URL construction. When set to auto, the SDK automatically determines whether to use plain text or Base64 encoding based on the input content.

For text overlays:

  • If auto is used, the SDK checks the text overlay input: if it is URL-safe, it uses the format i-{input} (plain text); otherwise, it applies Base64 encoding with the format ie-{base64_encoded_input}.
  • You can force a specific method by setting encoding to plain (always use i-{input}) or base64 (always use ie-{base64}).
  • Note: In all cases, the text is percent-encoded to ensure URL safety.

For image, video, and subtitle overlays:

  • The input path is processed by removing any leading/trailing slashes and replacing inner slashes with @@ when plain is used.
  • Similarly, if auto is used, the SDK determines whether to apply plain text or Base64 encoding based on the characters present.
  • For explicit behavior, use plain or base64 to enforce the desired encoding.

Use auto for most cases to let the SDK optimize encoding, and use plain or base64 when a specific encoding method is required.

Solid Color Overlay Transformations

OptionDescriptionExample
widthSpecifies the width of the solid color overlay block (in pixels or as an arithmetic expression).width: 100
heightSpecifies the height of the solid color overlay block (in pixels or as an arithmetic expression).height: 50
radiusSpecifies the corner radius of the solid color overlay block or shape. Can be a number or "max" for circular/oval shapes.radius: "max"
alphaSpecifies the transparency level of the solid color overlay. Supports integers from 1 (most transparent) to 9 (least transparent).alpha: 5
backgroundSpecifies the background color of the solid color overlay. Accepts an RGB hex code, an RGBA code, or a standard color name.background: "red"
gradientOnly works if base asset is an image. Creates a linear gradient with two colors. Pass true for a default gradient, or provide a string for a custom gradient. Learn moregradient: true

Text Overlay Transformations

OptionDescriptionExample
widthSpecifies the maximum width (in pixels) of the overlaid text. The text wraps automatically, and arithmetic expressions are supported (e.g., bw_mul_0.2 or bh_div_2).width: 400
fontSizeSpecifies the font size of the overlaid text. Accepts a numeric value or an arithmetic expression.fontSize: 50
fontFamilySpecifies the font family of the overlaid text. Choose from the supported fonts or provide a custom font.fontFamily: "Arial"
fontColorSpecifies the font color of the overlaid text. Accepts an RGB hex code, an RGBA code, or a standard color name.fontColor: "FF0000"
innerAlignmentSpecifies the inner alignment of the text when it doesn’t occupy the full width. Supported values: left, right, center.innerAlignment: "center"
paddingSpecifies the padding around the text overlay. Can be a single integer or multiple values separated by underscores; arithmetic expressions are accepted.padding: 10
alphaSpecifies the transparency level of the text overlay. Accepts an integer between 1 and 9.alpha: 5
typographySpecifies the typography style of the text. Supported values: b for bold, i for italics, and b_i for bold with italics.typography: "b"
backgroundSpecifies the background color of the text overlay. Accepts an RGB hex code, an RGBA code, or a color name.background: "red"
radiusSpecifies the corner radius of the text overlay. Accepts a numeric value or max for circular/oval shape.radius: "max"
rotationSpecifies the rotation angle of the text overlay. Accepts a numeric value for clockwise rotation or a string prefixed with N for counterclockwise rotation.rotation: 90
flipSpecifies the flip option for the text overlay. Supported values: h, v, h_v, v_h.flip: "h"
lineHeightSpecifies the line height for multi-line text. Accepts a numeric value or an arithmetic expression.lineHeight: 20

Subtitle Overlay Transformations

OptionDescriptionExample
backgroundSpecifies the subtitle background color using a standard color name, RGB color code, or RGBA color code.background: "blue"
fontSizeSets the font size of subtitle text.fontSize: 16
fontFamilySets the font family of subtitle text.fontFamily: "Arial"
colorSpecifies the font color of subtitle text using standard color name, RGB, or RGBA color code.color: "FF0000"
typographySets the typography style of subtitle text. Supported values: b, i, b_i.typography: "b"
fontOutlineSpecifies the font outline for subtitles. Requires an outline width and color separated by an underscore.fontOutline: "2_blue"
fontShadowSpecifies the font shadow for subtitles. Requires shadow color and indent separated by an underscore.fontShadow: "blue_2"