Disable XML-RPC in WordPress: Stop Brute-Force Attacks
If your server load spikes overnight and you find thousands of POST requests to /xmlrpc.php in the access log, you're not imagining it. XML-RPC is one of the oldest, quietest attack surfaces in WordPress, and most sites don't need it turned on at all. Here's how to confirm it's the problem, shut it down properly, and keep it from creeping back after an update.
What XML-RPC Actually Does
xmlrpc.php ships with every WordPress install. It's a remote-procedure-call interface that lets outside apps talk to your site without using the regular admin login form - originally built for desktop blogging clients, and later reused by the WordPress mobile app, Jetpack, and some pingback/trackback features.
The problem is that one endpoint, system.multicall, lets a single HTTP request bundle hundreds of login attempts together. That turns xmlrpc.php into a brute-force amplifier that's far more efficient than hammering wp-login.php one guess at a time - and most login-limit plugins were never built to watch this endpoint at all.
Symptom: How to Tell You're Being Hit
Before you disable anything, confirm it's actually happening. SSH into your server (or use cPanel's Terminal) and check the Apache/Nginx access log for your domain:
grep -c "xmlrpc.php" /home/username/access-logs/yourdomain.com
grep "xmlrpc.php" /home/username/access-logs/yourdomain.com | tail -n 30
A handful of hits a day is normal if you use Jetpack. Thousands of POST requests from rotating IPs, especially at odd hours, is a brute-force run. You'll usually also notice:
- CPU or "resource limit" alerts in cPanel with no real traffic to explain them
- Slow admin dashboard even though your site's front end loads fine
- A flood of failed login entries in Wordfence, Sucuri, or your security plugin's log, all referencing xmlrpc.php rather than wp-login.php
- Outbound traffic spikes if your site is also being used as a pingback relay to DDoS someone else
Why This Happens
It's almost never personal - bots scan huge ranges of IPs for any WordPress install and hit xmlrpc.php by default because it's predictable, unauthenticated by design, and rarely monitored. If your site has ever appeared in a leaked credential list or shares a weak password across services, this is the door they'll try first, not wp-login.php.
Fix 1: Block It in .htaccess (Apache/LiteSpeed)
This is the fastest fix if you don't use Jetpack or the WordPress mobile app. Open File Manager in cPanel, edit .htaccess in your site's root, and add this block above the WordPress rules:
# Block XML-RPC
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
Save it, then reload yourdomain.com/xmlrpc.php in a browser - you should get a 403 instead of the "XML-RPC server accepts POST requests only" message. That message itself is a giveaway the endpoint is still live.
Fix 2: Disable It Without Touching .htaccess (mu-plugin)
If your site sits behind a CDN or reverse proxy that doesn't always respect .htaccess, filter it at the WordPress level instead. Create a file at wp-content/mu-plugins/disable-xmlrpc.php (create the mu-plugins folder if it doesn't exist) with:
<?php
add_filter('xmlrpc_enabled', '__return_false');
add_filter('wp_headers', function ($headers) {
unset($headers['X-Pingback']);
return $headers;
});
remove_action('wp_head', 'rsd_link');
Files in mu-plugins load automatically - no activation needed, and it survives theme changes. It won't return a 403 like the .htaccess method, but it stops requests from doing anything, which is what actually matters.
Fix 3: Block at the Firewall Level
If you're managing your own VPS, blocking earlier saves CPU cycles that never even reach PHP. In Nginx:
location = /xmlrpc.php {
deny all;
return 403;
}
Reload with nginx -t && systemctl reload nginx. If you're behind Cloudflare, this is even cleaner: go to Security > WAF > Custom rules, create a rule matching (http.request.uri.path eq "/xmlrpc.php"), and set the action to Block. That stops the traffic before it ever touches your origin server, which matters if the attack is large enough to spike your CPU usage or LVE limits.
Fix 4: Use a Security Plugin (If You'd Rather Not Edit Files)
Wordfence, iThemes Security, and All In One WP Security all have a one-click "Disable XML-RPC" or "Disable Pingback" toggle under their firewall settings. This is the least error-prone route if you're not comfortable editing .htaccess, but it does add plugin overhead most of the other methods avoid.
Wait - Do You Actually Need It First?
Check before you block anything:
| You use... | XML-RPC needed? |
|---|---|
| WordPress mobile app for posting | Yes - keep it, or block only system.multicall |
| Jetpack (any module) | Yes |
| Third-party publishing tools (e.g. desktop blog clients) | Usually yes |
| None of the above | Safe to disable entirely |
If you need Jetpack but still want to stop the brute-force pattern, block just the system.multicall method with a security plugin instead of disabling XML-RPC outright - most plugins offer this as a separate toggle.
Prevention
- Re-check after every WordPress core update - some migrations or staging-to-live pushes silently drop custom .htaccess rules
- If you disabled it via .htaccess, keep a copy of the rule saved outside your site so you can re-add it fast after a restore
- Pair this with rate limiting on
wp-login.phptoo - closing one door doesn't help if the other is still wide open - Watch your access logs monthly, even after fixing it, so a new attack pattern doesn't sit unnoticed for weeks
None of these fixes take more than a few minutes, and once xmlrpc.php stops responding, you'll usually see CPU and LVE resource alerts settle down within the hour if that's what was driving them.
Frequently asked questions
Will disabling XML-RPC break my WordPress site?
No, not for most sites. XML-RPC is only required if you use the WordPress mobile app, Jetpack, or a third-party publishing tool that connects remotely. If you don't use any of those, disabling it has zero effect on your site's normal functioning.
How do I know if XML-RPC is even enabled on my site?
Visit yourdomain.com/xmlrpc.php in a browser. If you see 'XML-RPC server accepts POST requests only,' it's active and reachable. A 403 Forbidden or 404 means it's already blocked.
I use Jetpack - can I still stop the brute-force traffic?
Yes. Instead of disabling XML-RPC entirely, use a security plugin to block just the system.multicall method, which is the specific function attackers abuse for bulk login attempts. Jetpack itself doesn't rely on that method for normal operation.
Does blocking xmlrpc.php in .htaccess actually stop the CPU spikes?
Yes, because the request gets rejected by the web server before WordPress or PHP ever loads. Blocking it at the Cloudflare or Nginx level is even more efficient since the request never reaches your origin server at all.
Why doesn't my login-limit plugin catch these attempts already?
Most brute-force protection plugins were built to monitor wp-login.php form submissions. XML-RPC attacks go through a completely different endpoint and authentication path, so unless the plugin explicitly monitors xmlrpc.php, those attempts slip past unnoticed.