405 Method Not Allowed
Client Error
The request method is known by the server but is not supported by the target resource. For example, a client attempts POST on an endpoint that only accepts GET, or DELETE on a read-only resource. The response must include an Allow header listing the methods the resource does support. Clients and tooling rely on this header to discover the correct method without trial and error.
When does this happen?
Return 405 when the URL matches a route but the route does not handle the method the client used. Common cases include API endpoints that only accept POST being hit with GET (e.g., a search-by-body endpoint), CDN-cached pages where the CDN only permits GET and HEAD, and read-only assets where the client mistakenly issued DELETE. Web servers like Nginx and Apache return 405 for static files that are accessed via a method other than GET or HEAD. Browsers will not display anything special for a 405. The client must handle it in code. The Allow header is mandatory by spec, although in practice some frameworks omit it; if you control the server, make sure your handler emits Allow with the correct list of methods. Be wary of CORS preflight: if your OPTIONS handler returns 405 because you forgot to enable OPTIONS on the route, every cross-origin request will fail in browsers.
Common causes
- Client used POST against a GET-only endpoint or vice versa. Common when SDKs are out of sync with API changes.
- DELETE issued against a resource the API does not allow deletion on. Frequent in append-only or audit-log APIs.
- CORS preflight OPTIONS hit a route that does not handle OPTIONS. Every cross-origin request will fail until OPTIONS is wired up.
- PATCH used where the API only accepts PUT, or vice versa. Some frameworks differentiate strictly.
- Reverse proxy or CDN configured to only allow GET/HEAD. Common for static asset hosts.
- Server framework's route table is incomplete and the requested method falls through to a default 405 handler.
- Client library defaults to GET but the server expects POST for safe-but-large query bodies.
How to fix it
- Inspect the Allow header in the 405 response. It lists every method the endpoint accepts, no guessing required.
- Switch to the correct HTTP method based on the API documentation or the Allow header.
- Wire up an OPTIONS handler if cross-origin browser requests are getting 405. CORS preflight requires it.
- If you are the server operator, confirm your router has explicit handlers for every method the resource supports and that the framework emits Allow on rejection.
- Check CDN/proxy configuration if static-asset paths return 405 unexpectedly. Many CDNs block non-GET methods by default.
- For SDK mismatches, regenerate the SDK from the latest OpenAPI spec. Method drift is the most common cause of 405 in production traffic.
- Avoid using POST for everything just to dodge 405. Losing GET cacheability has a real performance cost.
Real-world examples
- API client calls DELETE /v1/orders/{id} on an audit-log API where orders are immutable.
- Server returns 405 with Allow: GET, POST and body {"error":"method_not_allowed"}. Client switches to a void or cancel endpoint instead.
- Single-page app makes a cross-origin POST to api.example.com but OPTIONS is not registered on the route.
- Browser preflight gets 405. The real POST is never sent. Console shows a CORS error and the developer adds an OPTIONS handler.
- Developer types curl https://example.com/upload (which defaults to GET) on an upload endpoint that only accepts POST.
- Server returns 405 with Allow: POST. Developer reruns with -X POST and includes the file body.
- CDN-fronted static asset path is requested with PUT by a tool attempting to deploy via the wrong API.
- CDN returns 405 with Allow: GET, HEAD. The deploy tool falls back to the correct upload endpoint.
- API documentation says PATCH for partial updates but the framework only registered PUT.
- Server returns 405 with Allow: PUT. Client switches to PUT with a full resource body until the API is fixed.
Debugging
- Run curl -I -X DELETE https://api.example.com/v1/orders/123 and read the Allow header to discover which methods are supported.
- Run curl -X OPTIONS https://api.example.com/v1/orders/123 to inspect the CORS preflight response and confirm OPTIONS is wired up.
- Check the API documentation or OpenAPI spec for the endpoint to confirm which methods it accepts.
- If 405 is intermittent, check whether a CDN or edge layer is rewriting your method or blocking it before it reaches the origin.
How it differs from related codes
HTTP 400
400 is for malformed requests at the syntax level. 405 is specifically about the method being wrong for an otherwise-valid URL.
HTTP 404
404 means the URL is unknown. 405 means the URL is known but the method does not apply. If you get 405, the route exists.
HTTP 501
501 means the server does not implement the method at all (e.g., the server does not understand PATCH globally). 405 is per-resource. Other URLs may support the same method fine.
Related status codes
See HTTP 405 in your redirect chains?