405 Method Not Allowed: What It Means and How to Fix It
01Introduction
A 405 Method Not Allowed error means the server understood your request and recognizes the HTTP method you used — GET, POST, PUT, DELETE — but that method isn't permitted on the resource you called. The route exists; the verb is wrong for it.
The quickest tell is in the response itself. Per the HTTP specification (RFC 9110, §15.5.6), a server returning 405 must include an Allow header listing the methods the resource does accept. That header is the fix hiding in plain sight — it tells you exactly which method to switch to.
Here's a 405 in practice. You send a POST to a read-only endpoint:
POST /api/data HTTP/1.1
Host: example.com
Content-Type: application/json
{"key": "value"}The server responds:
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD
Content-Type: text/htmlTranslation: this resource takes GET or HEAD, not POST. The error isn't the hard part — figuring out why the method is blocked, when the endpoint, the server config, and a framework router can all be the cause, is where the time goes.
02What a 405 Actually Means
HTTP methods define the action a request performs: GET reads, POST creates, PUT and PATCH update, DELETE removes. Every resource on a server declares which of those it supports. When your method isn't on that list, the server rejects the request with a 405 rather than attempting it.
The distinction that trips people up: a 405 is not "the server broke" and not "the page doesn't exist." The server is working correctly and the resource is there. It's specifically saying this verb is not valid here — and it's obligated to tell you which verbs are.
03405 vs 400, 401, 403, 404, and 501
405 is easy to confuse with the status codes around it. They fail for genuinely different reasons, and reading the wrong one sends you debugging the wrong thing:
| Code | Name | What it actually means | How it differs from 405 |
|---|---|---|---|
| 400 | Bad Request | The request itself is malformed — bad syntax, invalid JSON, missing required fields. | The verb is fine; the content is broken. A 405 is a well-formed request with the wrong method. |
| 401 | Unauthorized | Authentication is missing or failed. | 401 is about who you are. 405 doesn't care who you are — the method is wrong for everyone. |
| 403 | Forbidden | You're authenticated but not permitted to do this. | 403 is a permission decision on an allowed action. 405 means the action (method) itself isn't allowed on the resource. |
| 404 | Not Found | The resource or route doesn't exist. | 404 = the path is wrong. 405 = the path is right, the method is wrong. |
| 501 | Not Implemented | The server doesn't support the method at all, for any resource. | 501 is server-wide ("we don't do PATCH here, anywhere"). 405 is resource-specific ("this endpoint doesn't do PATCH, others might"). |
If you remember one line: 404 means the door isn't there; 405 means the door is there but locked to that knock.
04What Triggers a 405
The error surfaces in a handful of recurring situations:
- Wrong HTTP method for the endpoint. REST APIs are strict.
/usersmight acceptPOSTto create a record but rejectPUTbecause updates happen at/users/{id}. Sending the right verb to the wrong level still returns 405. - Server configuration blocking the method. Apache and Nginx can restrict methods at the config level. A rule meant to lock down
DELETEorPUTfor safety can overreach and block legitimate traffic. - API endpoint rules. A
GET-only endpoint hit withDELETEreturns an immediate 405. This is the endpoint enforcing its own contract, and it's easy to miss when the docs aren't in front of you. - Security filtering. Web Application Firewalls (WAFs) like Cloudflare sometimes block methods such as
TRACE,OPTIONS, orPATCHto reduce attack surface — producing 405s even when the origin server would have allowed the method. - Framework routing gaps. In most web frameworks, a route registered for one method won't answer another. Depending on the framework, sending the wrong verb returns either a 405 or a 404 (more on that below).
05How to Fix a 405 Method Not Allowed Error
The fix is always: find the cause, then correct the request or the config. Work through these in order.
1. Confirm which method the endpoint expects
Read the Allow header on the 405 response first — it lists the valid methods. If you don't have one, probe the endpoint with OPTIONS:
curl -X OPTIONS https://api.example.com/users -iA typical response:
HTTP/1.1 200 OK
Allow: GET, POST, HEADMatch your request to that list. If it says Allow: POST and you were sending PUT, that's your answer.
2. Check the server configuration
If the endpoint should accept your method but doesn't, inspect the server config.
Apache — look for Limit directives in .htaccess or httpd.conf:
<Limit GET POST PUT>
Order Allow,Deny
Allow from all
</Limit>Nginx — check limit_except in the relevant location block:
location /api {
limit_except GET POST DELETE {
deny all;
}
}Reload after changes (systemctl reload apache2 or nginx -s reload).
3. Check security filters and WAF rules
If a WAF sits in front of the origin, review its ruleset — it may be stripping methods before they reach your server. Whitelist the legitimate method rather than disabling the rule wholesale, so you don't trade a 405 for an actual vulnerability.
4. Fix the framework route
Make sure a handler exists for the method you're sending. In Express:
app.delete('/posts/:id', (req, res) => {
// delete logic
});No DELETE handler means no valid response for that verb.
5. Rule out permissions
If the method is allowed but tied to a role, a missing or wrong token can produce a 405 or 403. Send the request with auth attached and compare:
curl -X DELETE https://api.example.com/posts/1 \
-H "Authorization: Bearer <token>" -i6. Read the server logs
Logs tell you whether the block came from config or from the method itself. Nginx (/var/log/nginx/error.log):
2026/06/30 10:00:00 [error] 1234#0: *1 method not allowed
Apache (/var/log/apache2/error.log):
[Tue Jun 30 10:00:00.2026] [error] Method PUT not allowed for /api/data
Follow the trail from there to the config line or route responsible.
06Framework-Specific 405s (and the "works in the browser, fails in the client" case)
A recurring source of confusion: the same URL behaves differently depending on what sends the request. Pasting a URL into a browser issues a GET. An API client — Postman, curl, Voiden — can issue POST, PUT, or DELETE. So a route that only accepts GET will load fine in a browser and then return a 405 (or a 404) the moment a client sends a different verb. If a request "works in the browser but not in the client," check the method before anything else.
How different stacks report the same underlying problem:
- Laravel / Symfony throw
MethodNotAllowedHttpException(fromSymfony\Component\HttpKernel\Exception) when the path matches a route but the HTTP method doesn't. SeeingMethodNotAllowedHttpExceptionin a stack trace is the framework telling you the route exists for a different verb — check yourRoute::definitions or the controller's allowed methods. - Spring raises
HttpRequestMethodNotSupportedException, mapped to 405, when no handler matches the request method. - Django REST Framework returns its
MethodNotAllowedexception as a 405 when a viewset doesn't implement the method. - Express is the exception worth knowing: by default it does not return 405 for an unhandled method — it falls through to a 404 (
Cannot POST /posts). To get a proper 405 with anAllowheader, you handle it explicitly (for example withapp.all()on the route, or a router that tracks registered methods). If you expected a 405 and got a 404 in Node, this is usually why.
07Testing and Reproducing a 405
Reproducing the error deliberately is the fastest way to confirm the cause. Three tools cover most workflows:
- curl — the quickest way to fire a single request with an explicit method and read the raw
Allowheader. Ideal for one-off checks:· bashcurl -X PUT https://api.example.com/data -i - Postman — a GUI client for sending requests across methods and inspecting responses, useful when you're clicking through an API interactively.
- Voiden — an offline-first, Git-native API client that stores requests as Markdown-based
.voidfiles you can version alongside your code. Because the requests live in your repo, the exactPOST-vs-PUTcall that triggered a 405 is committed, diffable, and reproducible by anyone who checks out the branch — rather than trapped in one person's local client. Voiden is open source (Apache 2.0); you can download it here.
None of these fix the server — they let you see precisely which method the resource accepts, so you correct the request with certainty instead of guessing.
08Where ApyHub Fits
A large share of 405s in day-to-day work come from calling an endpoint with the wrong verb because the method contract wasn't obvious. That's a documentation-and-consistency problem as much as a coding one.
ApyHub is a certified API marketplace — a catalog of 200+ APIs and 1,000+ endpoints for the utility work most products need (file conversion, data validation, PDF processing, enrichment, and more). Every endpoint in the catalog ships with a documented, machine-readable specification, including the methods it accepts, so the "which verb does this take" question is answered before you write the call — and answerable by AI agents consuming the catalog through MCP, not just humans reading docs. It doesn't make 405s impossible, but it removes one of the most common ways developers stumble into them: guessing at an undocumented method contract.
09Conclusion
A 405 Method Not Allowed error is a signal, not a mystery: the resource exists, the method doesn't fit it, and the Allow header is telling you what does. Confirm the expected method, check server config and WAF rules, verify your framework route, and read the logs — in that order — and the fix is usually a one-line change. The habit that prevents most of them is knowing an endpoint's method contract before you call it, rather than discovering it from a rejected request.
10FAQ
What exactly causes a 405 Method Not Allowed error?
The server recognizes your HTTP method but the specific resource you called doesn't permit it — for example, sending DELETE to an endpoint built only for GET and POST. The response includes an Allow header listing the methods that are accepted, which tells you what to switch to.
How do I find out which HTTP methods an endpoint supports?
Read the Allow header on the 405 response, or send an OPTIONS request: curl -X OPTIONS https://api.example.com/resource -i. The response's Allow header lists every method the endpoint accepts.
What's the difference between a 403 and a 405 error?
A 403 Forbidden means you're not permitted to perform an action you're otherwise allowed to request — it's about authorization. A 405 means the HTTP method itself isn't valid for that resource, regardless of who you are.
What's the difference between a 404 and a 405?
A 404 means the route or resource doesn't exist. A 405 means the route exists but doesn't accept the method you used. If you're getting a 404 when you expected a 405, your framework may be treating an unhandled method as a missing route (Express does this by default).
Why does my request work in the browser but fail in Postman or curl?
A browser issues a GET when you load a URL, while an API client can send POST, PUT, or DELETE. A route that only allows GET will load in the browser and return a 405 (or 404) from the client. Check the method your client is sending first.
What does MethodNotAllowedHttpException mean?
It's the exception Symfony and Laravel throw when a request's path matches a defined route but its HTTP method doesn't. Seeing it means the route exists for a different verb — check your route definitions and correct the method or add a handler for the one you're sending.
Can a Web Application Firewall cause a 405 error?
Yes. WAFs such as Cloudflare may block methods like TRACE, PATCH, or OPTIONS to reduce attack surface, producing a 405 even when the origin server would allow the method. Review the WAF ruleset and whitelist the legitimate method rather than disabling the rule.
How do I prevent 405 errors during development?
Validate each request against the endpoint's method contract before deploying, and keep those contracts documented and version-controlled so the whole team calls endpoints the same way. Consuming APIs whose specifications already declare their accepted methods removes the most common cause — guessing at an undocumented verb.
