Table of Contents
The full message usually reads “cURL error 28: Failed to connect to example.com port 443 after 5002 ms: Timeout was reached”, and it appears in WordPress Site Health under loopback requests, in the REST API check, when WP-Cron fails to run, or when a plugin tries to reach an external API. The site itself loads fine in a browser, which confuses people: the failing request is being made by PHP on the server, not by the visitor, and something between PHP and the destination is dropping it. On cPanel servers with Imunify360 or CSF the cause is almost always the firewall treating the server’s own outbound or loopback traffic as hostile.
Short answer: Test from the account’s shell with curl -sS -m 10 -o /dev/null -w '%{http_code}\n' https://example.com/wp-json/; if it times out, check Imunify360 with imunify360-agent ip-list local list --purpose black | grep SERVER_IP and whitelist the server’s own address with imunify360-agent ip-list local add --purpose white SERVER_IP, or run imunify360-agent create-rbl-whitelist if the address was RBL-listed. For CSF, confirm 443 is in TCP_OUT and the address is not in csf.deny. Also confirm the domain resolves to the local server from the server itself.
Reproduce from the server
Log in as the cPanel user or use su -s /bin/bash - user and test the exact request WordPress makes:
curl -sS -m 10 -o /dev/null -w '%{http_code} %{remote_ip}\n' https://example.com/wp-json/
curl -sS -m 10 -o /dev/null -w '%{http_code} %{remote_ip}\n' https://api.wordpress.org/core/version-check/1.7/
dig +short example.com
The first line tests loopback, the second outbound to a public API, and the third shows what the server’s resolver thinks the domain’s address is. A timeout on loopback with a working outbound points at the firewall’s treatment of the server’s own IP; a timeout on both points at outbound rules; a wrong address from dig points at DNS or a stale /etc/hosts entry.
Imunify360 blocking the server’s own address
Imunify360 can add the server’s public IP to its blacklist after a burst of failed logins from a compromised site, and its WebShield or geo rules can reject connections it decides are suspicious even when they originate locally. Check and clear:
imunify360-agent ip-list local list --purpose black | grep 203.0.113.10
imunify360-agent ip-list local delete --purpose black 203.0.113.10
imunify360-agent ip-list local add --purpose white 203.0.113.10 --comment "server self"
imunify360-agent create-rbl-whitelist
The last command whitelists the server’s own addresses against the external reputation lists that Imunify360 consults, which matters when the IP has been listed on a public RBL and Imunify360 has started refusing it. In the WHM plugin the same lists are under Imunify360 » Firewall » White List and Black List. If the timeout persists, temporarily disable WebShield under Settings » General to confirm whether the proxy layer is responsible, then re-enable it and add the hostname to the WebShield exceptions if so. The broader whitelist workflow is in Whitelist IPs and countries in Imunify360 from the CLI.
CSF and LFD
CSF blocks in two ways. Outbound ports not listed in TCP_OUT are dropped, so a locked-down configuration that omits 443 breaks every external API call; check with grep '^TCP_OUT' /etc/csf/csf.conf. Separately, LFD can add the server’s own address to the temporary block list after repeated failures logged against it:
csf -g 203.0.113.10
csf -tr 203.0.113.10
csf -a 203.0.113.10 server-self
csf -ra
The first command greps every list for the address, the second removes a temporary block, and the third adds a permanent allow. On the cPanel CSF fork the commands are unchanged.
DNS, hosts file and resolver
If dig returns a different address from the one the site actually uses, for example because the domain is proxied through Cloudflare and the server is blocking Cloudflare ranges, the loopback request leaves the server, goes to the proxy, and never comes back. Either whitelist the proxy ranges in the firewall or add a line to /etc/hosts mapping the domain to the server’s own address so loopback stays local. Also confirm /etc/resolv.conf points at working resolvers; a dead resolver produces the same timeout with a slightly different cURL error code, and dig @127.0.0.1 example.com shows whether the local resolver responds.
Verify and prevent recurrence
Rerun the curl tests as the user and expect a 200 from loopback and outbound. In WordPress, open Tools » Site Health and confirm the loopback and REST API checks pass, then run wp cron event run --due-now from the site root and confirm no error. To stop the problem returning, whitelist the server’s own IPs permanently in Imunify360 and CSF, keep the proxy ranges current if a CDN is in front, and investigate why the address was blocked in the first place, since a compromised site generating login attempts against its own server is a common trigger.
The classic pitfall is whitelisting only IPv4 while the domain has an AAAA record and PHP prefers IPv6.
WordPress cURL error 28 at a glance

Official documentation: Imunify360 documentation, WordPress advanced administration handbook, cPanel & WHM documentation.
Related guides: Whitelist IPs and countries in Imunify360 from the CLI · Imunify360 in 2026: WAF by default, L7 rate limiting and Under Attack Mode tuning · Hardening a shared cPanel server with CageFS, ModSecurity (OWASP CRS) and Imunify/ClamAV.
Frequently asked questions
Does cURL error 28 in WordPress also appear on servers without Imunify360 or CSF?
Yes. A missing DNS resolver, an upstream firewall, or a hosting network that blocks hairpin connections to the server’s own public IP produces the same error; the /etc/hosts mapping fixes the last case.
How long does it take for an Imunify360 whitelist to take effect?
The ip-list local add command applies within seconds because the agent updates its ipset immediately; WebShield changes may take up to a minute to reload.
Can I undo the whitelist entries later?
Yes. Run imunify360-agent ip-list local delete --purpose white 203.0.113.10 and remove the line from /etc/csf/csf.allow followed by csf -ra, but expect the timeout to return if the underlying block trigger was not addressed.
Maintenance record
This guide changes servers, data or security settings, so we re-check it against current versions on a fixed schedule. Take a backup or snapshot before you start.
- Maintained by
- srvScripts editorial team
- Last full review
- Next review