# tus-js-client: a JavaScript client for resumable uploads

> tus-js-client speaks the tus 1.0.0 protocol from browsers, Node.js, React Native and Cordova. It is a thin client, so the resumability you get depends entirely on the tus server you point it at.

**tus/tus-js-client** — A pure JavaScript client for the tus resumable upload protocol

- Repository: https://github.com/tus/tus-js-client
- Website: https://tus.io/
- Stars: 2,625 · Forks: 338
- Language: JavaScript
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/tus-tus-js-client

## The problem tus-js-client solves, and who it is for

A plain HTTP POST of a large file is all or nothing. If the connection drops at 90 percent, the bytes are gone and the user starts again. tus-js-client exists to remove that failure mode. It is the JavaScript side of the tus protocol, described in the README as "a protocol based on HTTP for resumable file uploads", where an interrupted upload "can be resumed without re-uploading the previous data again".

The audience is narrow but real. The README lists browsers, Node.js, React Native and Apache Cordova, and the repository topics repeat browser, nodejs, reactnative and cordova. If you are shipping a web form that accepts multi-gigabyte video, or a mobile app that uploads photos over a flaky cellular link, this is the layer that keeps partial state alive. If your uploads are small and your network is reliable, the protocol machinery buys you nothing.

## How the client talks to a tus server

The design is deliberately thin. tus-js-client is a client only: it creates an upload resource on a tus server, sends the file in chunks, and asks the server how many bytes it already holds when a transfer resumes. The server owns the storage. That split is why the endpoint option is mandatory in every example, and why the repository ships separate browser and node entry points in package.json, with the node condition resolving to lib.esm/node/index.js and the default branch resolving to lib.esm/browser/index.js.

Resumption is not automatic. The README example calls findPreviousUploads() and then resumeFromPreviousUpload() before start(). That means the client has to persist the upload URL somewhere between sessions, and the package.json exports a FileUrlStorage module under ./node/FileUrlStorage for the Node case. In a browser the storage is whatever the client is configured to use. If that store is cleared, the upload URL is lost and the server-side partial data becomes unreachable, even though it still occupies space.

Retries are explicit too. The example passes retryDelays: [0, 3000, 5000, 10000, 20000], a fixed backoff schedule rather than an adaptive one. A long outage beyond the last delay ends the upload until the application calls start() again.

## Installing tus-js-client and running a first upload

The package is published to npm as tus-js-client, and the README points to docs/installation.md for requirements. The repository's package.json declares "type": "module" and exports both ESM and CommonJS builds, so the import form depends on your runtime.

For a browser build, install it from the registry:

```bash
npm install tus-js-client
```

Then wire it to a file input. This is the shape the README gives, with the endpoint pointing at a tus server rather than at your own API:

```js
import * as tus from 'tus-js-client'

input.addEventListener('change', function (e) {
  var file = e.target.files[0]
  var upload = new tus.Upload(file, {
    endpoint: 'http://localhost:1080/files/',
    retryDelays: [0, 3000, 5000, 10000, 20000],
    metadata: { filename: file.name, filetype: file.type },
    onError: function (error) { console.log('Failed because: ' + error) },
    onProgress: function (bytesUploaded, bytesTotal) {
      console.log(bytesUploaded, bytesTotal, ((bytesUploaded / bytesTotal) * 100).toFixed(2) + '%')
    },
    onSuccess: function () { console.log('Download %s from %s', upload.file.name, upload.url) }
  })
  upload.start()
})
```

The endpoint in that snippet is the tus.io test server port, not something you get for free. You need a tus 1.0.0 server listening there or at your own URL. What you should see is onProgress firing repeatedly as chunks land, and onSuccess printing the final upload URL, which the client keeps for a later resume.

To make resumption work across sessions, add the lookup the README shows before start():

```js
upload.findPreviousUploads().then(function (previousUploads) {
  if (previousUploads.length) {
    upload.resumeFromPreviousUpload(previousUploads[0])
  }
  upload.start()
})
```

If findPreviousUploads returns an empty array after a page reload, the client is not finding its stored URL, and the resume will silently become a fresh upload. That is the first thing to check when resumability appears broken.

## Where tus-js-client is the wrong tool

The client cannot upload anything without a tus 1.0.0 server. That is the central constraint, and the README never suggests otherwise. If your backend is a plain object-storage presigned URL, tus-js-client is not a drop-in replacement, because there is no server side to answer the offset query that resumption depends on.

The second limitation is state. Resumable uploads require durable client-side records of upload URLs, and the README does not document rollback or cleanup for orphaned uploads on the server. A user who abandons an upload halfway leaves bytes on the server that the client will only reclaim if it still holds the URL. On a shared browser profile or a Node process with an ephemeral filesystem, that store disappears and the partial data becomes dead weight you have to expire server-side.

The third is version churn. The README states plainly that the branch it documents is v4, and that v3.1.3 is available for anyone who has not absorbed the breaking changes introduced at v4.0.0. The repository's most recent release listed is v5.0.0-pre2 from 2026-01-13, a prerelease, while the last stable-looking entry is v4.3.1 from 2025-01-16. Teams that will not run prerelease code in production should plan around the v4 line.

## Alternatives and how they differ

The closest alternative named in the search data around this project is tus-java-client, the JVM implementation of the same protocol. The difference is not in behaviour but in where the code runs: tus-js-client targets JavaScript runtimes, and the Java client targets JVM services. If your uploader is an Android app written in Java or Kotlin, the JavaScript client is not a candidate at all, and the search results that pair "tus js client android" with "tus-java-client" are pointing at that boundary.

A more meaningful contrast is with chunked upload logic you write yourself against your own API. That path gives you control over storage, cleanup and authentication without a protocol layer, at the cost of implementing offset negotiation, retry and resume detection on both ends. tus-js-client exists precisely because that work is repetitive. The trade is that you inherit the protocol's assumptions, including a server that speaks tus 1.0.0 and a client-side store for upload URLs.

## Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-16, which is recent enough that the codebase is being touched. That is a statement about commit activity, not about release cadence: the release list shows v4.3.1 in January 2025 and a v5.0.0-pre2 in January 2026, so the gap between stable releases has been measured in months.

Upgrading across majors is the real cost. The README warns that breaking changes were introduced at v4.0.0 and points readers to the v3.1.3 tag if they are not ready. Anyone on v3 should read that release note before moving, because the client is embedded in upload paths where a silent behaviour change is expensive to debug.

The licence is MIT, stated in the README and present as a LICENSE file at the repository root. MIT is permissive and imposes no copyleft obligation on your application, but it also carries no warranty. That is a factual description of the licence text, not legal advice; if you redistribute the package in a regulated product, have your own counsel read the file.

## Conclusion

Adopt tus-js-client if you already run a tus 1.0.0 server and need uploads that survive a dropped connection or a closed laptop lid, and if your runtime is a browser, Node.js, React Native or Cordova. Do not adopt it if you cannot operate a tus endpoint, because the client holds no storage of its own and the README does not document a fallback path. Before wiring it into a product, verify two things against your own server: that findPreviousUploads actually returns entries after a restart, and whether you want to ship the v4 line or the v5.0.0-pre2 prerelease, since the repository's latest release is still marked pre2.

## FAQ

### What is the tus protocol and how does tus-js-client relate to it?

The README describes tus as a protocol based on HTTP for resumable file uploads, meaning an upload can be interrupted at any moment and resumed without re-sending the previous data. tus-js-client is the pure JavaScript client for that protocol, at protocol version 1.0.0.

### Does tus-js-client run on a server or in the browser?

Both, plus mobile. The README states it can be used inside browsers, Node.js, React Native and Apache Cordova applications, and package.json exposes separate node and browser entry points.

### How do I install tus-js-client?

It is published to npm as tus-js-client, so npm install tus-js-client is the install step. The README links to docs/installation.md for requirements, and the package ships both ESM and CommonJS builds.

### How does tus-js-client resume an interrupted upload?

The README example calls findPreviousUploads(), and if the returned array is non-empty it calls resumeFromPreviousUpload() with the first entry before start(). That requires the client to still hold the previous upload URL.

### Why does my upload restart from zero after a page reload?

Because findPreviousUploads() returned an empty array, so the client had no stored upload URL to resume from and started a new upload. The README does not document rollback or cleanup for the server-side bytes left behind by the abandoned attempt.

### Which version of tus-js-client should I use?

The README documents the v4 branch and points to the v3.1.3 tag for anyone who has not adopted the breaking changes introduced at v4.0.0. The repository's latest listed release is v5.0.0-pre2, which is a prerelease, while v4.3.1 is the most recent non-prerelease entry.

## Sources

- [License: MIT](https://github.com/tus/tus-js-client/blob/main/LICENSE)
- [Project website](https://tus.io/)
- [README](https://github.com/tus/tus-js-client/blob/main/README.md)
- [Releases](https://github.com/tus/tus-js-client/releases)
- [tus/tus-js-client on GitHub](https://github.com/tus/tus-js-client)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tus-tus-js-client
