webdav: a TypeScript WebDAV client for Node and the browser
WebDAV client written in Typescript for NodeJS and the browser
At a glance
- What is it?
- The webdav package is a promise based WebDAV client written in TypeScript that runs in NodeJS, in the browser and in React Native, with ESM builds per target and automatic or explicit authentication. It is deliberately not an RFC purist, which makes it easy to use against real servers and occasionally surprising in the details.
- Who is it for?
- Adopt webdav if you need to talk to Nextcloud, ownCloud, Box, Yandex or any other WebDAV enabled service from one TypeScript codebase that runs in Node and in the browser, and you value a small promise based API over strict protocol fidelity.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 36 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Convenience over RFC fidelity
WebDAV is described in the README as a well known, stable and highly flexible protocol for interacting with remote filesystems through an API, and because it is so widespread many file hosting services such as Nextcloud and ownCloud, Box and Yandex use it as a fallback to their primary interfaces.
The library provides a WebDAV client interface that makes interacting with those services easy. The API returns promises and resolves with the results, and it parses and prepares directory contents requests for easy consumption, along with methods for things like file stats and quotas.
The design position is stated with unusual clarity, and it is the single most important thing to know before you adopt it. The motivation is not to follow an RFC or to strictly adhere to standard WebDAV interfaces, but to provide an easy to consume client API for working with most WebDAV services.
That is a deliberate trade and it cuts both ways. You get an API that behaves the way most applications want, with directory listings already turned into objects that carry a filename, a basename, a last modification date, a size and a type. You also give up the guarantee that every server corner case is handled the way the specification describes, and when something misbehaves the answer is usually in the server's behaviour rather than in a conformance bug in the client.
Version 5 is ESM only, and that is the migration
The version story is the part of the README that has consequences for your build.
Version 5 is under active development, version 4 is in support mode and will receive security and stability related bugfixes, and earlier versions are deprecated with no updates. The README also carries a dated note that version 4 support will be dropped January 2025 and that you should migrate to v5 as soon as possible. That note is what you would expect from a project that has already made the transition, so treat v4 as a path you should not be starting on.
The reason v4 is not a drop in replacement is ESM. Version 5 upgrades the library to ECMAScript modules, and your environment has to fit one of three shapes. A NodeJS project with "type": "module" in its package.json, a web project bundled with a tool like Webpack that can handle ESM, or a React Native project.
If you are not ready to upgrade, the README says you may consider using version 4.
The Node support table shows how much has moved. Version 5 lists Node 14 and later, while v4 covers 10 to 18, v3 covers 10 to 16, v2 covers 6 to 14 and v1 covers 4 to 12. The footnote is the honest part: while Node 14 is supported on v5, it is not tested for, and Node versions below 18 have no active test cases and rely on community support for patching.
The request layer moved from Axios to @buttercup/fetch
The transport is worth a section of its own because it changed between major versions and it determines what your code inherits.
The library uses @buttercup/fetch to make requests in a cross platform manner. It uses the browser's native fetch if present, or a polyfill if not, and in Node and other environments it uses node-fetch. Versions before v5 used Axios for requests.
If you are migrating from v4, that difference matters in practice. Axios is a feature rich client with interceptors, retry helpers and its own response handling, and code written against it will not port mechanically. A fetch based layer is closer to the platform, which is why the same package can serve Node, a browser bundle and React Native from one source tree.
The cross platform goal also explains the package layout. The exports map in package.json routes the root entry to the Node build by default, to the web build under the browser condition and to the React Native build under the react-native condition, with explicit subpath entries for webdav/web and webdav/react-native. The build script produces exactly those three artefacts, with tsc compiling the Node build and webpack producing the web bundle.
Browser entry points, React Native, and streams that are not there
Browser support exists from version 3 of the library onwards. What changed in v5 is how you get to it.
In version 4 you had to use a different entry point for the web version. That is still possible in version 5, but you no longer need to, and the README shows both forms working in supported bundlers:
import { createClient } from "webdav/web";
// or
import { createClient } from "webdav";Versions 3 and 4 supported a UMD style module in the browser. Version 5 dropped that and provides only an ESM enabled bundle, which the README says can be imported into other ESM supporting projects. It also advises against transpiling the default Node entry point yourself for the browser and recommends the dedicated web version instead.
React Native is better supported as of version 5.6.0, using a specific build for the platform, with the import automatic or forced by importing from /react-native directly. There is a caveat about Metro, the React Native build system, not properly resolving those entries, in which case the README shows a babel module-resolver configuration that aliases webdav to the react-native build.
The limitation that will actually break code is streams. They are not available within the browser, so createReadStream and createWriteStream are stubbed and calling them throws an exception. A browser application that wants to move a large file has to use the ordinary buffer methods and accept the memory cost.
Creating a client and choosing an authentication type
Usage starts with the factory function createClient, and the authentication choice is the only piece of configuration most callers need to think about.
The client detects automatically which authentication to use between AuthType.None and AuthType.Password if no authType parameter is provided. For AuthType.Token or AuthType.Digest you must specify it explicitly, and setting the authType manages the Authorization header automatically when connecting. If you are unsure whether the remote server requires digest or password based authentication, AuthType.Auto is the option to reach for.
The documented example shows the shape of the call, with the URL, the authentication type and the credentials:
import { AuthType, createClient } from "webdav";
const client = createClient("https://some-server.org", {
authType: AuthType.Digest,
username: "user",
password: "pass"
});The README also shows a plain usage form and what a directory listing looks like once parsed. The client is created against a base URL, and client.getDirectoryContents("/") resolves with an array of objects carrying filename, basename, lastmod, size and type. If the server does not require authentication, you simply avoid passing username and password values.
TypeScript types are exported for the Node build and can be imported directly from the module, which is what makes the authType enum usable in a typed codebase rather than a magic string.
The test suite covers node, browser and types separately
The scripts in package.json describe how the project is checked, and the structure tells you what the maintainers consider risky.
The build script cleans and then runs the Node and web builds in parallel, with the Node build handled by tsc and the web build by webpack in production mode. There is a separate development script that runs nodemon over ts and js files and rebuilds on change.
Testing is split into four parts run in sequence: test:node, test:web, test:types and test:format. The node tests run vitest against the node-unit project. The web tests are the interesting ones, because they clean and rebuild the web bundle and then run a server and the browser specs concurrently, with the server started through tsx and the browser project run under vitest. The type tests build the Node output first and then run a dedicated vitest project for types, which is how the exported type surface is checked rather than merely compiled.
Format checking is part of the same gate, with prettier run in check mode over the source and test directories. The test target is wired as the check, so a formatting difference is a failing build rather than a nit someone remembers to fix.
The tree matches that layout: source/ for the library, test/ for the suites including a web server fixture, util/ for helper scripts, with vitest.config.ts, webpack.config.cjs and tsconfig.json at the root, alongside a CHANGELOG.md, a CONTRIBUTING.md and a LOCK_CONTACT.md.
Where this WebDAV client is the wrong tool
The main wrong-tool case is the one the README implies when it says services use WebDAV as a fallback to their primary interfaces.
If you are integrating with one provider and want the things that provider's own API offers, such as sharing controls, comments, version history or collaborative features, WebDAV is the fallback protocol and it will not carry those. The difference in approach is that a provider API models that service's capabilities, while WebDAV models a filesystem, so you trade feature depth for the ability to speak to many services with one client. That trade is worth making when you support several backends, and it is a bad one when you support exactly one and want everything it can do.
The second wrong-tool case is the browser stream limitation. If your application moves large files in a browser tab, createReadStream and createWriteStream throwing an exception is a hard stop, and the buffering methods are not a substitute for a streaming design.
The third is protocol fidelity. Because the library explicitly does not follow an RFC, a server that behaves unusually, or a corner of the standard you depend on, may not be handled. If your work is about interoperability testing rather than convenience, you want a client that implements the specification.
The last practical note is the version split. With v5 in active development, v4 in support mode and the README already stating that v4 support was dropped in January 2025, a new project should start on v5 and accept the ESM requirement, and an existing project still on v4 has a migration to schedule rather than an option to defer indefinitely.
Editorial conclusion
Adopt webdav if you need to talk to Nextcloud, ownCloud, Box, Yandex or any other WebDAV enabled service from one TypeScript codebase that runs in Node and in the browser, and you value a small promise based API over strict protocol fidelity. Do not adopt it if you need service specific features that only the provider's own API exposes, if you need streaming in the browser, since createReadStream and createWriteStream are stubbed there and throw, or if your build tooling cannot consume ESM. Verify three things first: which major version you install, because version 5 is ESM only and the README states version 4 support was dropped in January 2025; which entry point your bundler resolves, since the package exposes separate node, web and react-native builds with an exports map; and how you authenticate, because AuthType.Token and AuthType.Digest have to be specified explicitly rather than detected. The licence is MIT, the package version is 5.11.0, and the last push was on 2026-09-19.
Frequently asked questions
How do I install and start using the webdav package?
Install it with npm install webdav --save, then create a client with the createClient factory passing a base URL and your credentials. The client exposes promise based methods such as getDirectoryContents, which resolves with parsed objects carrying filename, basename, lastmod, size and type.
Which authentication types does the webdav client support?
AuthType.None and AuthType.Password are detected automatically when no authType is given, while AuthType.Token and AuthType.Digest must be specified explicitly. Setting authType manages the Authorization header, and AuthType.Auto is available when you are unsure whether the server wants digest or password authentication.
Does the webdav client support streaming in the browser?
No. The README states that streams are not available within the browser, so createReadStream and createWriteStream are stubbed and calling them throws an exception.
What are the requirements for version 5 of the webdav client?
Version 5 is ESM only, so it needs a NodeJS project with type set to module in package.json, a web project bundled with a tool that handles ESM such as Webpack, or a React Native project. It also lists Node 14 and later as supported, with the note that Node 14 is not tested and versions below 18 have no active test cases.
How does the webdav client handle React Native?
React Native is better supported as of version 5.6.0 using a specific build for the platform, and the import should be automatic though it can be forced from webdav/react-native. Because Metro does not properly resolve those entries, the README shows a babel module-resolver configuration that aliases webdav to the react-native build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/perry-mitchell-webdav-client)Was this useful?