405 Method Not Allowed Error: Causes and How to Fix It
A 405 Method Not Allowed error means the server understood exactly what you were asking for, and refused to let you ask for it that way. It's not a missing page (that's a 404) and it's not a permissions problem in the usual sense (that's a 403) - it's a server, plugin, or firewall rule saying "this URL doesn't accept that HTTP method." Here's how to find which layer is doing the blocking and fix it.
What a 405 actually means
Every HTTP request has a method attached to it - GET, POST, PUT, DELETE, HEAD, OPTIONS. A 405 shows up when a client sends a method the target URL isn't configured to accept. Browsers usually only send GET (loading a page) and POST (submitting a form), so when you see this error as a regular visitor, something unusual is happening: a form is posting to the wrong place, a cached page is intercepting a POST, or a security rule is stripping methods it doesn't like.
If you're a developer hitting a REST API or webhook, it's more straightforward - you sent a PUT or DELETE to an endpoint that's only wired up for GET and POST, or a proxy in front of it is filtering methods before your request even reaches the app.
Step 1: Confirm which method and which URL
Before touching any config, get the exact request. Open your browser's DevTools Network tab, reproduce the error, and click the failed request. Note:
- The exact URL that returned 405
- The request method (GET, POST, PUT, DELETE, OPTIONS)
- The response headers - look for an
Allowheader, which tells you which methods the server will accept - Which server is answering - check the
Serverheader (nginx, Apache/LiteSpeed, cloudflare) so you know where to start looking
You can also reproduce it from the command line, which strips out browser extensions and cache as suspects:
curl -I -X POST https://example.com/wp-json/wp/v2/posts
If curl gives you the same 405 that the browser does, the problem is server-side, not a stale asset or extension.
Common cause 1: A form posting to the wrong URL
This is the single most common cause on WordPress and WooCommerce sites. A contact form, checkout page, or login form is set to POST to a URL that either doesn't exist as a script endpoint or has been rewritten by a redirect. Classic triggers:
- A page was moved and a 301 redirect now points the form's
actionURL somewhere that only accepts GET - The site was migrated from HTTP to HTTPS (or old domain to new) and the form still hardcodes the old URL, which redirects and drops the POST body along the way
- A caching plugin or CDN served a cached version of a page that should have processed the POST dynamically
Fix: Check the form's action attribute against the live URL. If a redirect is involved, most redirects (301/302) will actually re-send a GET on the second hop unless the server does a 307/308 - so any form pointed at a redirecting URL is a landmine. Update the form to point directly at the final URL instead of relying on the redirect.
Common cause 2: Apache/.htaccess LIMIT directives
If you or a security plugin added a <Limit> or <LimitExcept> block to .htaccess, it can silently restrict a directory to only GET and HEAD. This shows up a lot after hardening guides that lock down uploads folders.
<LimitExcept GET HEAD>
Order deny,allow
Deny from all
</LimitExcept>
That block returns 405/403 for anything else hitting that directory, including legitimate POST requests from a plugin's AJAX handler if it happens to live in the restricted path. Comment the block out temporarily to confirm, then rewrite it to allow the specific method your app actually needs.
Common cause 3: Nginx explicitly returning 405
On a VPS running Nginx (or Nginx in front of Apache/PHP-FPM), someone may have added a method allowlist like this:
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
This is common in hardened server blocks meant to block PUT/DELETE probing, but it also blocks legitimate PUT/DELETE calls your own REST API or app needs - which matters a lot if you're running a Node.js app or a WordPress site using the block editor's autosave, since both rely on methods beyond plain GET/POST. Search your site's config for return 405 and request_method:
grep -rn "request_method\|return 405" /etc/nginx/
If you find a match and the blocked method is one your app legitimately needs, add it to the allowlist and reload Nginx with nginx -t && systemctl reload nginx.
Common cause 4: Cloudflare or a WAF blocking the method
If your site sits behind Cloudflare or another WAF/CDN, check two things in the dashboard:
- Firewall/WAF rules - a custom rule matching on
http.request.methodmay be blocking or challenging PUT/DELETE/PATCH requests meant for a REST API - Page Rules or Cache Rules - if a rule is caching a URL that should be dynamic (e.g. an API endpoint or checkout path), Cloudflare can serve a cached response for a method it never should have cached, producing odd 405s intermittently
Fix: In Cloudflare, go to Security > WAF > Custom rules and check for anything referencing HTTP methods. For caching, make sure API and form-submission paths are excluded via a Cache Rule set to "Bypass cache."
WordPress REST API and Gutenberg-specific 405s
If the 405 shows up specifically when saving a post, uploading media in the block editor, or hitting /wp-json/ URLs, the REST API route itself may only be registered for certain methods. This happens with custom endpoints registered like this:
register_rest_route('myplugin/v1', '/items', array(
'methods' => 'GET',
'callback' => 'my_callback',
));
If a plugin's JavaScript then tries to POST or PUT to that same route, WordPress correctly returns 405 because the route was never registered for that method. This is a plugin/theme code bug, not a server misconfiguration - check for a plugin update, or if it's custom code, add the missing method to the methods array (WordPress accepts an array like array('GET', 'POST')).
Also confirm your permalink structure isn't set to "Plain" (Settings > Permalinks) - the REST API relies on pretty permalinks to route correctly, and a plain structure can produce inconsistent method errors on some setups.
Quick diagnostic table
| Symptom | Likely layer | Where to look |
|---|---|---|
| Only happens on one contact/checkout form | Application | Form's action URL and any redirects on it |
| Whole folder returns 405 for anything but browsing | Apache | .htaccess Limit/LimitExcept blocks |
| REST/API calls with PUT, DELETE, PATCH fail | Nginx or WAF | Nginx request_method checks, Cloudflare WAF rules |
| Only in the block editor / Gutenberg / Elementor | WordPress plugin | Plugin's register_rest_route method list |
| Intermittent, works then fails | CDN cache | Cloudflare Cache Rules on that path |
Prevention checklist
- Never point a form's
actionat a URL that redirects - use the final destination directly - When hardening
.htaccessor Nginx configs, list every method your app actually uses (including OPTIONS for CORS preflight) before locking things down - Exclude API and form-submission paths from CDN/page caching explicitly, don't rely on defaults
- Test plugin and theme updates on a staging site before pushing to production, especially anything touching custom REST routes
- Keep permalinks on a pretty structure (not "Plain") so WordPress's REST API routing behaves predictably
Frequently asked questions
Is a 405 error the same as a 403 Forbidden error?
No. A 403 means you're not allowed to access the resource at all, regardless of method. A 405 means the resource exists and you could access it - just not with the HTTP method you used. Check the response's Allow header to see which methods are actually accepted.
Why do I only get a 405 error sometimes, not every time?
Intermittent 405s usually point to caching - a CDN or page cache is serving a stored response for a URL that should be handled dynamically. Check Cloudflare Cache Rules or any server-side page cache and exclude the affected path from caching.
Can a security plugin cause a 405 error on my WordPress site?
Yes. Security plugins that add .htaccess method restrictions or block certain request types as a hardening measure can accidentally block legitimate POST or PUT requests from other plugins. Temporarily disable the security plugin to confirm before adjusting its rules.
I fixed the .htaccess rule but I'm still getting 405 - why?
If your site is behind Cloudflare or another CDN, the old response may still be cached at the edge. Purge the cache for that specific URL and retest with curl -I to bypass the browser's own cache.
Does a 405 error affect SEO?
Not directly, since 405s are almost always tied to form submissions or API calls rather than page loads that search engines crawl. But if a redirect is misconfigured and search bots hit the same broken URL with the wrong method during a crawl, it's worth fixing quickly to avoid confusing crawlers or breaking site functionality visitors rely on.