Skip to main content

WebDAV Protocol: Web-Based Distributed Authoring 2026

Created: March 11, 2026 Larry Qu 9 min read

Introduction

WebDAV (Web-based Distributed Authoring and Versioning) extends HTTP with methods for remote file operations, enabling web servers to function as full-featured file servers with locking, metadata, and directory support. Unlike plain HTTP file uploads, WebDAV provides a structured protocol for collaborative editing where multiple users can read, write, lock, and organize files on a remote server through standard HTTP verbs and XML request bodies.

This guide covers the WebDAV protocol methods, server configuration for Apache and Nginx, a complete Python client implementation with detailed explanation of each operation, file locking semantics, and a comparison with alternative approaches (S3, FTP, SCP) so you can choose the right tool for your use case.

How WebDAV Works

WebDAV operates as an HTTP extension using existing verbs (GET, PUT, DELETE) plus new methods (PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK). A WebDAV client communicates with a WebDAV-enabled server by sending these HTTP requests, and the server responds with XML bodies describing resources, properties, and lock status.

sequenceDiagram
    participant Client as WebDAV Client
    participant Server as WebDAV Server

    Client->>Server: PROPFIND / (list directory)
    Server-->>Client: 207 Multi-Status (XML with file list)
    Client->>Server: GET /docs/report.pdf (download)
    Server-->>Client: 200 OK (binary data)
    Client->>Server: LOCK /docs/report.pdf (prevent conflicts)
    Server-->>Client: 200 OK (Lock-Token header)
    Client->>Server: PUT /docs/report.pdf (upload new version)
    Server-->>Client: 204 No Content
    Client->>Server: UNLOCK /docs/report.pdf (release lock)
    Server-->>Client: 204 No Content

The XML responses use the DAV: namespace and contain property data for each resource. This design lets clients discover file metadata without separate API calls — a single PROPFIND returns file sizes, modification dates, content types, and custom properties for an entire directory tree.

WebDAV Methods

Standard HTTP + WebDAV Methods

Method Description Request Body Response
GET Read file contents None File binary data
PUT Upload or overwrite a file File binary data 200/201/204
DELETE Remove a file or collection None 200/204
PROPFIND Retrieve resource properties and list directory contents XML (depth, prop specs) 207 Multi-Status (XML)
PROPPATCH Modify resource properties XML (property updates) 207 Multi-Status
MKCOL Create a new directory (collection) None 201 Created
COPY Copy a resource to a new location XML (destination, depth) 201/204
MOVE Move or rename a resource XML (destination) 201/204
LOCK Lock a resource for exclusive or shared write access XML (lock scope, owner) 200 + Lock-Token
UNLOCK Release a lock Lock-Token header 204 No Content

PROPFIND in Detail

PROPFIND is the most distinctive WebDAV method. The client sends a Depth header (0 for single resource, 1 for immediate children, infinity for entire tree) and optionally an XML body requesting specific properties:

<?xml version="1.0" encoding="utf-8"?>
<propfind xmlns="DAV:">
  <prop>
    <displayname/>
    <getcontentlength/>
    <getcontenttype/>
    <getlastmodified/>
    <resourcetype/>
  </prop>
</propfind>

The server responds with a 207 Multi-Status containing a <multistatus> element with <response> entries for each resource. Each response includes the resource URL (<href>) and the requested property values. This is how the client discovers what files and directories exist at a given path without needing a separate index.

Server Configuration

Apache WebDAV

Apache supports WebDAV through the mod_dav and mod_dav_fs modules. The configuration below sets up a password-protected WebDAV share with HTTPS:

# /etc/apache2/sites-available/webdav.conf

<VirtualHost *:443>
    ServerName dav.example.com
    DocumentRoot /var/www/webdav

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key

    DAV On
    Options +Indexes

    <Location /webdav>
        DAV On
        AuthType Basic
        AuthName "WebDAV"
        AuthUserFile /etc/apache2/.htpasswd
        Require valid-user
    </Location>
</VirtualHost>

This config enables WebDAV on the /webdav path with basic authentication. The AuthUserFile is created with htpasswd -c /etc/apache2/.htpasswd username. For production, prefer digest authentication or integrate with LDAP, and always use HTTPS since Basic auth transmits credentials in every request.

Enable the required modules and restart Apache:

sudo a2enmod dav dav_fs
sudo a2ensite webdav.conf
sudo systemctl restart apache2

Nginx WebDAV

Nginx supports WebDAV through the ngx_http_dav_module, though it lacks PROPFIND and locking support in the default module. For full WebDAV support, use the nginx-dav-ext-module (compile Nginx with --add-module=nginx-dav-ext-module):

# /etc/nginx/sites-available/webdav

server {
    listen 443 ssl;
    server_name dav.example.com;

    ssl_certificate /etc/ssl/certs/server.crt;
    ssl_certificate_key /etc/ssl/private/server.key;

    root /var/www/webdav;

    # Enable WebDAV methods
    dav_methods PUT DELETE MKCOL COPY MOVE;
    dav_ext_methods PROPFIND PROPPATCH;

    # Require authentication for writes
    auth_basic "WebDAV";
    auth_basic_user_file /etc/nginx/.htpasswd;

    # Allow creating files with PUT
    create_full_put_path on;
    dav_access user:rw group:rw all:r;

    location / {
        autoindex on;
    }
}

The create_full_put_path on directive lets clients create intermediate directories automatically when uploading files — useful for clients that structure files in nested paths. Nginx’s built-in module handles the basic WebDAV methods, and the extension module adds property retrieval and modification.

Python WebDAV Client

The following client class implements the core WebDAV operations using Python’s requests library. Each method maps to a specific HTTP verb and handles the corresponding response codes.

import requests
from requests.auth import HTTPBasicAuth

class WebDAVClient:
    """A lightweight WebDAV client that wraps HTTP requests.

    Each method corresponds to a WebDAV operation. The client
    maintains an authenticated session so credentials are sent
    with every request automatically.
    """

    def __init__(self, base_url, username, password):
        """Initialize with server URL and credentials.

        Args:
            base_url: Root URL of the WebDAV server (e.g. https://dav.example.com/webdav)
            username: WebDAV authentication username
            password: WebDAV authentication password
        """
        self.base_url = base_url
        self.session = requests.Session()
        self.session.auth = HTTPBasicAuth(username, password)

    def upload(self, local_path, remote_path):
        """Upload a local file to the WebDAV server.

        Uses HTTP PUT to write file contents. The server creates
        or overwrites the resource at the given remote path.
        Returns True on success (201 Created or 204 No Content).
        """
        with open(local_path, 'rb') as f:
            response = self.session.put(
                f"{self.base_url}/{remote_path}",
                data=f
            )
        # 200 OK (overwrite), 201 Created (new), 204 No Content (accepted)
        return response.status_code in (200, 201, 204)

    def download(self, remote_path, local_path):
        """Download a remote file and save it locally.

        Uses HTTP GET to retrieve the resource content.
        Returns True only on 200 OK.
        """
        response = self.session.get(f"{self.base_url}/{remote_path}")
        with open(local_path, 'wb') as f:
            f.write(response.content)
        return response.status_code == 200

    def list_files(self, path='/'):
        """List resources at the given path.

        Sends a PROPFIND request with Depth: 1 to retrieve
        immediate children. The server returns XML with resource
        URLs and properties. This method returns the raw XML
        response text for parsing.
        """
        response = self.session.request(
            'PROPFIND',
            f"{self.base_url}/{path}",
            headers={'Depth': '1'}  # 0=self, 1=children, infinity=all
        )
        return response.text

    def delete(self, path):
        """Delete a resource (file or empty directory).

        Uses HTTP DELETE. The server returns 200 or 204 on success.
        """
        response = self.session.delete(f"{self.base_url}/{path}")
        return response.status_code in (200, 204)

    def create_directory(self, path):
        """Create a new directory (collection).

        Uses the MKCOL method. The server creates the collection
        and returns 201 Created on success.
        """
        response = self.session.request('MKCOL', f"{self.base_url}/{path}")
        return response.status_code in (200, 201)

Usage Example

Here is how you use the client to interact with a WebDAV server:

client = WebDAVClient(
    base_url="https://dav.example.com/webdav",
    username="alice",
    password="secure-pass"
)

# Upload a file
if client.upload("report.pdf", "docs/report.pdf"):
    print("Upload succeeded")

# List directory contents
files_xml = client.list_files("docs/")
print(files_xml)  # XML with file names, sizes, modification dates

# Download a file
if client.download("docs/report.pdf", "downloaded_report.pdf"):
    print("Download succeeded")

# Create a new directory
client.create_directory("docs/archive")

# Delete a file
client.delete("docs/report.pdf")

File Locking

WebDAV provides two locking mechanisms to prevent conflicting edits: exclusive locks (one user at a time) and shared locks (multiple readers). Locks are managed through the LOCK and UNLOCK methods with an XML body specifying the lock scope and type.

How Locking Works

def lock(self, path, timeout=60):
    """Acquire an exclusive write lock on a resource.

    The XML body specifies:
    - lockscope: exclusive (single writer) or shared (multiple)
    - locktype: write (prevents writes from others)

    The server returns a Lock-Token header that must be
    included in subsequent UNLOCK requests.
    """
    headers = {
        'Timeout': f'Second-{timeout}',
        'Content-Type': 'application/xml'
    }
    body = '''<?xml version="1.0"?>
<d:lockinfo xmlns:d="DAV:">
  <d:lockscope><d:exclusive/></d:lockscope>
  <d:locktype><d:write/></d:locktype>
</d:lockinfo>'''

    response = self.session.request(
        'LOCK',
        f"{self.base_url}/{path}",
        headers=headers,
        data=body
    )
    # Returns the opaque token string, or None if lock failed
    return response.headers.get('Lock-Token')

def unlock(self, path, lock_token):
    """Release a previously acquired lock.

    The Lock-Token value from the LOCK response must be
    sent in the Lock-Token header to identify which lock
    to release.
    """
    headers = {'Lock-Token': lock_token}
    response = self.session.request(
        'UNLOCK',
        f"{self.base_url}/{path}",
        headers=headers
    )
    return response.status_code in (200, 204)

The XML body sent with the LOCK request tells the server what kind of lock is requested:

  • Exclusive lock: Only the lock owner can modify the resource. Other clients that attempt to PUT or PROPPATCH the locked resource receive a 423 Locked status.
  • Shared lock: Multiple clients can hold the lock simultaneously. Useful for collaborative editing where multiple users read the same file.

The Lock-Token returned by the server is an opaque URL (e.g., urn:uuid:...). Clients must store this token and include it when unlocking or modifying the locked resource. If a client crashes after locking but before unlocking, an administrator can break the lock through server-side tools (e.g., Apache’s dav_fs provides lock management utilities).

Best Practices

Always use HTTPS. WebDAV transmits authentication credentials and file contents over the wire. Without TLS, credentials sent in Basic auth headers are base64-encoded (not encrypted) and trivially intercepted.

Implement proper authentication. Basic auth over HTTPS is adequate for most use cases. For enterprise deployments, integrate with LDAP, Active Directory, or OAuth2.

Use locks for concurrent editing. Without locking, two clients can overwrite each other’s changes silently. Locks serialize writes and prevent conflicts. Set timeouts appropriate to your workload — long enough for a single edit session (60-300 seconds), short enough that abandoned locks are released promptly.

Set appropriate timeout values. The Timeout header in LOCK requests specifies seconds before the lock auto-expires. Servers may enforce maximum timeouts (Apache defaults to 120 seconds). The actual timeout is the minimum of client request and server limit.

Consider client compatibility. Not all operating systems and file managers support WebDAV equally. macOS Finder and Windows Explorer have built-in WebDAV support. Linux users typically mount via davfs2. Mobile support is limited — use a dedicated client app or your own Python client.

Alternatives Comparison

Feature WebDAV S3 API FTP/SFTP SCP
Protocol HTTP/HTTPS HTTP/HTTPS TCP port 21/22 SSH (port 22)
Directory listing PROPFIND (XML) GET ?list-type=2 LIST/MLSD None
Locking Built-in (LOCK/UNLOCK) None native None None
Metadata Arbitrary properties via PROPPATCH Tags + user metadata File modification time only File modification time
Firewall friendly Yes (port 443) Yes (port 443) No (requires multiple ports) Yes (port 22)
Client support OS file managers, Python, JS AWS SDK, HTTP CLI, GUI clients CLI (scp)
Best for Collaborative editing, cloud storage Object storage, CDN, data lakes Server file transfer Quick one-off file copy

WebDAV excels in scenarios where users need to edit files remotely with conflict prevention, especially in enterprise environments with existing HTTP infrastructure. S3 is better suited for scalable object storage with high availability. FTP/SFTP remains practical for bulk server-to-server transfers. SCP is the simplest option for ad-hoc file copying but offers no directory browsing or locking.

Conclusion

WebDAV fills a specific niche: HTTP-based remote file management with locking and metadata support. It integrates naturally with existing web infrastructure (same ports, same authentication mechanisms) and works with operating system file managers for a native experience. For collaborative editing workflows where multiple users need to read, write, and organize files on a remote server with conflict prevention, WebDAV remains the best available standard protocol.

The Python client implementation in this guide gives you a foundation you can extend with XML response parsing, recursive upload/download, and progress reporting — all built on the simple HTTP request model.

Resources

Comments

👍 Was this article helpful?