Skip to Content
Mux Docs: Home

Upload from your web app with Mux Uploader

Allow your users to upload content directly to Mux.

<mux-uploader> is a drop-in web component that makes it easy to upload video files to Mux.

This component allows you to build a fully-functional video upload UI in your application using a single line of code.

Quick start

Here are some examples of Mux Uploader in action.

HTML element

First, install it:

npm i @mux/mux-uploader

Then, import it:

import '@mux/mux-uploader';

Finally, add the HTML tag:

<div>
<mux-uploader></mux-uploader>
</div>

Alternatively, use the CDN hosted version of this package:

<script src="https://cdn.jsdelivr.net/npm/@mux/mux-uploader@1.0.0-beta.6"></script>

If you are using ECMAScript modules, you can also load the mux-uploader.mjs file with type=module:

<script
type="module"
src="https://cdn.jsdelivr.net/npm/@mux/mux-uploader@1.0.0-beta.6/dist/mux-uploader.mjs"
></script>

React

First, install it:

npm i @mux/mux-uploader-react

Then, import it:

import MuxUploader from '@mux/mux-uploader-react';

Finally, add the JSX tag:

<div>
<MuxUploader />
</div>

Upload a video

<mux-uploader> takes care of rendering a file selector, uploading your video file, displaying progress updates to the user, handling retries, and more.

There's only one required attribute that you must set to upload your file – the endpoint attribute. It looks like this:

<mux-uploader
endpoint="https://my-authenticated-url/storage?your-url-params"
></mux-uploader>

The endpoint attribute provides mux-uploader with a direct upload URL that will receive the video file you're uploading.

You can generate a signed direct upload URL by making a server-side API call to Mux's Create Direct Upload endpoint.

In a successful API response, you will receive a unique signed upload URL that can then be passed along to your client application and set as the endpoint property on a mux-uploader element. The URL for a Direct Upload looks like "https://storage.googleapis.com/video...".

In the following examples, you will replace the value of the endpoint property with your unique direct upload URL.

HTML element

<mux-uploader
    endpoint="https://httpbin.org/put"
></mux-uploader>

React

import MuxUploader from "@mux/mux-uploader-react"; 

export default function App() {
  return (
    <MuxUploader endpoint="https://httpbin.org/put" />
  );
}

Fetching the upload URL async

At the time you render the <mux-uploader>, you may not have the direct upload URL yet. Instead, you might want to retrieve it async from your server after a user selects a file. You can do that by setting the endpoint property value to a custom function instead of a URL.

<mux-uploader></mux-uploader>
<script>
const muxUploader = document.querySelector("mux-uploader");
/*
Endpoint should be a function that returns a promise and resolves
with a string for the upload URL.
*/
muxUploader.endpoint = function () {
/*
In this example, your server endpoint would return the upload URL
in the response body "https://storage.googleapis.com/video..."
*/
return fetch("/your-server/api/create-upload").then((res) => res.text());
};
</script>

Customizing the appearance

We've built <mux-uploader> with sensible styling defaults that might Just Work™ for your application. Of course, there are times when you'll want to change the default appearance or behavior to something a little more custom.

Basic customization with slots

<mux-uploader> uses HTML slots, allowing you to replace default UI elements with your own HTML elements.

View the slots reference to learn about all of the available slots in <mux-uploader>.

Example: using your own file selector

You can use your own button with the slot="file-select" attribute.

This is really handy if, for example, you already have a .btn class that styles buttons in your application.

<style>
  .btn {
    /* your styles for .btn */
    padding: 6px 8px;
    border: 1px solid #0d9488;
    border-radius: 5px;
    font-size: 24px;
    color: #FFF;
    background: #D91377;
    cursor: pointer;
  }
</style>

<!-- slot="file-select" tells mux-uploader to replace the default file selector with a button.btn element -->
<mux-uploader endpoint="https://httpbin.org/put">
  <button class="btn" type="button" slot="file-select">Pick a file</button>
</mux-uploader>

Basic customization with CSS variables

<mux-uploader> exposes CSS variables that allow you to change the default styling of the uploader UI.

View the CSS variables reference to learn about all of the available CSS variables in <mux-uploader>.

Styling with React

If you're using React to build your application, you may be using CSS-in-JS or a CSS framework to handle styling. Here's an example of how you can style Mux Uploader using CSS modules:

import styles from "./Styles.module.css";
import MuxUploader, { MuxUploaderFileSelect, MuxUploaderProgress } from "@mux/mux-uploader-react"; 

export default function App() {
  return (
    <div>
        <h2 className={styles.heading}>Mux Uploader with CSS Modules</h2>
        <MuxUploader id="css-modules-uploader" className={styles.uploader} endpoint="https://httpbin.org/put" />
        <MuxUploaderFileSelect muxUploader="css-modules-uploader">
        <button className={styles.button}>Pick your video</button>
        </MuxUploaderFileSelect>
        <MuxUploaderProgress type="percentage" muxUploader="css-modules-uploader" className={styles.progress} />
    </div>
  );
}

Another common approach to styling React applications is using Tailwind, so here's an example of styling Mux Uploader using the Tailwind framework:

import MuxUploader, { MuxUploaderFileSelect, MuxUploaderProgress, MuxUploaderDrop } from "@mux/mux-uploader-react"; 

export default function App() {
  return (
    <div className="p-4">
        <h2 className="text-lg text-slate-800 mb-2 font-bold">Mux Uploader with Tailwind example</h2>
        <MuxUploader id="my-uploader" className="hidden" endpoint="https://httpbin.org/put" />

        <MuxUploaderDrop
            id="my-uploader"
            className="border border-4 border-slate-200 rounded shadow mb-4"
            overlay
            overlayText="Let it go"
        >
            <span slot="heading" className="text-slate-600 text-xl mb-2">Drop your favorite video</span>
            <span slot="separator" className="text-slate-400 text-sm italic">— or —</span>
            
            <MuxUploaderFileSelect muxUploader="my-uploader">
                <button
                    className="bg-pink-500 hover:bg-pink-600 my-2 px-4 py-2 rounded text-white text-sm"
                >
                    Select from a folder
                </button>
            </MuxUploaderFileSelect>
        </MuxUploaderDrop>

        <MuxUploaderProgress
            type="percentage"
            muxUploader="my-uploader"
            className="text-3xl text-orange-600 underline"
        />
    </div>
  );
}

Example: Customizing the progress bar

By default, the progress bar color is black with a gray background. Here's how you can change the progress bar color to purple:

<style>
  mux-uploader {
    --progress-bar-fill-color: #7e22ce;
  }
</style>

<mux-uploader endpoint="https://httpbin.org/put">
  <button class="btn" type="button" slot="file-select">Pick a file</button>
</mux-uploader>

Advanced customization

If you're looking to build a custom UI for uploading videos in your application, advanced customization is for you.

You can use the individual web components that come packaged with <mux-uploader> to build out a custom upload UI that meets your needs.

To use this approach, add an id attribute to your <mux-uploader> element with a unique value.

You can then associate the <mux-uploader> element with any of the packaged components by adding a mux-uploader="" attribute to each component.

<!-- add a mux-uploader tag with an id attribute and hide it with CSS -->
<mux-uploader id="my-uploader" style="display: none;"></mux-uploader>
<!-- ...then, somewhere else in your app, add a reference back to it -->
<mux-uploader-file-select mux-uploader="my-uploader">
<button slot="file-select">Pick a video</button>
</mux-uploader-file-select>

If you'd like to prevent certain components from rendering within the <mux-uploader> element, you can pass attributes that will disable their output.

Possible values include no-drop, no-progress, no-retry, and no-status

<!-- This will remove file drag-and-drop functionality and remove the status messages -->
<mux-uploader no-drop no-status></mux-uploader>

Incorporating Mux Uploader into a form

There may be times when you want to include a video upload field as part of a larger form in your application. For example, imagine we're building a video contest submission form. We might have other form fields to associate with the video, like a video_title, video_description etc.

One way you can solve for this is to create the Direct Upload URL on the server when a request to your form page is made. You'd then retrieve the resulting upload URL and upload id and send it down to the client.

You might consider keeping your form submit button disabled until you've received a success event from Mux Uploader. You can find an example of this flow using Next.js on this CodeSandbox.

Web components reference

Here are all of the available web components you can use with <mux-uploader>:

Component nameDescription
<mux-uploader>Manages the uploading state. Required
<mux-uploader-status>A single-line message informing the user of the current status of the upload, i.e. Upload complete!
<mux-uploader-file-select>Displays the system file-select dialog when clicked
<mux-uploader-drop>Enables drag-and-drop functionality for handling file input
<mux-uploader-retry>Renders a "retry" button if the upload fails
<mux-uploader-progress>Displays a progress indicator showing how much of your file has been uploaded. This can be a bar or percentage type

Check out the mux-uploader-modal.html example application to see a real-world example of how these components can be used.

Drag and Drop

<mux-uploader-drop> is available for drag and drop functionality. It works like a <div> or other "container" element in the sense that you can style it and populate it with whatever children you see fit (including but not necessarily a <mux-uploader>).

Similar to <input> and <label> relationships, you associate a <mux-uploader-drop> with its corresponding <mux-uploader> via id using the mux-uploader attribute.

The <mux-uploader-drop> component will get the active attribute when the drag is active, this allows you to write some CSS to style it for your application.

Here's a full example of a custom button, customized progress text and drag and drop functionality that changes the background when the drag is active

<style>
  /* This .btn class styles buttons in my application */
  .btn {
    padding: 6px 8px;
    border: 1px solid #0d9488;
    border-radius: 5px;
    font-size: 24px;
    color: #134e4a;
    background: #99f6e4;
    cursor: pointer;
  }
  /* Customize progress bar color */
  mux-uploader {
    --progress-bar-fill-color: #7e22ce;
  }
  /* Customize drop area background color & active background color */
  mux-uploader-drop {
    padding: 40px;
    background: #fef9c3;
  }
  mux-uploader-drop[active] {
    background: #ffe4e6;
  }
</style>

<mux-uploader-drop mux-uploader="my-uploader">
  <mux-uploader
    no-drop
    id="my-uploader"
    endpoint="https://my-authenticated-url/storage?your-url-params"
  >
    <button class="btn" type="button" slot="file-select">Pick a file</button>
  </mux-uploader>
</mux-uploader-drop>

Technical details about drop areas

When a file is dropped, <mux-uploader> will dispatch a custom file-ready event with the relevant file.

You can implement your own drag and drop completely separate from <mux-uploader> and as long as you dispatch a custom file-ready with the file in the detail property then <mux-uploader> will handle the upload upon receiving the event.

<script>
const muxUploader = document.querySelector("mux-uploader");
// Dispatch custom event to trigger upload
muxUploader.dispatchEvent(
new CustomEvent("file-ready", {
composed: true,
bubbles: true,
detail: file,
})
);
</script>

Listening for events

<mux-uploader> uses custom events to share details about how the upload is progressing.

You can listen for the progress event to receive details on how far along your file upload is.

const muxUploader = document.querySelector("mux-uploader");
muxUploader.addEventListener("progress", function (e) {
console.log(`My upload is ${e.detail}% complete!`);
});

When the upload is complete, you'll see 100% on the progress bar and the success event will fire.

If an error occurs during the upload, an uploaderror event will fire.

<mux-uploader endpoint="https://my-authenticated-url/storage?your-url-params"></mux-uploader>
<script>
const muxUploader = document.querySelector('mux-uploader');
muxUploader.addEventListener('success', function () {
/* Handle upload success */
});
muxUploader.addEventListener('uploaderror', function () {
/* Handle upload error */
});
</script>

Attributes reference

<mux-uploader>
AttributeTypeDescriptionDefault
endpointstring | PromiseEither a) the authenticated URL that your file will be uploaded to or b) an async function that yields a promise that resolves to that url. Check out the direct uploads docs. Required.undefined
idstringAn ID that allows mux-uploader-drop to locate mux-uploader. Required if you use advanced customization.N/A
upload-in-progressboolean(Read-only) Toggles visual status of progress bar while upload is in progress. Can be targeted with CSS if you want to control styles while in progress i.e. mux-uploader[upload-in-progress].false
upload-errorboolean(Read-only) Toggles visual status of progress bar when upload encounters an error. Can be targeted with CSS if you want to control styles when an error occurs i.e. mux-uploader[upload-error].false
dynamic-chunk-sizebooleanToggles uploading with dynamic chunk sizes. Chunk sizes will change with upload speed to attempt to optimize upload.false
no-dropbooleanRenders a div wrapper instead of a <mux-uploader-drop> componentfalse
no-progressbooleanPrevents the ouput of <mux-uploader-progress> elements as children of <mux-uploader>false
no-retrybooleanPrevents the ouput of the <mux-uploader-retry> element as a child of <mux-uploader>false
no-statusbooleanPrevents the ouput of the <mux-uploader-status> element as a child of <mux-uploader>false
max-file-sizenumberEnforces a client-side limit on the maximum video file size the uploader component will accept as valid input.undefined

<mux-uploader-drop>
AttributeTypeDescriptionDefault
overlaybooleanToggles showing an overlay on dragover.false
overlay-textstringOptional text to display on dragover when overlay is on.''
mux-uploaderstring Must match the id on MuxUploader. Required.N/A

Slots reference

Web ComponentSlot NameSlot DescriptionCode Example
<mux-uploader>file-selectUsed to customize the file select button in the uploader component.<mux-uploader><button slot="file-select">Custom File Select</button></mux-uploader>
<mux-uploader-drop>headingUsed to customize the text shown when prompting users to drop a file.<mux-uploader-drop><span slot="heading">Custom heading</span></mux-uploader-drop>
<mux-uploader-drop>separatorUsed to customize the separator text between the drop area and the file picker.<mux-uploader-drop><span slot="separator">Custom separator</span></mux-uploader-drop>
<mux-uploader-drop>defaultUsed to customize the file picker button or input.<mux-uploader-drop><button slot="default">Custom file picker</button></mux-uploader-drop>

Events reference

<mux-uploader>

<mux-uploader> fires several events throughout the uploading lifecycle to monitor uploading state. These events match the events fired by Upchunk under the hood.

EventDescription
file-readyFired when a file has been selected to be uploaded
uploadstartFired when the upload begins.
chunkattemptFired immediately before a chunk upload is attempted.
chunksuccessFired when an indvidual chunk is successfully uploaded. Sample response: { detail: { chunk: Integer, attempts: Integer, response: XhrResponse } }
uploaderrorFired when an error occurs in the chunked upload process.
progressFired continuously with incremental upload progress. This returns the current percentage of the file that's been uploaded. Sample response: { detail: [0..100] }
successFired when the entire file has successfully completed uploading.

Styling reference

<mux-uploader> and its packaged components can be styled with standard CSS, but also includes the following CSS variables for "under the hood" styling.

<mux-uploader>
NameCSS PropertyDefault ValueDescriptionNotes
--progress-bar-fill-colorbackground#000000background color for progress bar div
--progress-radial-fill-colorstrokeblackstroke color for circle SVG (wip)
--progress-percentage-displaydisplayblockdisplay value for percentage progress
<mux-uploader-drop/>
NameCSS PropertyDefault ValueDescriptionNotes
--overlay-background-colorbackground-colorrgba(226, 253, 255, 0.95)background color of the overlay divVisible only when component has fullscreen attribute

Was this page helpful?