
If your WordPress site has ever felt sluggish for no obvious reason, or your hosting dashboard suddenly flags a spike in CPU usage at 3 a.m., there's a good chance an automated bot is hammering a single file: xmlrpc.php. It sits in the root of nearly every WordPress install, and for most modern sites it does almost nothing useful while quietly serving as one of the most popular doors for brute-force attacks.
Here's a number that surprises people: a single request to xmlrpc.php using the system.multicall method can attempt hundreds of password guesses in one HTTP call. That means an attacker doesn't need to send 500 separate login attempts that your security plugin would notice and throttle. They can bundle them. I've watched server logs where one IP made 40 requests in a minute and effectively tried over 10,000 credential pairs. That's the kind of efficiency that turns a weak admin password into a breach by lunchtime.
In this guide I'll walk through exactly what xmlrpc.php does, how to tell if you actually need it, and four concrete methods to disable xmlrpc.php in WordPress — from a one-line plugin to server-level blocks. We'll compare the approaches, run through a real before/after scenario, and cover the edge cases (Jetpack, mobile apps, pingbacks) so you don't break anything you rely on.
Key Takeaways
xmlrpc.phpis a legacy remote-access API most sites don't need, and it's a favorite target for brute-force and DDoS amplification attacks.- The
system.multicallmethod lets attackers batch hundreds of login guesses into a single request, bypassing simple rate limits.- You can disable it via a filter in
functions.php, a plugin, an.htaccessrule, or an Nginx directive — server-level blocks are the most efficient.- Before disabling, check whether you use the Jetpack app, the official WordPress mobile app, or pingbacks, since those depend on XML-RPC.
- Blocking the file at the web server level stops the request before WordPress even loads, saving CPU during an attack.
- Pair the block with IP-level filtering and a hardened login page for defense in depth.
What Is xmlrpc.php and Why Does It Exist?
xmlrpc.php is a remote procedure call interface. It lets external applications talk to your WordPress site using XML over HTTP. It was added back when blogging tools like Windows Live Writer and early mobile clients needed a way to publish posts remotely, long before the modern REST API existed.
The protocol supports dozens of methods. Some are harmless (wp.getPosts), and a few are genuinely dangerous in the wrong hands:
wp.getUsersBlogs— accepts a username and password, making it perfect for credential stuffing.system.multicall— bundles many method calls into one request, which attackers abuse to test thousands of passwords per call.pingback.ping— can be weaponized to bounce traffic off your site at a third-party target (a DDoS amplification trick).
Since WordPress 4.4, the REST API handles most of what xmlrpc.php used to do, and it does so with better authentication. For the vast majority of sites built in the last several years, XML-RPC is dead weight with a security cost attached.
The honest exceptions
I won't pretend it's useless for everyone. You still need XML-RPC enabled if you:
- Use the Jetpack plugin (it relies on XML-RPC to communicate with WordPress.com).
- Publish from the official WordPress mobile app on older configurations.
- Run a desktop blogging client like Open Live Writer.
- Depend on legitimate pingbacks and trackbacks (most people don't anymore).
If none of those apply, you can disable it with zero loss of functionality. If some do, you can still block the specific dangerous methods rather than the whole file. We'll cover both.
How to Tell If You're Already Under Attack
Before you touch anything, it helps to confirm the file is being targeted. The signs are usually obvious once you know where to look.
- Check your access logs. On most hosts you can find these in cPanel under "Raw Access" or via SSH at
/var/log/nginx/access.logor/var/log/apache2/access.log. Search for the file:grep xmlrpc.php access.log | wc -l. A healthy site might show a handful of hits a day. An attacked site shows hundreds or thousands. - Look at the request method. Legitimate XML-RPC traffic uses
POST. A flood ofPOST /xmlrpc.phpfrom a small set of IPs is a brute-force signature. - Watch CPU and memory. Hosting dashboards often show resource spikes that line up with the attack window. PHP-FPM processes pile up because every request boots WordPress.
- Read security plugin reports. If you run a firewall plugin, it will frequently log "blocked XML-RPC login attempts" without you ever noticing the source.
If you want a deeper, repeatable process for evaluating what's running on your site and where the weak points are, our walkthrough on how to audit WordPress plugins for vulnerabilities before installing pairs nicely with this. A lot of XML-RPC exposure comes bundled with plugins you forgot you installed.
Worked Example: A 600-Guess Attack in One Request
Let me make the threat concrete. Say you have a site, example.com, with an admin account named admin and a password you reused from another service that was breached two years ago.
An attacker sends a single POST to https://example.com/xmlrpc.php with a system.multicall payload containing 600 wp.getUsersBlogs calls, each trying a different password from a leaked list. WordPress processes the batch and responds with 600 results in one body. For each, a faultCode of 403 means "wrong," and the absence of a fault means "correct."
Before the block: the attacker effectively tests 600 passwords per request. At 30 requests per minute, that's 18,000 attempts a minute — and your login throttling plugin, which counts failed logins on wp-login.php, never fires because the traffic never touches that page.
After disabling xmlrpc.php at the server level: the request returns a 403 Forbidden before WordPress loads. The attacker gets zero password results, your PHP workers stay free, and the bot usually moves on within minutes once it stops getting useful responses.
That single change collapses the attack surface from 18,000 guesses a minute to zero through this vector. It's one of the highest-leverage five-minute jobs in WordPress hardening.
Method Comparison: Four Ways to Disable xmlrpc.php
There's no single "right" method — it depends on your hosting, comfort with config files, and whether you need partial functionality. Here's how the main approaches stack up.
| Method | Difficulty | Blocks before WordPress loads? | Lets you keep partial access? | Best for |
|---|---|---|---|---|
PHP filter in functions.php |
Easy | No | Yes (selective) | Developers comfortable editing themes |
| Security plugin toggle | Very easy | No | Sometimes | Non-technical site owners |
.htaccess rule (Apache) |
Medium | Yes | Yes (by IP) | Apache/LiteSpeed shared hosting |
Nginx location block |
Medium | Yes | Yes (by IP) | VPS and managed Nginx hosts |
The takeaway: if your goal is purely security and you don't need XML-RPC at all, a server-level block (.htaccess or Nginx) is best because it stops the request before PHP runs. If you need to keep Jetpack working, a PHP filter that disables only the dangerous methods is the smarter choice.
Method 1: Disable It With a Code Filter
This is the cleanest approach if you're comfortable with a child theme or a small custom plugin. Add the following to your theme's functions.php or, better, a site-specific plugin so it survives theme changes:
add_filter('xmlrpc_enabled', '__return_false');
That fully disables the XML-RPC functionality. WordPress will still serve the file, but every method call returns an error. Note this does not stop the file from being hit, so it won't save you CPU during a heavy flood. It's a logic-level block, not a network-level one.
Disable only the dangerous methods
If you use Jetpack but want to kill credential stuffing and pingback abuse, remove just those methods instead:
- Remove the pingback methods with a filter on
xmlrpc_methodsthat unsetspingback.pingandpingback.extensions.getPingbacks. - Keep the rest intact so Jetpack's authenticated calls still work.
This selective approach is exactly the kind of nuance that separates a careful setup from a copy-pasted snippet. If you write or borrow these filters from elsewhere, it's worth a quick sanity check — our guide on how to verify AI-generated code before you ship it is a good habit to apply to any snippet you drop into a live site.
Method 2: Block It at the Web Server (Recommended)
This is my preferred method for sites that don't need XML-RPC, because the request dies at the front door and never costs you a PHP process.
Apache or LiteSpeed (.htaccess)
Add this block to the top of your .htaccess file in the WordPress root:








