How to disable XML-RPC in WordPress

Disabling XML-RPC closes a legacy remote access path in WordPress that still attracts brute-force and pingback abuse. Sites that no longer use Jetpack, the WordPress mobile app, or older remote-publishing clients usually have little reason to keep xmlrpc.php reachable from the internet.

The xmlrpc.php endpoint is shipped with WordPress core and handles XML-RPC method calls outside the normal dashboard flow. WordPress still exposes it by default, and the xmlrpc_enabled filter only disables authenticated methods inside WordPress itself rather than removing the public endpoint at the web-server layer.

The steps below use an Apache 2.4 access rule in the active virtual host so requests are denied before they reach WordPress. Keep XML-RPC available when a real dependency still needs it, and prefer a narrower allow-list or edge filtering when removing the endpoint outright would break production workflows.

Steps to disable XML-RPC in WordPress:

  1. Confirm that no active workflow still depends on XML-RPC.

    Common dependencies include Jetpack connections, the WordPress mobile app, older remote-publishing tools, and custom integrations that still call xmlrpc.php directly.

  2. Locate the active Apache virtual host file for the site.
    $ sudo apache2ctl -S
    VirtualHost configuration:
    *:80                   www.example.com (/etc/apache2/sites-enabled/example.com.conf:1)
    *:443                  www.example.com (/etc/apache2/sites-enabled/example.com-ssl.conf:1)
    ##### snipped #####

    On Red Hat-family systems, use sudo apachectl -S instead of apache2ctl -S.

  3. Open the site's Apache virtual host file in a text editor.
    $ sudo vi /etc/apache2/sites-enabled/example.com.conf

    Edit the file that actually serves the hostname shown by apache2ctl -S instead of guessing between sites-available and sites-enabled.

  4. Add a file-level deny rule for xmlrpc.php inside the relevant <VirtualHost> block.
    <Files "xmlrpc.php">
        Require all denied
    </Files>

    Place the rule near the rest of the site-specific access controls so it is easy to audit later.

    If the site is behind Nginx, a CDN, or a managed host that does not expose Apache virtual hosts, block xmlrpc.php at that layer instead of copying this snippet blindly.

    On shared hosting with working .htaccess overrides, the same Files block can usually be placed above the generated WordPress rewrite section. If direct requests still reach WordPress, move the rule into the virtual host or another server-level include.

  5. Test the updated Apache configuration before reloading it.
    $ sudo apache2ctl configtest
    Syntax OK

    On Red Hat-family systems, the equivalent command is usually sudo apachectl configtest or sudo httpd -t.

  6. Reload Apache so the block takes effect without a full restart.
    $ sudo systemctl reload apache2

    Use sudo systemctl reload httpd on Red Hat-family systems, or sudo apache2ctl graceful when systemd is not the normal service interface.

  7. Request the endpoint directly and confirm that Apache now returns 403 Forbidden before WordPress handles the request.
    $ curl -s -o /dev/null -D - https://www.example.com/xmlrpc.php | sed -n '1,5p'
    HTTP/1.1 403 Forbidden
    Server: Apache/2.4.66 (Debian)
    Content-Length: 317
    Content-Type: text/html; charset=iso-8859-1

    A previous 405 Method Not Allowed response with Allow: POST means the endpoint was still reachable through WordPress.

  8. Send a short XML-RPC POST and confirm that it is blocked with the same 403 result.
    $ curl -s -X POST \
      -H 'Content-Type: text/xml' \
      --data '<methodCall><methodName>system.listMethods</methodName><params></params></methodCall>' \
      -o /dev/null -D - https://www.example.com/xmlrpc.php | sed -n '1,5p'
    HTTP/1.1 403 Forbidden
    Server: Apache/2.4.66 (Debian)
    Content-Length: 317
    Content-Type: text/html; charset=iso-8859-1

    If a legitimate integration fails after this change, remove the block, identify the caller, and replace blanket exposure with a narrower allow-list, proxy rule, or a supported REST API workflow when the integration supports it.