xmlrpc.php 403 Forbidden

The other day I encountered this error on one of my domains while working on a small project. The endpoint used to work, as I had used it for testing as recently as a month ago so when it stopped working I became annoyed.

There are a few reasons for this to happen and you have probably already tried them, though I will still enumerate them here:

  1. One of your plugins, in particular security plugins, is blocking access to the endpoint (you can check by looking at your .htaccess file or disabling the security plugins)
  2. The file permissions for xmlrpc.php are incorrect (they should be 644)
  3. The .htaccess file has become corrupt (you can check by renaming the current file to something like .htaccess.org then go to dashboard of the WP instance, click on settings, writing, permalinks and click on save. This will re-create the .htaccess file. If it works, then your .htaccess file was corrupt indeed, otherwise, just delete that newly created file and revert to the original)

Obviously, none of these were the issue for me. The problem turned out to be my hosting provider was filtering on xlmrpc.php and returning a 403.

You can confirm this by doing the following:

curl -v https://your-domain/xmlrpc.php

If access to the xmlrpc.php file is being blocked by your hosting provider the response will look like this:

*   Trying 198.54...
* TCP_NODELAY set
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
*  SSL certificate verify ok.
> GET /xmlrpc.php HTTP/1.1
> Host: <your domain>
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 403 Forbidden
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
<
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
* TLSv1.2 (IN), TLS alert, Client hello (1):
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, Client hello (1):

The giveaway is in the response headers.

< HTTP/1.0 403 Forbidden 
< Cache-Control: no-cache 
< Connection: close 
< Content-Type: text/html

If the issue is on your WP instance configuration, the response headers will include Apache as the server (like this):

< HTTP/2 405
< content-type: text/plain;charset=UTF-8
< date: Wed, 04 Apr 2018 07:37:10 GMT
< server: Apache
< x-powered-by: PHP/7.0.26
< allow: POST

I contacted my hosting provider and indeed they were filtering on xmlrpc.php. I am not recommending you use or not use xmlrpc, I am simply demonstrating the steps to troubleshoot the error.