A 405 Method Not Allowed means the URL exists but does not accept the HTTP method you used, for example a POST sent to a route that only handles GET. The server must list the methods it does accept in an Allow header. Send one of those, or add a handler for your method on the server.
| Status | Meaning | Typical fix |
|---|---|---|
| 405 Method Not Allowed | The resource exists; this method is not accepted for it | Use a method from Allow, or add a handler |
| 404 Not Found | No resource at this URL | Fix the path |
| 501 Not Implemented | The server does not support the method at all | Use a standard method |
| 403 Forbidden | The method is fine, you lack permission | Get access or change accounts |
Updated
Tick the methods your route handles, pick the method a client sends, and the builder shows the exact response the server should return: a normal success, or a 405 carrying an Allow header with the methods in the order you ticked them.
Methods this route handles
Method the client sends
What the server should send back
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, POST
Content-Length: 0The method is not in the list, so the answer is 405 with an Allow header naming the 3 methods you ticked.
Without methods=, the route answers GET only (Flask adds HEAD and OPTIONS automatically).
from flask import Flask, request
app = Flask(__name__)
@app.route("/contact", methods=["GET", "POST"])
def contact():
if request.method == "POST":
return {"ok": True}
return "<form method=\"post\"><button>Send</button></form>"app.all after the real handlers catches every other method for the same path.
import express from "express";
const app = express();
app.get("/items", (req, res) => res.json([]));
app.post("/items", (req, res) => res.status(201).json({ ok: true }));
app.all("/items", (req, res) => {
res.set("Allow", "GET, HEAD, POST");
res.status(405).end();
});
app.listen(3000);app/api/items/route.ts. A request with a method you did not export cannot reach your code.
export async function GET() {
return Response.json([]);
}
export async function POST(request: Request) {
const body = await request.json();
return Response.json({ received: body }, { status: 201 });
}A form with no method attribute submits as GET.
<form action="/contact" method="post">
<label>Email <input type="email" name="email" required></label>
<button type="submit">Send</button>
</form>
The method is recognised by the origin server, but the target resource does not support it. Because the server knows which methods would work, the specification requires it to say so through Allow. A 405 without Allow is incomplete.
Framework routes registered for one method, API gateways that map each method separately, and static file servers that serve files but accept no writes are the usual sources. In each case the path matched and the method did not.
Next.js route handlers export one function per method. The supported names are GET, POST, PUT, PATCH, DELETE, HEAD and OPTIONS, and when you do not export OPTIONS, Next.js answers it for you with an Allow header built from the methods you did export.
It is a 4xx code, so the request is what the server objects to. Either the client should use another method, or the server owner should add support for the one being sent.
Yes. RFC 9110 says the server must generate an Allow header field listing the methods the resource currently supports. An empty list is allowed when the resource takes no methods at all.
Usually the form sends a method the route does not accept. A route in Flask, for instance, only answers GET until you pass methods=["GET", "POST"] to the route decorator.
Express treats an unmatched method and path the same way: no route responded, so the request falls through to the 404 handler. Add a catch for the path with app.all to send 405 yourself.
405 means this resource refuses a method the server understands. 501 means the server does not support the method for any resource.
Related: HTTP status codes reference, Next.js API routes, 401 vs 403, CORS explained, Nginx 502 and other nginx errors.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.