TL;DR: The Quick Band-Aid
If you're in a rush, you can give your server more breathing room by bumping up the timeout limit. Drop this snippet into your theme's functions.php or a functionality plugin to extend the window from the default 5 seconds to 30:
add_filter('http_request_args', function($args, $url) {
$args['timeout'] = 30;
return $args;
}, 10, 2);
Keep in mind this usually masks a deeper issue. It stops the error, but it won't fix a misconfigured firewall or a sluggish DNS resolver.
Why WordPress Throws cURL Error 28
WordPress needs to talk to itself to stay healthy. It uses "Loopback Requests" to trigger background tasks like wp-cron.php or to verify REST API endpoints. When you see cURL error 28, it means WordPress sent a request to its own URL, waited for a response, but eventually gave up after the 10-second default limit.
This isn't just a cosmetic bug. A failing loopback prevents scheduled posts from publishing, breaks the Block Editor's autosave feature, and can even crash some WooCommerce shipping integrations.
Common Root Causes
- **Firewall Overkill:** Tools like UFW or IPTables might be blocking the server from connecting to its own public IP address.
- **Security Plugin Interference:** Heavy hitters like Wordfence or NinjaFirewall might mistake these internal pings for a bot attack.
- **DNS Loops:** The server might fail to resolve its own domain name, causing the request to hang indefinitely.
- **Server Exhaustion:** If your CPU is pinned at 100% or you've run out of RAM, PHP-FPM won't have the cycles to process the request in time.
- **Legacy Libraries:** Running an ancient version of cURL (anything below 7.50) or OpenSSL can cause massive delays during the SSL handshake.
Step-by-Step Fixes
1. Open Up Your Firewall
In VPS environments, the firewall is the most likely culprit. You need to ensure the server can communicate with itself on ports 80 and 443. If you're running UFW on Ubuntu, first identify your public IP, then whitelist it:
# Find your server's public IP
curl -4 icanhazip.com
# Whitelist your own IP (replace 1.2.3.4 with your actual IP)
sudo ufw allow from 1.2.3.4
Managed hosting users should skip this and ask support to "enable loopback connections for the local IP."
2. Fix DNS 'Self-Awareness'
Sometimes a server doesn't know where it lives. Test this by SSHing into your box and trying to reach your own site:
ping yourdomain.com
If the ping hangs or returns a 'Destination Host Unreachable' error, you can force a local map. Edit your hosts file and point your domain directly to the local loopback address:
sudo nano /etc/hosts
# Add this at the bottom
127.0.0.1 yourdomain.com
3. Audit Your Plugins
Security and caching plugins often sit in the middle of these requests. To find a conflict:
- Temporarily disable security suites like Wordfence or All In One WP Security.
- Clear your Object Cache (Redis/Memcached) if you use one. A stale cache entry can sometimes trap a request in a loop.
- Refresh Site Health. If the error vanishes, you've found the conflict and may need to tweak that plugin's internal firewall settings.
4. Force Library Updates
Ubuntu 18.04 and CentOS 7 are notorious for having outdated cURL versions that struggle with modern TLS 1.3 handshakes. Run these to ensure your stack is current:
# For Ubuntu/Debian
sudo apt update && sudo apt install --only-upgrade curl openssl php-curl
# For CentOS/RHEL
sudo yum update curl openssl
Don't forget to restart your services: sudo systemctl restart nginx php8.1-fpm (adjust for your specific version).
5. Investigate ModSecurity
ModSecurity is a powerful Web Application Firewall, but it's often too aggressive. It may block the WordPress/X.X User-Agent by default. Scour your logs at /var/log/nginx/error.log. If you see 403 Forbidden or 406 Not Acceptable errors alongside your Site Health attempts, you'll need to create a whitelist rule for your server's IP.
How to Verify the Fix
- Head to your WordPress Dashboard.
- Go to **Tools > Site Health**.
- Wait for the analysis to finish.
- Check the **Passed tests**. "The REST API is available" and "Your site can perform loopback requests" should now show green checkmarks.
Still stuck? Check wp-config.php for WP_PROXY_HOST settings. If your server is behind a proxy, WordPress needs to know about it to route cURL calls correctly.
Further Reading
- [Official Site Health Guide](https://wordpress.org/documentation/article/site-health-screen/)
- [PHP cURL Troubleshooting](https://www.php.net/manual/en/book.curl.php)
- [WordPress REST API Docs](https://developer.wordpress.org/rest-api/)

