WebDAV Client for Node.js and Browser
The `webdav` library provides a promise-based WebDAV client for interacting with remote filesystems, supporting both Node.js and browser environments. Currently at version 5.9.0, the library is under active development, with version 4 in maintenance mode until January 2025, and earlier versions deprecated. It differentiates itself by prioritizing an easy-to-consume client API for common WebDAV services (like Nextcloud, ownCloud, Box, Yandex) over strict RFC adherence. Version 5 transitioned to ECMAScript Modules (ESM) and uses `@buttercup/fetch` for requests, replacing Axios from prior versions. This enables cross-platform compatibility, leveraging native `fetch` in browsers and `node-fetch` in Node.js, making it suitable for modern JavaScript projects.
Common errors
-
ERR_REQUIRE_ESM
cause Attempting to `require()` the `webdav` package in a CommonJS environment when using version 5 or higher.fixChange `require('webdav')` to `import { ... } from 'webdav';` and ensure your `package.json` has `'type': 'module'`, or downgrade to `webdav` version 4.x. -
TypeError: client.getDirectoryContents is not a function
cause Incorrect import of `createClient` or `WebDAVClient`, often due to mixing default/named imports or CJS/ESM patterns.fixEnsure you are using `import { createClient } from 'webdav';` for named exports, and avoid `import createClient from 'webdav';` unless the library explicitly exports a default. Check for correct module resolution in your build configuration. -
Error: fetch failed (in Node.js) or TypeError: fetch is not a function (in older Node.js/browser environments)
cause Potential issues with `node-fetch` resolution by `@buttercup/fetch` in Node.js, or `fetch` not being globally available or correctly polyfilled in certain environments.fixVerify Node.js version compatibility (>=14 for v5). If in a custom environment or older browser, ensure `global.fetch` is correctly polyfilled. `@buttercup/fetch` should handle `node-fetch` transparently in supported Node.js versions. -
405 Method Not Allowed
cause The WebDAV server does not support the HTTP method being used (e.g., PUT, DELETE, MKCOL) for the requested resource or path, often due to server configuration or permissions.fixCheck the WebDAV server's configuration and permissions for the affected path. Some servers are read-only or restrict certain operations. Ensure your client's authentication details are correct.
Warnings
- breaking Version 5.x of the `webdav` library is ESM-only. CommonJS `require()` is no longer supported, requiring projects to adopt ES Modules syntax and configuration.
- breaking The underlying HTTP request library changed from Axios to `@buttercup/fetch` (which uses `node-fetch` in Node.js) in version 5.x. Direct reliance on Axios APIs or its error structure will no longer work.
- deprecated Support for version 4.x of the `webdav` library will be dropped in January 2025. This means no further security or stability bugfixes will be provided for v4.
- gotcha While Node.js 14+ is officially supported for `webdav` v5, active testing only occurs on Node.js 18 and newer. Issues encountered on older Node.js versions may require community support for resolution.
- gotcha Browser environments using `webdav` v5 require an ESM-compatible bundler (e.g., Webpack, Rollup) as UMD module format support was removed. Loading via a `<script>` tag is no longer directly supported for browser builds.
Install
-
npm install webdav -
yarn add webdav -
pnpm add webdav
Imports
- createClient
const { createClient } = require('webdav');import { createClient } from 'webdav'; - WebDAVClient
import WebDAVClient from 'webdav';
import { WebDAVClient } from 'webdav'; - createClient (web entrypoint)
import { createClient } from 'webdav'; // for older browser environments that need an explicit web entrypointimport { createClient } from 'webdav/web'; - FileStat (type)
import type { FileStat } from 'webdav';
Quickstart
import { createClient, FileStat } from 'webdav';
import * as fs from 'fs/promises'; // For Node.js file system operations
import path from 'path';
// Configure your WebDAV client
const webdavUrl = process.env.WEBDAV_URL ?? 'https://example.com/webdav/';
const username = process.env.WEBDAV_USERNAME ?? 'your-username';
const password = process.env.WEBDAV_PASSWORD ?? 'your-password';
const client = createClient(webdavUrl, {
username,
password
});
async function runWebDAVOperations() {
try {
console.log(`Connecting to WebDAV at: ${webdavUrl}`);
// 1. List contents of the root directory
const contents: FileStat[] = await client.getDirectoryContents('/');
console.log('Root directory contents:');
contents.forEach(item => {
console.log(`- ${item.type === 'directory' ? 'Dir' : 'File'}: ${item.filename} (size: ${item.size ?? 'N/A'} bytes)`);
});
// 2. Create a new directory
const newDirPath = '/test-directory';
await client.createDirectory(newDirPath);
console.log(`Directory created: ${newDirPath}`);
// 3. Upload a file
const localFilePath = path.join(__dirname, 'test-upload.txt');
await fs.writeFile(localFilePath, 'Hello, WebDAV from checklist.day!');
const remoteFilePath = `${newDirPath}/uploaded-file.txt`;
await client.putFileContents(remoteFilePath, await fs.readFile(localFilePath));
console.log(`File uploaded: ${remoteFilePath}`);
// 4. Download the file and verify content
const downloadedContent = await client.getFileContents(remoteFilePath, { format: 'text' });
console.log(`Downloaded content from ${remoteFilePath}: "${downloadedContent}"`);
// 5. Delete the uploaded file and directory
await client.deleteFile(remoteFilePath);
console.log(`File deleted: ${remoteFilePath}`);
await client.deleteFile(newDirPath); // Can delete directories too
console.log(`Directory deleted: ${newDirPath}`);
// Clean up local test file
await fs.unlink(localFilePath);
} catch (error) {
console.error('WebDAV operation failed:', error);
}
}
runWebDAVOperations();