xmlrpc.php is WordPress’s legacy remote-publishing API. Before the REST API existed, it let desktop editors, the WordPress mobile app and services like Jetpack talk to your site. Today it’s mostly a target: attackers use it for password brute-forcing and DDoS amplification.

Why it’s abused

  • system.multicall lets one HTTP request try hundreds of username/password combinations. Login rate limits on wp-login.php don’t see it.
  • Pingbacks can be abused to make your site send requests to a victim, joining a DDoS.
  • Bot floods against xmlrpc.php tie up PHP workers and can slow or crash a small server.

Check your access log to see how often it’s hit:

sudo grep -c "POST /xmlrpc.php" /var/log/nginx/access.log

Do you need it?

Probably not. You still need XML-RPC if you use:

  • Jetpack (some features still use it),
  • the WordPress mobile app with older configurations,
  • old desktop blogging tools or integrations that only speak XML-RPC.

Everything modern — the block editor, the mobile app with application passwords, headless front ends — uses the REST API instead.

Option 1: block it in Nginx (best)

Blocking at the web server stops requests before they reach PHP, saving resources:

location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

Or close the connection without any response:

location = /xmlrpc.php { return 444; }

Put it in the site’s server block, then:

sudo nginx -t && sudo systemctl reload nginx

Allow Jetpack only

If you use Jetpack, allow only Automattic’s IP ranges (check Jetpack’s documentation for the current list) and deny everyone else:

location = /xmlrpc.php {
    allow 192.0.64.0/18;     # example: verify against Jetpack's published ranges
    deny all;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

Option 2: Apache / .htaccess

<Files xmlrpc.php>
    Require all denied
</Files>

Add it to the virtual host (preferred) or the site’s .htaccess.

Option 3: a filter in WordPress

add_filter( 'xmlrpc_enabled', '__return_false' );

As a mu-plugin (wp-content/mu-plugins/disable-xmlrpc.php) it can’t be disabled by accident. Note: this filter disables authenticated XML-RPC methods, but requests still reach PHP (and some methods remain); blocking at the web server is more complete and cheaper. Plugins like “Disable XML-RPC” do the same thing.

Also remove the advertising header (optional)

WordPress announces the endpoint in an X-Pingback header and an RSD link. With XML-RPC blocked these are harmless, but you can remove them:

add_filter( 'wp_headers', function ( $headers ) {
    unset( $headers['X-Pingback'] );
    return $headers;
} );
remove_action( 'wp_head', 'rsd_link' );

Verify

curl -s -o /dev/null -w "%{http_code}\n" -X POST https://example.com/xmlrpc.php

403 (deny) or no response (444) means it’s blocked. Before, WordPress answered 200 with “XML-RPC server accepts POST requests only.” on GET.

Fail2Ban as an extra layer

If you must keep XML-RPC open, ban IPs that hammer it. A jail matching POST /xmlrpc.php in the access log — see Fail2Ban for WordPress.

On a WordPress VPS you can block abusive endpoints at the Nginx level, where it costs almost nothing.

  • WordPress
  • Security
  • XML-RPC