Short answer: a 501 Not Implemented error means the server does not support what the request asked for, usually the HTTP method: a WebDAV method such as PROPFIND, or PUT and DELETE sent to a server that only serves files. Less often it is a Transfer-Encoding the server cannot decode. Fix it on the server or proxy that answered.
# Which method fails? Send it yourself and read the status line
curl -s -i -X PUT --data 'hello' https://example.com/upload/test.txt | head -n 5
curl -s -i -X PROPFIND -H 'Depth: 1' https://example.com/dav/ | head -n 5
# What does the server say it accepts, and which software answers?
curl -s -i -X OPTIONS https://example.com/ | grep -i -E '^(HTTP|allow|server)'Replace the URL with the one that fails, and the method with the one your app, client or log shows. Do not test HEAD with -X HEAD: curl then waits for a body that never comes. Use curl -I instead. More request recipes are in the curl examples guide.
What does 501 Not Implemented mean?
RFC 9110, the current HTTP specification, defines it in one sentence: the server “does not support the functionality required to fulfill the request”, and it is the right answer “when the server does not recognize the request method and is not capable of supporting it for any resource”. The key words are for any resource. A server that knows the method but does not allow it at this URL should say 405 Method Not Allowed instead. RFC 9112 adds a second case: a request with a transfer coding the server does not understand should also get a 501.
| Status | What it says | Typical trigger |
|---|---|---|
| 501 Not Implemented | The server does not support this method or feature at all | An unknown method, a WebDAV method on a server without DAV, an unsupported Transfer-Encoding |
| 405 Method Not Allowed | The method exists, but this URL does not take it; the response must list the allowed ones in an Allow header | PUT or DELETE on a static file, POST to a page that only serves GET |
| 400 Bad Request | The request itself is malformed | Invalid characters in the method, broken headers, Content-Length and Transfer-Encoding together |
| 403 Forbidden | Understood, but refused by a rule | A WAF rule or an nginx limit_except block that denies the method |
In practice the line is blurry, because servers disagree about which code fits. The same unknown method gets a 405 from nginx, a 501 from Apache and a 400 from Node.js, as the next table shows. The status tells you which software answered at least as much as what went wrong. A 501 is a server-side status like a 500 Internal Server Error, but it is not a crash: the server understood the request well enough to decline it.
What nginx, Apache and others answer
| Request | nginx, static files | Apache 2.4, static files | Python http.server | Node.js http |
|---|---|---|---|---|
Unknown method, e.g. FOO | 405 | 501, page text FOO not supported for current URL. | 501 | 400, before your code runs |
PUT, DELETE, PROPFIND without DAV | 405 | 405, The requested method PUT is not allowed for this URL. | 501 | Whatever your handler returns |
OPTIONS | 405 | 200 with an Allow header | 501 | Whatever your handler returns |
A Transfer-Encoding other than chunked | 501 | 400 when chunked is not the last coding | Not checked | 400 for identity |
The nginx and Apache columns follow their source code (nginx’s static and request modules, httpd 2.4’s core, protocol and error page code), read on 21 October 2026. The Python and Node.js columns were checked on Debian 12 with Python 3.11.2 and Node.js 25.7.0. Python’s built-in server only implements GET and HEAD, so everything else is a 501:
$ curl -s -i -X PUT http://127.0.0.1:18501/index.html
HTTP/1.0 501 Unsupported method ('PUT')
Server: SimpleHTTP/0.6 Python/3.11.2
Date: Wed, 21 Oct 2026 19:47:43 GMT
Connection: close
Content-Type: text/html;charset=utf-8
Content-Length: 356One more rule matters for reading these: when nginx hands a request to an app with proxy_pass or fastcgi_pass, it passes every well-formed method through except TRACE, which nginx always answers with a 405 itself. A 501 behind such a location came from the app, and the app’s own log has the reason.
The usual causes
WebDAV clients on a server without DAV
WebDAV (RFC 4918) adds methods of its own: PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK and UNLOCK. Mapping a web folder as a network drive in Windows Explorer, connecting to a server from the macOS Finder, file sync tools, calendar and contact clients and many backup apps all speak it. Point one at a plain web server and the first PROPFIND gets a 405 or a 501. Either enable DAV on the server (below) or point the client at the app that implements DAV itself, such as a self-hosted cloud or calendar server.
API methods that hit a static location or a dev server
A frontend that sends PUT, PATCH or DELETE to a URL that the web server maps to files, instead of to the API, gets a 405 from nginx and Apache. The 501 variant shows up with minimal servers: a mock backend started with python3 -m http.server refuses every OPTIONS request, and that includes the preflight a browser sends before a cross-origin PUT or JSON POST. The browser then reports a CORS failure, not the 501. The CORS error guide shows how the preflight must be answered.
Proxies, load balancers and WAFs in between
Between the client and your app there may be a CDN, a WAF, a load balancer and a reverse proxy, and any of them can refuse a method it does not know or does not allow. Some older forward proxies and appliances answer unknown methods with a 501 of their own. WAFs usually answer with a 403 instead: the OWASP Core Rule Set, for example, allows only a short list of methods by default. Compare the Server header and the error page with what your own server sends, then skip the layers in front and ask your server directly:
curl -s -i -X PUT --data 'x' \
--resolve example.com:443:203.0.113.10 https://example.com/api/items/1 | head -n 5If the direct request works and the normal one gets a 501, the layer in front refused it, and its configuration or its support documentation is the place to fix it.
An unsupported Transfer-Encoding
nginx accepts exactly one request transfer coding, chunked. Per its source code, any other value, such as identity or gzip, chunked, gets a 501, and the reason is logged only at the info level, which the default error log does not record: client sent unknown "Transfer-Encoding". Apache answers a 400 when chunked is not the last coding, as with identity. The senders are usually old HTTP libraries or custom clients. Fix the client: send a Content-Length or plain chunked, and compress the body with Content-Encoding if it must be compressed. To see nginx’s reason, raise the log level for a short test:
error_log /var/log/nginx/error.log info;Embedded and development servers
Web interfaces of routers, printers, cameras and other devices often implement GET and POST and nothing else, and so do quick development servers. A 501 from one of them is a statement of fact, not a fault. Use the device’s own app or API, or put a full web server in front of whatever needs more methods.
Fixing it on nginx
For an app behind nginx, make sure the location that receives the request passes it on, and that no limit_except block or static location in front catches it first. For plain file uploads over HTTP, nginx’s own DAV module handles PUT, DELETE, MKCOL, COPY and MOVE. It does not handle PROPFIND, OPTIONS or LOCK, which is what a mapped network drive needs; those come from the third-party dav-ext module, which Debian and Ubuntu package as libnginx-mod-http-dav-ext. Check what your build has:
nginx -V 2>&1 | tr ' ' '\n' | grep -i dav
ls /etc/nginx/modules-enabled/ | grep -i davlocation /upload/ {
root /var/www;
dav_methods PUT DELETE MKCOL COPY MOVE;
create_full_put_path on;
dav_access user:rw group:r all:r;
# everyone may read; every other method needs the password
limit_except GET HEAD {
auth_basic "upload";
auth_basic_user_file /etc/nginx/upload.htpasswd;
}
}sudo nginx -t && sudo systemctl reload nginxThe directory must be writable by the nginx worker user (www-data on Debian and Ubuntu), and large uploads also need client_max_body_size, as the 413 guide explains. The config above is written from nginx.org’s documentation for ngx_http_dav_module and limit_except; run nginx -t before every reload.
Fixing it on Apache
Apache ships WebDAV as mod_dav with the file system provider mod_dav_fs, covering PROPFIND and the other DAV methods. Enable both and switch DAV on for one directory only, behind authentication:
sudo a2enmod dav dav_fs
sudo mkdir -p /var/www/dav && sudo chown www-data:www-data /var/www/dav
sudo htpasswd -c /etc/apache2/webdav.passwd alice
sudo apache2ctl -M | grep -i dav<Directory /var/www/dav>
Dav On
AuthType Basic
AuthName "WebDAV"
AuthUserFile /etc/apache2/webdav.passwd
Require valid-user
</Directory>sudo apache2ctl configtest && sudo systemctl reload apache2Two Apache settings produce refusals that look like a missing feature:
HttpProtocolOptions RegisteredMethodsmakes Apache answer 501 to every method that is not registered, already while it parses the request. The default isLenientMethods; a custom method can be allowed withRegisterHttpMethod.<Limit>and<LimitExcept>blocks withRequire all deniedrefuse methods with a 403, not a 501.
sudo grep -rn -E 'HttpProtocolOptions|RegisterHttpMethod|<Limit' /etc/apache2/ /var/www/Why a fixed 501 can keep coming back
RFC 9110 lists 501 among the status codes a cache may store by heuristic, like 404 and 405, as long as no header says otherwise. A browser or a CDN can therefore keep serving the old 501 after you have fixed the server. Test with curl, which keeps no cache, and purge the CDN for that URL. On error pages you generate yourself, send Cache-Control: no-store.
The HTTP header checker shows the status code and headers from outside your network, which tells you whether a CDN still answers with a stored copy.
Find every 501 in your logs
On a VPS or dedicated server you run every layer yourself, so each 501 is in an access log together with its method. In the default combined log format, the method is field 6 (with the opening quote of the request line, which substr strips) and the status field 9:
sudo awk '$9 == 501 {print substr($6, 2), $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# Apache: the same with /var/log/apache2/access.logA burst of 501s or 405s for methods you never use, from addresses you do not know, is usually a scanner probing for WebDAV or debug methods. It needs no fix beyond keeping those methods switched off.
For search engines, a 501 counts as a server error like any other 5xx. Google’s crawler documentation says 5xx answers make Googlebot slow down, and URLs that keep failing are eventually dropped from the index. Googlebot fetches pages with GET, so a 501 on a normal page is always worth fixing: something in front of the site refuses the most basic request there is.
Frequently asked
What does 501 Not Implemented mean?
The server does not support the functionality the request needs, usually its HTTP method. RFC 9110 reserves 501 for a method the server does not recognise for any resource; a method it knows but does not allow at that URL should get 405 Method Not Allowed. A request with a Transfer-Encoding the server cannot decode can also get a 501.
What is the difference between 501 and 405?
501 says the server does not support the method at all. 405 says it knows the method but this URL does not accept it, and the response must list the allowed methods in an Allow header. Servers differ in practice: an unknown method such as FOO gets 405 from nginx serving a static file, 501 from Apache and 400 from Node.js's built-in HTTP server.
How do I fix a 501 error for WebDAV or PROPFIND?
Enable WebDAV on the server, or route the path to an app that implements it. On Apache, enable mod_dav and mod_dav_fs and set Dav On for one directory behind authentication. nginx's built-in DAV module handles PUT, DELETE, MKCOL, COPY and MOVE but not PROPFIND, which needs the third-party dav-ext module.
Can a visitor fix a 501 error?
Rarely. A 501 is the server's answer, so the fix is on the server or on the proxy in front of it. Clearing the browser cache only helps when an old, cached 501 is shown. If a normal page returns 501 in every browser, report the URL and the time to the site owner.