Flag of Ukraine   We stand with the brave people of Ukraine. Stop the war. Find out how you can help.

Uppy 0.23: Import from Url, refactored thumbnail generation, XHR bundle

Hi all! We are back from holidays with a shiny new 0.23.0 release for you! It’s packed with a new Url plugin (imports files from urls), refactored ThumbnailGenerator, Webcam improvements and more.

Import from Url

Meet our new “Provider” plugin, Url. It’s simple, yet powerful: paste a link to any file on the web, and Uppy with Uppy Server will upload it wherever you need.

uppy.use(Url, { target: Dashboard, host: YOUR_UPPY_SERVER_URL })


Thumbnail generation has been refactored to a separate ThumbnailGenerator plugin, thanks to the PR from @richardwillars. So Uppy Core is now more lightweight, if you don’t need previews.

ThumbnailGenerator is still bundled with our most feature complete Dashboard plugin though, so you don’t have to change anything if you were using that.

We’ve also fixed previews in Safari and tweaked the code slightly after reading the excellent Image resize in browsers is broken post by Uploadcare 👌.

Processing results

Processing results from encoding plugins like Transloadit, are now added to complete event:

uppy.on('complete', (result) => {
  // result: {
  //   failed: [...],
  //   successful: [...],
  //   transloadit: [...],
  //   uploadID: "cjdnzj2zy0000c___iewu9m5y"
  // }

And to uppy.upload() promise result too:

uppy.upload().then((result) => {

You can still use events like transloadit:result, its just easier when things are in the same place. Plugins can use the new uppy.addResultData() API to add data to the result, like so:

uppy.addResultData(uploadID, { transloadit: assemblies })


The Webcam plugin now mirrors image previews by default, so when you are making a selfie and wave with your right hand, you see that right hand in the Webcam preview, just like in the mirror. This option can be disabled via uppy.use(Webcam, { mirror: false }. Note that the resulting image will not be mirrored, so your hand will actually be waving on the left. This mimics the behaviour of smarphone selfie cameras.

We’ve also added an option to select which camera will be used to capture pictures or video: facingMode, set to user (front camera) by default.


  • You can now specify a config path when starting the standalone Uppy Server like so uppy-server --config /path/to/uppyconf.json. The config file is expected to be a JSON file with the same schema as the Uppy Server options.
  • A periodic cleanup job has been added to Uppy Server, to delete stale upload files from the specified filePath. Even though we’d rarely expect uploaded files to go undeleted immediately, there could be cases where an error occurs during an upload, and so Uppy Server leaves the file undeleted to give room for upload retries. With the cleanup job in place, we can ensure that this file would eventually be deleted after the file upload is done.
  • Responses from Multipart uploads are now relayed to Uppy Client as they are received from the target server. With this in place, you can now handle responses from local and remote XHRUpload in nearly the same way.

Other Improvements and Additions

  • Added new option to hide ProgressBar and StatusBar after upload finish (#485 / @wilkoklak)
  • Chaining API has been improved, you can now use .on and .off anywhere: uppy.use(Dashboard).use(Tus).on('complete', handleComplete).run()
  • The Transloadit plugin now has a new transloadit:assembly-executing event and passes Assembly results to the complete callback (#547, #527 / @goto-bus-stop)
  • We’ve added a bundle option to the XHRUpload plugin to send multiple files in one request (#442 / @goto-bus-stop)
  • Uppy releases are now hosted on Edgly CDN by Transloadit
  • A Third-party extension for integrating the Ngrx Angular state management library with Uppy has been released, uppy-store-ngrx by @rimlin

Other Fixes

  • Fixed blank preview thumbnails for images in Safari; use slightly different step scaling (#458, #584 / @arturi)
  • We now log in console and show an Informer message, not error in console, when file cannot be added due to restrictions (#604, #492 / @goto-bus-stop).
  • Unused files have been removed from published package, saving many many precious megabytes :) (#586 / @goto-bus-stop)
  • Use empty input value so same file can be selected multiple times (@arturi / #534)
  • Fix modal and page scroll (#564 / @arturi)
  • Refactor provider views (#554 / @arturi)
  • Lots of documentation fixes, thanks to all our contributors!


Uppy has made some appearances on the internet recently.

1. Better File Uploads with Shrine: Direct Uploads:

On how to set up Uppy with Shrine, a file attachment toolkit for Ruby applications. It starts off with an example of a plain <form> upload and builds up to a more advanced experience:

  • When the user submits the form with selected files, there is no indicator telling them when the upload will finish.
  • When the user is uploading multiple files at once and the request happens to get aborted, it’s not possible to keep the files that were uploaded so far, because all files are sent in a single request. In other words, multiple uploads are all-or-nothing.
  • Files are validated only after they have been uploaded, which means the user needs to wait until the upload finishes before they can know whether their file was even valid.

We can improve that by asynchronously starting to upload files on the client side as soon as they’re selected. This also gives users the ability to continue filling in other fields while files are being uploaded, because the UI isn’t blocked during the upload.

There are many popular JavaScript file upload libraries out there – jQuery-File-Upload, Dropzone.js, FineUploader etc. – but the one you should use with Shrine is definitely Uppy 🐶. Uppy is a modular library that knows how to upload files to a custom endpoint on your app, to Amazon S3, or even to a resumable endpoint, providing progress bars, drag & drop functionality, image previews, file validations etc, all while making as few assumptions as possible.

2. Featured in Javascript Daily:

Uppy: A Powerful, Modular JavaScript File Uploader

— JavaScript Daily

3. #1 Trending on GitHub accross all languages:

Today our open source efforts are outpacing those of MSFT GOOG FB combined :D

— kvz, transloadit

4. #2 Product of the Week on ProductHunt:

You literally solved my biggest problem, thank you for developing such a great project.

— Chetan Menaria

Writing file upload functionality is always a pain in the arse. I’ll be checking this out today and integrating into SongBox if it’s good.

— Mick

5. #2 New Tool of The Year on Stackshare:

Uppy closed out the year as the #1 trending GitHub JavaScript project, so we think it’s only getting started.

Full Changelog

Here is the full list of changes for version 0.23.0 (and patches

  • core: Allow plugins to add data to result object. Return processing results among with upload results in complete event and upload() promise (#527 / @goto-bus-stop)
  • core: Move limiting to different point, to fix StatusBar and other UI issues #468 (#524, #526 / @goto-bus-stop)
  • core: Add uploadID to complete event (#569 / @richardwillars)
  • core: Allow chanining after .on() and .off() to improve ergonomics (#597 / @arturi)
  • core: Allow user to override sass variables (#555 / @chao)
  • core: Move preview generation to separate plugin, add queuing (#431 / @richardwillars)
  • core: Third-party extension, uppy-store-ngrx https://github.com/rimlin/uppy-store-ngrx/ (#532 / @rimlin)
  • core: Warn, not error, when file cannot be added due to restrictions? (#604, #492 / @goto-bus-stop)
  • dashboard: Add more i18n strings (#565 / @arturi)
  • dashboard: Fix modal and page scroll (#564 / @arturi)
  • dashboard: Refactor provider views (#554 / @arturi)
  • dashboard: Restore focus after modal has been closed (#536 / @arturi)
  • dashboard: Use empty input value so same file can be selected multiple times (@arturi / #534)
  • dashboard: Use more accessible tip lib microtip (#536 / @arturi)
  • docs: Add PHP snippets to XHRUpload docs (#567 / @goto-bus-stop)
  • meta: Added instruction to fork the repo first (#512 / muhammadInam)
  • meta: Automatically host releases on edgly and use that as our main CDN (#558 / @kvz)
  • meta: Dependency version updates (#523 / @goto-bus-stop)
  • meta: Remove unused files from published package (#586 / @goto-bus-stop)
  • s3: Respect limit option for upload parameter requests too; fix isXml() check when no content-type is available (#545, #544, #528 / @goto-bus-stop)
  • statusbar: Fix status text still showing when statusbar is hidden (#525 / @goto-bus-stop)
  • test: Alter jest testPathPattern to current dir, add chai (#583 / @arturi)
  • thumbnail: Add thumbnail generation plugin (#461 / @richardwillars)
  • thumbnail: Fix blank preview thumbnails for images in Safari; use slightly different stap scaling (#458, #584 / @arturi)
  • transloadit: Add transloadit:assembly-executing event (#547 / @goto-bus-stop)
  • transloadit: Add assembly results to to the complete callback (#527 / @goto-bus-stop)
  • transloadit: Easily pass form fields (#593 / @goto-bus-stop)
  • tus: resume: false — don’t store url (@arturi / #507)
  • uppy-server: Detect file upload size from the server (@ifedapoolarewaju)
  • uppy-server: Fix circular json stringify error (@ifedapoolarewaju)
  • uppy-server: Load standalone server options via config path (@ifedapoolarewaju)
  • uppy-server: Pass response from uppy-server upload’s endpoint (#591 / @ifedapoolarewaju)
  • uppy-server: Schedule job to delete stale upload files (@ifedapoolarewaju)
  • uppy-server: Security audit, ask @acconut
  • uppy-server: Support localhost urls as endpoints (@ifedapoolarewaju)
  • url: New plugin that imports files from urls (#588 / @arturi, @ifedapoolarewaju)
  • webcam: Font styling for Webcam option (#509 / @muhammadInam)
  • webcam: Mirror image preview, add option to select which camera is used to capture, try filling the whole Dashboard with webcam preview image, remove URL.createObjectURL() (#574 / @arturi, @nqst)
  • website: Add Transloadit example to website (#603 / @arturi)
  • website: Doc fixes (#563 / @arturi)
  • website: Improve the Contributing guide (#578 / @arturi)
  • xhrupload: Add bundle option to send multiple files in one request (#442 / @goto-bus-stop)
  • xhrupload: Prevent files from being uploaded multiple times in separate uploads (#552 / @richardwillars)
  • xhrupload: Refactor response and error handling (#591 / @goto-bus-stop, @arturi, @ifedapoolarewaju)
  • core: Fix remote uploads (#474 / @arturi)
  • statusbar, progressbar: Add option to hide progress bar after upload finish (#485 / @wilkoklak)
  • s3: Allow passing on XHRUpload options, such as “limit” to AwsS3 Plugin (#471 / @ogtfaber)
  • XHRUpload: Fix progress with limited XHRUploads (#505 / @goto-bus-stop)
  • core: fix error when file.type === null, shouldn’t pass that to match (@arturi)
  • dashboard: input hidden=”true” should not be focusable too (@arturi)
  • webcam: Font styling for Webcam option (#509 / @muhammadInam)
  • docs: fix reference to incorrect width/height options (#475 / @xhocquet)
  • docs: Documentation fixes and improvements (#463 / @janko-m)
  • docs: Fixed several typos in docs/server and docs/uppy (#484 / @martiuslim)

The Uppy Team