Geonode logo
Website and server errors

How to Fix a 405 Error (Method Not Allowed)

Find which methods the URL takes and what changed yours, with code for cURL, Python and Node.js.

Updated

TL;DR

A 405 error means the website or API knows the URL but refuses your HTTP method, such as a POST to a page that only reads data. Read the Allow header in the reply, then resend with a method it lists.

How servers and frameworks word a 405

The wording names the software that refused the method. Django sends no body, so Chrome draws its own page ending in HTTP ERROR 405.

WhereWhat you see
nginx (POST to a static file)405 Not Allowed
Apache httpd (PUT or DELETE on a file)Method Not Allowed The requested method PUT is not allowed for this URL.
Flask or WerkzeugMethod Not Allowed The method is not allowed for the requested URL.
FastAPI{"detail":"Method Not Allowed"}
Laravel (exception message)The GET method is not supported for route login. Supported methods: POST.
Django (server log, empty response body)Method Not Allowed (POST): /contact/
curl with -x set to a web serverCONNECT tunnel failed, response 405

Why this happens

The address exists, but it does not accept the kind of request you sent.

Each URL takes a set list of methods, the verb that opens every request, and the server turns down the rest. So a script or form that sends POST to a URL taking only GET is refused.

Diagnose your 405 first

The first two checks need no tools; the rest use DevTools or curl.

  • Note what triggered the 405; if it came right after a form submit or API call, that request used a method its address refuses.

  • Check whether the 405 page is a block notice with a request ID; if so, a firewall such as Alibaba Cloud WAF refused the request.

  • In DevTools Network, click the failed request; if the method under General is GET where you meant POST, something changed it on the way.

  • Check the browser console; 'It does not have HTTP ok status' means the browser's OPTIONS preflight, not your call, got the 405.

  • Run curl -v -x with your proxy on an https:// URL; a 405 to CONNECT came from the proxy address, not the site.

Solutions ranked by effectiveness

The first two fix your request; the third is for whoever runs the server.

  1. Most common fix

    Send a method the URL accepts

    Applies when the URL opens in a browser but your POST or DELETE gets 405. The code asks which methods the URL accepts without changing anything, so you can pick one for your client.

    URL="https://example.com/api/items"
    for METHOD in OPTIONS GET; do
      echo "$METHOD:"
      curl -sS -o /dev/null -D - -X "$METHOD" "$URL" | grep -iE '^(HTTP|allow)'
    done
  2. Check next

    Stop your POST from turning into GET

    Browsers and curl send GET unless told otherwise, and they switch POST to GET after a 301 or 302. Make the method explicit and target the final URL.

    1. Add method="post" to the form tag when the handler expects POST.

    2. Set the method option in fetch() for anything other than GET.

    3. Send the request to the redirect's Location URL, with https:// and any trailing slash.

    4. When curl -L must resend the POST after a redirect, add --post301 or --post302.

  3. Site owners

    Let the method reach your app

    If you run the endpoint and the method should work, add it to the route and make sure no static file rule or firewall answers first.

    1. Register the method on the route; in a Django class-based view, add a post() method.

    2. In nginx, proxy_pass POST to your app; the static handler answers only GET and HEAD.

    3. Answer OPTIONS with a 2xx status and your CORS headers, as browser preflights require.

    4. Look up the block page's request ID in your WAF console and suppress false positives.

Stop the 405 from coming back

Server settings that make 405s rarer and easier for clients to fix.

  1. Return Allow with every 405 your app sends, as RFC 9110 requires, so clients can correct themselves.

  2. Redirect URLs that take form posts or API writes with 307 or 308, which keep the method.

  3. If a URL's methods may change, send 405s to GET with Cache-Control: no-store; caches may store them otherwise.

Manage proxies through a REST APIGeonode's API docs give a sample request for each GET, POST, PUT and DELETE call.
Try residential proxies

Related errors

Learn more

FAQ

It is the standard wording of status 405: the server recognizes your method, but the address you sent it to does not support it. Other methods on that address may still work.

Resend the request with a method from the Allow header or API reference, and make sure no form, fetch() call or redirect turned your POST into GET. On a firewall block page, give the request ID to the site owner.

It is a 4xx client-error code. A server lacking the method entirely sends 501 instead, and an unknown URL usually gets 404, though nginx and Apache answer PUT on a missing file with 405.

It is the default 405 text of Werkzeug, the library under Flask. A Flask route answers only GET until you list other methods in its methods argument.

Laravel throws it when the route exists only for other methods, and it names them after Supported methods. HTML forms cannot send PUT, PATCH or DELETE, so Laravel reads a hidden _method field instead.

It usually means the proxy address you set belongs to a web server, which refuses the CONNECT request curl sends to open an HTTPS tunnel. Copy the host and port again from your provider's dashboard.

Residential IPs in Postman and cURL

Add Geonode's HTTP/HTTPS proxy to either tool and send your API calls through it.