Security PHP Beginner

Block XML-RPC Completely

Last updated: May 6, 2026

XML-RPC is a remote procedure call protocol that WordPress has supported since its early days, originally designed to let external tools like the WordPress mobile app, MarsEdit, and blogging clients publish and manage content remotely. The REST API has since replaced it for virtually all modern use cases, but WordPress still ships with xmlrpc.php active by default. For the vast majority of sites, this file serves no legitimate purpose, and for attackers, it’s a well-documented attack surface.

Why XML-RPC Is a Security Risk

The most common attack against xmlrpc.php is credential brute-forcing. The system.multicall method allows a single HTTP request to attempt hundreds of username and password combinations simultaneously, making it far more efficient than attacking the login page directly where rate limiting and lockout plugins typically apply. WordPress does not rate-limit XML-RPC by default.

A secondary risk is pingback abuse. The pingback.ping method can be exploited to make your server send HTTP requests to arbitrary third-party URLs, effectively using your site as a tool in distributed denial-of-service attacks against other hosts.

The Code

This snippet takes a thorough approach, addressing XML-RPC at four separate levels rather than relying on a single filter.

The xmlrpc_enabled filter set to __return_false disables the XML-RPC API at the WordPress application level. Any request that reaches WordPress through the normal bootstrap process will be refused.

The wp_headers filter removes the X-Pingback HTTP response header that WordPress adds to all page responses. This header advertises the location of your XML-RPC endpoint to any client that reads response headers, including crawlers and scanners looking for targets.

remove_action( 'wp_head', 'rsd_link' ) removes the Really Simple Discovery link tag from your page <head>. This tag also advertises the XML-RPC endpoint and is unnecessary once the endpoint is disabled.

The final block uses the init hook at priority 0, the earliest possible point in WordPress’s bootstrap, to detect direct requests to xmlrpc.php by checking the script filename. If matched, it returns a 403 and exits before WordPress processes the request at all. This prevents any code within xmlrpc.php itself from executing.

Is This Safe to Apply?

On the vast majority of WordPress sites, yes, completely safe. The cases where you’d want to keep XML-RPC active are narrow: using the WordPress iOS or Android app to post content (which now uses the REST API anyway), using certain legacy desktop blogging clients, or running a Jetpack integration in an unusual configuration. If none of those apply, disabling XML-RPC removes an attack surface with zero functional cost.

Server-Level Blocking

For maximum protection, you can complement this snippet with a server-level rule in your .htaccess (Apache) or Nginx config that blocks requests to xmlrpc.php before they reach PHP at all. The application-level approach in this snippet is sufficient for most cases, but a server-level rule eliminates the request overhead entirely.

functions.php
// Disable the XML-RPC API
add_filter( 'xmlrpc_enabled', '__return_false' );

// Remove the X-Pingback header from all responses
add_filter( 'wp_headers', function( $headers ) {
    unset( $headers['X-Pingback'] );
    return $headers;
} );

// Remove the link tag that advertises the RSD endpoint
remove_action( 'wp_head', 'rsd_link' );

// Block direct requests to xmlrpc.php at the application level
add_action( 'init', function() {
    if (
        isset( $_SERVER['SCRIPT_FILENAME'] ) &&
        str_ends_with( $_SERVER['SCRIPT_FILENAME'], 'xmlrpc.php' )
    ) {
        http_response_code( 403 );
        header( 'Content-Type: text/plain' );
        exit( 'Forbidden.' );
    }
}, 0 );

Built by Nahnu Plugins

Need something more powerful than a snippet?

Our commercial plugins go further, built for serious WordPress sites with full support, updates, and documentation included.

Browse All Plugins →

This website uses cookies to enhance your browsing experience and ensure the site functions properly. By continuing to use this site, you acknowledge and accept our use of cookies.

Accept All Accept Required Only