Update: Please use the Bytescale JavaScript SDK instead 👍


JavaScript File Upload Library,
with Integrated Cloud Storage.

Get StartedLive Demo
import { Upload } from "upload-js";
// Call once per app.
const upload = Upload({ apiKey: "free" });
// <input type="file" onchange="onFileSelected(event)" />
async function onFileSelected(event) {
const [ file ] = event.target.files;
const { fileUrl } = await upload.uploadFile(file);
console.log(`File uploaded: ${fileUrl}`);
  • Just Works Out-the-Box
  • Fast CDN (600 Nodes)
  • Lightweight (6KB)
Fork on GitHub
See examples for:
Bytescale Dashboard screenshot

Integrated Cloud Storage

Upload.js comes pre-integrated with cloud-based file storage, purpose-built for high-demand, low-latency file uploading.

  • Scalable File Storage & Hosting (300-Point CDN)
  • Powerful Rules Engine (Rate & Traffic Limiting, etc.)
  • File Transformations (Image Resizing, Cropping, etc.)
Multipart upload diagram

Multipart File Uploads

Upload.js automatically switches between single and multipart file uploads based on file size, making it suitable for large file uploads, such as videos, and small file uploads, such as images.

Tip: Try using the API key "free" — no sign up required.

File upload progress diagram

Automatic Progress Smoothing

Upload.js makes it easy to implement file upload progress bars and percentages. Using an internal Exponential Moving Average (EMA) algorithm, Upload.js pre-smooths file upload events before they're raised, giving your users a better experience.

See examples: JS, React, Vue, Angular and jQuery.

Upload validation diagram

File Upload Validation

Benefit from enforced, server-side file upload validation without writing any server-side code. Simply configure “upload rules” in the Bytescale Dashboard to have your files automatically checked on upload. This provides increased security over traditional client-side JavaScript file upload validation.

Lightweight graphic

Lightweight (6KB)

Performing AJAX file uploads shouldn't require a large JavaScript library: so we've made sure it doesn't. Upload.js is only 6KB, including all dependencies, after minification and GZIP.

Let's get started...

It takes seconds to implement JavaScript file uploads with Upload.js:


Install Upload.js using one of these options:

npm install upload-js
yarn add upload-js
<script src="https://js.bytescale.com/upload-js/v2"></script>


Initialize once at the start of your app:

const upload = Upload({ apiKey: "free" })

Note: files expire after 4 hours with the API key "free" — please create an account for permanent storage.


To upload a file in JavaScript, first create an HTML file input element:

<input type="file" onchange="onFileSelected(event)" />

Next, use the uploadFile method to implement the onchange handler:

async function onFileSelected(event) {
const [ file ] = event.target.files;
const { fileUrl } = await upload.uploadFile(
onBegin: ({ cancel }) => console.log("File upload started!"),
onProgress: ({ progress }) => console.log(`File uploading... ${progress}%`)
console.log(`File uploaded! ${fileUrl}`);

Note: the cancel callback is used to cancel file uploads through JavaScript. Calling this aborts all active XMLHttpRequest (XHR) calls.

That's It!

You now have everything you need to implement an end-to-end file upload in JavaScript!

Try in Live Code Editor

Integration with JS Frameworks:

Upload.js is framework-agnostic, so can be used to implement JavaScript file uploading in any framework:

React File Upload Example

To perform a file upload in React using an <input type="file"> element:

import { Upload } from "upload-js";
// Create one instance per app.
const upload = Upload({ apiKey: "free" });
const FileUploadButton = () => {
const [progress, setProgress] = useState(null);
const [fileUrl, setFileUrl] = useState(null);
const [error, setError] = useState(null);
if (fileUrl !== null) return fileUrl;
if (error !== null) return error.message;
if (progress !== null) return <>File uploading... {progress}%</>;
return <input type="file"
onBegin: ({ cancel }) => setProgress(0),
onProgress: ({ progress }) => setProgress(progress),
onUploaded: ({ fileUrl }) => setFileUrl(fileUrl),
onError: (error) => setError(error)
})} />;

Vue File Upload Example

To perform a file upload in Vue using an <input type="file"> element:

<input v-if="progress === null" type="file" @change="uploadFile" />
<div v-else-if="fileUrl !== null">{{ fileUrl }}</div>
<div v-else-if="error !== null">Error: {{ error }}</div>
<div v-else>Progress: {{ progress }}%</div>
import { Upload } from "upload-js";
// Create one instance per app.
const upload = Upload({ apiKey: "free" });
export default {
name: "App",
data() {
return {
error: null,
progress: null,
fileUrl: null,
methods: {
uploadFile(event) {
onBegin: ({ cancel }) => (this.progress = 0),
onProgress: ({ progress }) => (this.progress = progress),
onUploaded: ({ fileUrl }) => (this.fileUrl = fileUrl),
onError: (error) => (this.error = error.message)

Angular File Upload Example

To perform a file upload in Angular using an <input type="file"> element:

import { Component } from "@angular/core";
import { Upload } from "upload-js";
selector: "app-root",
template: `
<input type="file" (change)="uploadFile($event)" [hidden]="progress !== null" />
<div [hidden]="progress === null">Progress: {{ progress }}%</div>
<div [hidden]="fileUrl === null">{{ fileUrl }}</div>
<div [hidden]="error === null">Error: {{ error }}</div>
export class AppComponent {
// Create one instance per app.
upload = Upload({ apiKey: "free" });
// Component state.
progress: number | null = null;
fileUrl: string | null = null;
error: string | null = null;
async uploadFile(event: Event) {
try {
const { files } = event.currentTarget as HTMLInputElement;
if (files === null) {
throw new Error("No file selected!");
const { fileUrl } = await this.upload.uploadFile(
files[0], {
onBegin: ({ cancel }) => (this.progress = 0),
onProgress: ({ progress }) => (this.progress = progress)
this.fileUrl = fileUrl;
} catch (e: any) {
this.error = (e as Error).message;

jQuery File Upload Example

To perform a jQuery AJAX file upload using an <input type="file"> element:

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://js.bytescale.com/upload-js/v2"></script>
const upload = Upload({
// Get production API keys from Bytescale.com
apiKey: "free"
$(() => {
$("#file-input").change(async (event) => {
try {
const { fileUrl } = await upload.uploadFile(
event.target.files[0], {
onProgress: ({ progress }) => $("#title").html(`File uploading... ${progress}%`)
File uploaded:
<a href="${fileUrl}" target="_blank">${fileUrl}</a>`
} catch (e: any) {
<h1 id="title">Please select a file...</h1>
<input type="file" id="file-input" />

Releasing to production?

Use the API key "free" to experiment with Upload.js without creating an account. When you're ready, create a Bytescale account to get permanent file storage.

✓ No credit card required. Try free for 14 days.

No hidden fees
Storage & CDN, built-in.

Upload.js comes pre-integrated with cloud-based file storage, file hosting, and a worldwide 600-point CDN.

Learn More
Start your integration
Zero infrastructure.

No need to configure servers, buckets, security policies or roles: all you need is Upload.js and an API key.

Get an API Key

You are using an outdated browser.

This website requires a modern web browser -- the latest versions of these browsers are supported: