pingrobot

HTTP status codes / 405

405 Method Not Allowed — HTTP Status Code

· 3 min read

Short answer

405 Method Not Allowed means the server recognizes the HTTP method, but the resource at that URL does not accept it, for example a POST to a page that only supports GET. The server must list the methods it does accept in an Allow header. The URL is fine; the method is the problem.

What 405 means

RFC 9110 (Section 15.5.6) defines 405 Method Not Allowed as the method in the request line being known to the origin server but not supported by the target resource. The server must include an Allow header listing the methods the resource currently supports, for example Allow: GET, HEAD.

RFC 9110 also separates it from 501 Not Implemented: a method the server does not recognize at all should get 501, while a recognized method that this resource does not permit should get 405. The same section states that all general-purpose servers must support GET and HEAD.

When you see it

  • Static file servers. nginx returns 405 when you POST to a static file, because there is nothing to process the body.
  • Frameworks with method-aware routing. Django class-based views, Laravel, Spring and others return 405 when a route exists but has no handler for that method.
  • APIs. Sending DELETE to a read-only endpoint, or GET to an endpoint that only accepts POST, such as a webhook receiver or a form handler.
  • CDNs and WAFs configured to allow only certain methods.
  • WebDAV and file managers that disable PUT or DELETE by default.

Common causes

  1. A form or JavaScript call posting to the wrong URL, often a static HTML page after a site was moved to static hosting.
  2. A trailing slash redirect that changes the method. A POST to /api/items is redirected to /api/items/ with a 301 or 302, and many clients repeat it as a GET, which the endpoint rejects. Use 307 or 308 when the method must be preserved, or call the canonical URL directly.
  3. HEAD not supported by an app that only wired up GET.
  4. CORS preflight failures. Browsers send an OPTIONS request before some cross-origin calls; an API that does not handle OPTIONS can answer 405.
  5. Testing a POST endpoint in the browser address bar, which always sends GET.

How to fix it

Read the Allow header first. It tells you exactly what the endpoint accepts, and often points straight at the mismatch.

If a form must post to a URL that nginx serves as a static file, send the request to your app instead of the file:

location = /contact {
    proxy_pass http://127.0.0.1:3000;
}

If your API should answer 405 rather than fall through to 404, add a handler that lists allowed methods. In Express:

app.route("/api/items")
  .get(listItems)
  .post(createItem)
  .all((req, res) => {
    res.set("Allow", "GET, HEAD, POST");
    res.status(405).json({ error: `${req.method} not allowed` });
  });

Express answers HEAD for any GET route automatically, which is why HEAD appears in the list. For CORS, handle OPTIONS explicitly or use your framework's CORS middleware so preflight requests succeed.

How to check it

Send a method the resource does not accept and look at the Allow header:

curl -sS -i -X POST https://example.com/index.html | grep -iE "^HTTP|^allow"

Compare HEAD and GET to see whether only HEAD is broken. Note that curl -I sends HEAD:

curl -sS -o /dev/null -w "%{http_code}\n" -I https://example.com/
curl -sS -o /dev/null -w "%{http_code}\n" https://example.com/

What it means for uptime monitoring

PingRobot's checker uses GET, not HEAD, with the user agent PingRobot/1.0 (+https://pingrobot.io/bot). It follows redirects and counts the final response as up only if its status is 200 to 399, so a 405 is reported as down.

Because the check is a GET, the common "HEAD not supported" issue does not affect it. A 405 almost always means the monitor points at an endpoint that only accepts other methods, such as a POST-only API route or webhook URL. That is a monitor configuration problem: point it at a page or health endpoint that answers GET.

If a URL that served GET yesterday starts returning 405 for GET today, something changed in routing or WAF rules, and real users are likely affected too.

Start monitoring free — 10 monitors, no credit card.

Frequently asked questions

What is the difference between 405 and 501?

405 means the server knows the method but this particular resource does not allow it. 501 Not Implemented means the server does not support the method for any resource at all.

Why does a HEAD request return 405 when GET works?

RFC 9110 requires general-purpose servers to support HEAD, but some apps and frameworks only register GET handlers or explicitly reject HEAD. Fix the app, or check with GET instead.

Why does my API return 404 instead of 405 for the wrong method?

Many routers, including Express by default, only match on method plus path, so a path with no handler for that method falls through to the 404 handler. Add explicit 405 handling if you want clients to see the right code.