apyhub
Cover illustration for 405 Method Not Allowed: What It Means and How to Fix It Fast
Engineering

405 Method Not Allowed: What It Means and How to Fix It Fast

Updated September 2026. Refreshed against RFC 9110 with three details missing from the original: what an empty Allow header means, why proxies cannot touch it, and why a 405 on GET signals something more serious. Added a section on why AI agents hit this error far more often than people do, and corrected the catalog figures.

TL;DR: A 405 means the server understood your request and knows the method, but that method is not permitted on the resource you called. The route exists. The verb is wrong. The response is required to tell you which verbs are right.

01What a 405 Actually Means

A 405 Method Not Allowed error means the server understood your request and recognises the HTTP method you used, but that method is not permitted on the resource you called.

The quickest tell is in the response itself. RFC 9110 15.5.6 is explicit: the origin server MUST generate an Allow header in a 405 response, listing the methods the target resource currently supports.

That header is the fix hiding in plain sight.

Here is a 405 in practice. You send a POST to a read-only endpoint:

http

POST /api/data HTTP/1.1 Host: example.com Content-Type: application/json {"key": "value"}

The server responds:

http

HTTP/1.1 405 Method Not Allowed Allow: GET, HEAD Content-Type: text/html

This resource takes GET or HEAD, not POST.

The error is not the hard part. Working out why the method is blocked, when the endpoint, the server config, and a framework router can all be responsible, is where the time goes.

02Three Things the Spec Says That Most Guides Skip

An empty Allow header is meaningful. RFC 9110 10.2.1 states that an empty Allow value indicates the resource allows no methods at all, which can happen when a resource has been temporarily disabled by configuration. If you get a 405 with Allow: and nothing after it, the endpoint has not been misconfigured for your verb. It has been switched off.

A proxy must not modify the Allow header. The spec forbids intermediaries from rewriting it, precisely so the value you receive reflects what the origin server actually supports. If the Allow header looks wrong, suspect the origin rather than the CDN.

GET and HEAD are mandatory. All general-purpose servers must support both. So a 405 on a plain GET is not an ordinary method mismatch. Something is blocking it: a config rule, a WAF, or a resource that has been disabled.

03405 vs 400, 401, 403, 404, and 501

These fail for genuinely different reasons, and reading the wrong one sends you debugging the wrong thing.

CodeNameWhat it meansHow it differs from 405
400Bad RequestThe request is malformed. Bad syntax, invalid JSON, missing fields.The verb is fine, the content is broken.
401UnauthorizedAuthentication is missing or failed.401 is about who you are. 405 does not care who you are.
403ForbiddenAuthenticated but not permitted.403 is a permission decision on an allowed action.
404Not FoundThe route does not exist.404 means the path is wrong. 405 means the path is right.
501Not ImplementedThe server does not support the method anywhere.501 is server-wide. 405 is resource-specific.

RFC 9110 9.1 draws the 405 and 501 line precisely: a method that is unrecognised or not implemented gets 501, a method that is recognised and implemented but not allowed on that resource gets 405.

If you remember one line: 404 means the door is not there, 405 means the door is there but locked to that knock.

04What Triggers a 405

Wrong method for the endpoint. REST APIs are strict. /users might accept POST to create but reject PUT, because updates happen at /users/{id}. The right verb at the wrong level still returns 405.

Server configuration blocking the method. Apache and Nginx can restrict methods at config level. A rule written to lock down DELETE can overreach and block legitimate traffic.

Endpoint rules. A GET-only endpoint hit with DELETE returns an immediate 405. Easy to miss when the docs are not in front of you.

Security filtering. WAFs including Cloudflare commonly block TRACE, OPTIONS or PATCH to reduce attack surface. TRACE is the classic case: MDN documents servers disallowing it outright over security concerns.

Framework routing gaps. A route registered for one method usually will not answer another. What you get back depends heavily on the framework.

File and directory permissions. MDN notes that improper server-side permissions can produce a 405 where the request would otherwise have succeeded. Worth checking when nothing else explains it.

05How to Fix It

Work through these in order.

1. Read the Allow header

It lists the valid methods. If there is no header, probe with OPTIONS:

bash

· bash
curl -X OPTIONS https://api.example.com/users -i

http

HTTP/1.1 200 OK Allow: GET, POST, HEAD

Match your request to that list.

2. Check the server configuration

Apache - look for Limit directives in .htaccess or httpd.conf:

apache

<Limit GET POST PUT> Order Allow,Deny Allow from all </Limit>

Nginx - check limit_except in the relevant location block:

nginx

location /api { limit_except GET POST DELETE { deny all; } }

Reload after changes.

3. Check the WAF

If a firewall sits in front of the origin, it may be stripping methods before they arrive. Whitelist the legitimate method rather than disabling the rule, so you do not trade a 405 for a vulnerability.

4. Fix the framework route

Make sure a handler exists for the method you are sending:

javascript

· js
app.delete('/posts/:id', (req, res) => {
  // delete logic
});

5. Rule out permissions

bash

· bash
curl -X DELETE https://api.example.com/posts/1 \
  -H "Authorization: Bearer <token>" -i

6. Read the logs

Nginx (/var/log/nginx/error.log) and Apache (/var/log/apache2/error.log) will tell you whether the block came from config or from routing.

06Framework Differences

The same URL behaves differently depending on what sends the request. Pasting a URL into a browser issues a GET. An API client can issue anything. So a GET-only route loads fine in a browser and returns a 405 the moment a client sends something else.

If a request works in the browser but not in your client, check the method first.

FrameworkWhat you getNotes
Laravel / SymfonyMethodNotAllowedHttpExceptionThe path matched a route, the method did not. Check your Route:: definitions.
SpringHttpRequestMethodNotSupportedExceptionMapped to 405 when no handler matches the method.
Django REST FrameworkMethodNotAllowedReturned as 405 when a viewset does not implement the method.
Express404, not 405By default Express falls through to Cannot POST /posts. Handle it explicitly with app.all() to return a proper 405 with an Allow header.

The Express case catches people out constantly. If you expected a 405 and got a 404 in Node, that is usually why.

07Why AI Agents Hit This More Than You Do

This section did not exist when this article was first published. It is now the most common way teams meet a 405 at volume.

A human developer reads the docs, sees that an endpoint takes POST, and sends POST. An AI agent calling an API it discovered at runtime has to work out the verb from whatever it can see, and if the contract is not machine-readable, it guesses.

Guessing produces 405s. And the recovery depends entirely on what comes back.

An agent that receives a 405 with an Allow header fixes its own call. It reads Allow: GET, HEAD, switches the method, retries, succeeds. No human involved.

An agent that receives a bare 405 gives up, or worse, retries the same wrong verb in a loop until something rate-limits it.

That makes the Allow header, which the spec has required since 2022 and plenty of servers still omit, the difference between an agent recovering and an agent failing. It is a small piece of compliance with outsized consequences now that non-human callers are common.

Two practical implications.

If you publish an API, return the Allow header. It costs nothing and it is the single most useful thing you can do for automated consumers. The Express default of falling through to 404 is now actively harmful, because a 404 tells an agent the endpoint does not exist rather than that it used the wrong verb.

If you consume APIs with agents, prefer ones whose method contracts are machine-readable rather than described in prose. An agent that can read the contract never guesses.

This is part of why every endpoint in the ApyHub catalog is available over MCP. An agent connects, searches for the capability it needs, and reads the accepted method and input schema before calling anything. The 405 does not happen because the verb was never in question.

We covered how agents discover and sequence calls in How AI Agents Use APIs and API Chaining in 2026.

08Testing and Reproducing a 405

Reproducing it deliberately is the fastest way to confirm the cause.

curl fires a single request with an explicit method and shows the raw Allow header:

bash

· bash
curl -X PUT https://api.example.com/data -i

Postman is the GUI option for clicking through an API interactively.

Voiden is offline-first and Git-native, storing requests as Markdown-based .void files you can version alongside your code. The exact POST-versus-PUT call that triggered a 405 gets committed and diffed rather than trapped in one person's local client. Open source, Apache 2.0, download here.

None of these fix the server. They let you see exactly which method the resource accepts.

09Where ApyHub Fits

A large share of 405s come from calling an endpoint with the wrong verb because the method contract was not obvious. That is a documentation problem as much as a coding one.

ApyHub is a curated API catalog: 450+ services and 1,500+ endpoints covering the utility work most products need, including file conversion, data validation, OCR and extraction and domain intelligence.

Every endpoint 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. Answerable by AI agents through MCP, not just by humans reading docs.

It does not make 405s impossible. It removes the most common way developers and agents stumble into them, which is guessing at an undocumented method contract.

Explore the catalog | Get a free API key

10Conclusion

A 405 is a signal, not a mystery. The resource exists, the method does not 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, read the logs. In that order, the fix is usually one line.

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. That was good advice for developers. It is now a requirement for anything automated.

Try ApyHub

11FAQ

What exactly causes a 405 Method Not Allowed error?

The server recognises your HTTP method but the resource you called does not permit it. For example, sending DELETE to an endpoint built only for GET and POST. The response must include an Allow header listing the methods that are accepted.

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 accepted method.

What does an empty Allow header mean?

That the resource currently allows no methods at all. RFC 9110 notes this can occur when a resource has been temporarily disabled by configuration. It is a different problem from using the wrong verb.

What is the difference between a 403 and a 405 error?

A 403 means you are not permitted to perform an action you are otherwise allowed to request, which is about authorisation. A 405 means the method itself is not valid for that resource, regardless of who you are.

What is the difference between a 404 and a 405?

A 404 means the route does not exist. A 405 means the route exists but does not accept your method. If you expected a 405 and got a 404, your framework may be treating an unhandled method as a missing route, which Express does 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. An API client can send POST, PUT or DELETE. A GET-only route loads in the browser and returns a 405 from the client. Check the method first.

What does MethodNotAllowedHttpException mean?

It is the exception Symfony and Laravel throw when a request path matches a route but the HTTP method does not. The route exists for a different verb, so check your route definitions or add a handler.

Can a Web Application Firewall cause a 405?

Yes. WAFs including Cloudflare may block TRACE, PATCH or OPTIONS to reduce attack surface, producing a 405 even where the origin would have allowed it. Whitelist the specific method rather than disabling the rule.

Why do AI agents get 405 errors so often?

Because an agent calling an API it discovered at runtime has to infer the verb, and if the method contract is not machine-readable it guesses. Whether it recovers depends on the Allow header: with one it corrects the call itself, without one it gives up or retries the same wrong method.

Should my API return an Allow header on 405?

Yes, and the spec requires it. It costs nothing and it is what lets an automated caller correct itself. Express does not do this by default, falling through to a 404 instead, which tells an agent the endpoint does not exist rather than that the verb was wrong.

Can I get a 405 on a GET request?

You should not, under normal circumstances. RFC 9110 requires all general-purpose servers to support GET and HEAD. A 405 on a plain GET points at a config rule, a WAF, a permissions problem, or a resource that has been disabled.

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. Consuming APIs whose specifications already declare their accepted methods removes the most common cause.

12Sources

13Further Reading

14About ApyHub

ApyHub is a curated API catalog for developers, teams, and AI agents, covering file conversion, data validation, OCR and extraction, domain intelligence and more across 20 categories.

One subscription covers the whole catalog, with headroom pooled across every API rather than locked to individual services. Every service ships with a machine-readable specification including its accepted methods, and carries certification covering data handling, retention and standards alignment including GDPR, SOC 2 and ISO 27001. Every endpoint is MCP-ready by default.

ApyHub is EU-based and runs entirely on EU infrastructure, which keeps data residency simple for teams with GDPR obligations. The catalog holds 450+ services and 1,500+ endpoints, with new APIs and providers onboarded continuously. The free tier requires no credit card.