Image & Video APIs

Next.js image and video upload

Last updated: Feb-26-2026

The Next.js SDK provides React components that make it easy to add file upload functionality to your Next.js application. These components wrap the Cloudinary Upload Widget, giving you a ready-made, responsive UI that supports uploads from multiple sources including local files, camera, URL, and more.

You can implement uploads using either unsigned upload presets for quick setup, or signed uploads with server-side signature generation for enhanced security.

Upload options

The Next.js SDK offers two components for uploading assets. Both components open the Cloudinary Upload Widget, a ready-made, responsive user interface that enables your users to upload files from a variety of sources (local files, camera, URL, and more).

  • CldUploadButton - A simple button component that opens the upload widget when clicked. Best for straightforward upload functionality.
  • CldUploadWidget - A flexible component that provides full programmatic control over the upload widget, including the ability to open it from custom UI elements.

Both components provide access to callback functions, configuration options, and instance methods to customize the upload experience for your users.

Using CldUploadButton

The CldUploadButton component provides the simplest way to add upload functionality to your Next.js app. It renders a button that, when clicked, opens the Cloudinary Upload Widget.

Basic usage

This example shows the minimal setup required to add an upload button to your Next.js application. The uploadPreset prop specifies which upload preset to use, which defines the upload configuration:

Note
For quick setup, an unsigned upload preset is required. For production applications requiring enhanced security, configure signed uploads with server-side signature generation. For signed uploads, an upload preset is optional.

Handling upload results

Use the onSuccess callback to handle successful uploads:

Customizing the button

The CldUploadButton component inherits all props from CldUploadWidget (including callback functions like onSuccess, onQueuesEnd, etc.), however, it handles children differently.

Button-specific props:

  • className - CSS class name for styling
  • onClick - Click event handler function

All other HTML button props (like style, disabled, type, etc.) are spread onto the <button> element, giving you full control over the button's appearance and behavior.

Button content:

You can customize the content inside the button by placing elements between the opening and closing <CldUploadButton> tags. If no content is provided, the button displays "Upload" by default.

Note
In CldUploadWidget, the content between the tags is a render function that receives widget state. In CldUploadButton, the content is simply the button's label or inner elements.

Example with custom styling:

Create styling for your button in CSS, for example, in globals.css:

Set the className prop to the name of the class, in this case, custom-button:

This renders a styled button with the text "Upload Files":

Example with default label:

If you don't provide content between the tags, the button displays "Upload":

This renders a styled button with the text "Upload":

Example with onClick handler:

You can add custom logic when the button is clicked, before the upload widget opens:

Using CldUploadWidget

The CldUploadWidget component provides more control over the upload experience, allowing you to customize when and how the widget opens.

Note
The CldUploadWidget won't render any UI by default. It uses a render prop pattern where you provide a function that returns your custom UI, giving you complete control over the trigger element and interface.

Basic usage

Render function parameters

The render function receives an object with the following parameters:

Parameter Type Description
cloudinary Cloudinary The Cloudinary instance which creates and manages the Widget instance
error string The error, if any, produced by an upload widget action
isLoading boolean Designates whether the upload widget is loading and initializing
results object The event that triggered the results and information related to that event, which can include upload results
widget Widget The widget instance attached to the current component
open function Instance method to open the widget
close function Instance method to close the widget
hide function Instance method to hide the widget
show function Instance method to show the widget
minimize function Instance method to minimize the widget
destroy function Instance method to destroy the widget
isDestroyed function Instance method to check if widget is destroyed
isShowing function Instance method to check if widget is showing
isMinimized function Instance method to check if widget is minimized
update function Instance method to update widget options

Example accessing multiple parameters:

Handling upload events

The widget provides callback functions for different events in the upload lifecycle. There are two types of callbacks:

  1. Callback Functions - Receive both results and options (including widget instance and instance methods)
  2. Action Callbacks - Receive only results (designed for Server Actions workflow)

Callback Functions

These callbacks receive (results, options) or (error, options) parameters:

Callback Description
onAbort Triggered when upload is aborted
onBatchCancelled Triggered when batch upload is cancelled
onClose Triggered when widget is closed
onDisplayChanged Triggered when widget display changes
onError Triggered when an error occurs
onOpen Triggered when widget opens (receives only widget parameter)
onPublicId Triggered when public ID is generated
onQueuesEnd Triggered when all uploads in queue complete
onQueuesStart Triggered when upload queue starts
onRetry Triggered when upload is retried
onShowCompleted Triggered when completed uploads are shown
onSourceChanged Triggered when upload source changes
onSuccess Triggered on successful upload
onTags Triggered when tags are processed
onUpload (Deprecated) Use onSuccess instead
onUploadAdded Triggered when file is added to upload queue

Example:

This example demonstrates using multiple callback functions to handle different stages of the upload process. It uses onSuccess to capture upload results, onQueuesEnd to automatically close the widget after all uploads complete, and onError to handle any upload failures:

Action Callbacks

These callbacks receive only the (results) parameter for use with Server Actions:

Action Callback Description
onAbortAction Action version of onAbort
onBatchCancelledAction Action version of onBatchCancelled
onCloseAction Action version of onClose
onDisplayChangedAction Action version of onDisplayChanged
onPublicIdAction Action version of onPublicId
onQueuesEndAction Action version of onQueuesEnd
onQueuesStartAction Action version of onQueuesStart
onRetryAction Action version of onRetry
onShowCompletedAction Action version of onShowCompleted
onSourceChangedAction Action version of onSourceChanged
onSuccessAction Action version of onSuccess
onTagsAction Action version of onTags
onUploadAddedAction Action version of onUploadAdded

Tip
For more details on when each event triggers, see the Upload Widget events documentation.

Callback parameters

Most callbacks provide parameters with the following structure:

For Callback Functions:

  • results (object) - Contains event (string) and info (object with upload details like public_id, secure_url, width, height, etc.)
  • options (object) - Contains widget (Widget instance) and instance methods

For Action Callbacks:

  • results (object) - Contains event and info only

Example results object:

Instance methods

The Upload Widget exposes instance methods that provide greater control over the upload experience. These are available through the children function parameters or callback options:

Method Description
open() Renders an existing widget currently in memory, but not currently displayed
close() Closes and resets the widget to its initial state without removing it from memory
hide() Hides a previously rendered widget while retaining its current state in memory
show() Renders a previously hidden widget
minimize() Minimizes the widget
destroy() Closes the widget and completely removes it from the DOM. Returns a promise that resolves upon cleanup completion
isShowing() Returns whether the widget is currently visible
isMinimized() Returns whether the widget is currently minimized
isDestroyed() Returns whether the destroy method was called on this instance
update(options) Updates a widget currently in memory with new options

Example using instance methods:

This example demonstrates how to programmatically control the upload widget using instance methods. It creates multiple buttons that allow you to open, close, hide, show, and minimize the widget, as well as check its current state:

Signed vs unsigned uploads

There are two options when using the upload components: signed and unsigned. These options allow you to control the amount of security and restrictions you place on uploads.

Unsigned uploads:

  • Simpler to implement (no server-side code required)
  • Require an unsigned upload preset
  • Anyone with the preset name can upload
  • Best for: Public assets, demos, prototypes

Signed uploads:

  • More secure (requires server-side signature generation)
  • Prevents unauthorized uploads
  • Allows more control over upload parameters
  • Best for: Production applications, restricted uploads, sensitive content

Tip
To learn more about the differences, see the authenticated upload requests documentation.

Using unsigned uploads

Unsigned uploads are the simplest option and work well for public assets. All the examples in Using CldUploadButton and Using CldUploadWidget show unsigned uploads.

For unsigned uploads, you need to set the uploadPreset prop to your unsigned upload preset.

For CldUploadButton:

For CldUploadWidget:

Caution
Unsigned uploads should only be used when you don't need to restrict who can upload or what can be uploaded. Anyone with access to your upload preset name can upload to your account.

Using signed uploads

Signed upload requests provide enhanced security for your file uploads. This helps prevent unauthorized uploads to your Cloudinary account.

For signed uploads, you need to set the signatureEndpoint prop to an API endpoint that'll provide the signature.

For CldUploadButton:

For CldUploadWidget:

You can optionally also provide a signed upload preset in the uploadPreset prop, but this isn't required for signed uploads.

For CldUploadButton:

For CldUploadWidget:

Creating the signature endpoint

When working in Next.js, you can use the Cloudinary Node SDK in a server-side API route to sign your upload requests.

Step 1: Install the Cloudinary Node SDK

Step 2: Set up environment variables

Add your Cloudinary API credentials to your environment variables:

Caution
Never expose your CLOUDINARY_API_SECRET to the client. Keep it in server-side environment variables only (without the NEXT_PUBLIC_ prefix).

Step 3: Create the API endpoint

The implementation differs based on whether you're using the App Router or Pages Router.

For App Router (Next.js 13+):

Create a new file at app/api/sign-cloudinary-params/route.js:

For Pages Router:

Create a new file at pages/api/sign-cloudinary-params.js:

That's it! The upload components will now automatically call your signature endpoint before each upload to generate a secure signature.

Tip
Learn more about generating authentication signatures in the Cloudinary documentation.

Configuration

Both CldUploadButton and CldUploadWidget support configuration through props.

Cloudinary environment configuration

The upload components automatically use environment variables for Cloudinary configuration:

  • NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME - Your Cloudinary cloud name (required)
  • NEXT_PUBLIC_CLOUDINARY_API_KEY - Your API key (optional, for signed uploads)
  • CLOUDINARY_API_SECRET - Your API key (optional, for signed uploads)

Tip
Using environment variables is the recommended approach. The components will automatically detect and use these values.

You can also use the config prop to configure Cloudinary settings:

Caution
Environment variables take precedence over the config prop. If you have NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME set, it will override any cloudName specified in the config prop. To use the config prop values, you must remove or unset the corresponding environment variables.

Upload Widget configuration options

You can pass any Upload Widget configuration option using the options prop:

Common configuration options include:

Option Type Description
sources array Upload sources (e.g., ['local', 'camera', 'url'])
multiple boolean Allow multiple file uploads
maxFiles number Maximum number of files
maxFileSize number Maximum file size in bytes
clientAllowedFormats array Allowed file formats (e.g., ['jpg', 'png'])
resourceType string Resource type ('image', 'video', 'raw', 'auto')
folder string Upload folder path
tags array Tags to apply to uploaded assets
context object Contextual metadata
styles object Custom widget styling
text object Custom widget text/labels
language string Widget language (e.g., 'en', 'es')
showAdvancedOptions boolean Show advanced upload options
showCompletedButton boolean Show completed button
showUploadMoreButton boolean Show upload more button
showSkipCropButton boolean Show skip crop button
cropping boolean Enable image cropping
croppingAspectRatio number Aspect ratio for cropping
croppingDefaultSelectionRatio number Default selection ratio
croppingShowDimensions boolean Show dimensions during cropping
croppingCoordinatesMode string Coordinates mode ('custom' or 'face')
croppingShowBackButton boolean Show back button in cropping view

Example with multiple configuration options:

Tip
For a complete list of configuration options, see the Upload Widget reference.

Related topics

✔️ Feedback sent!

Rate this page:

one star two stars three stars four stars five stars