The error reads:
cURL error 28: Connection timed out after X milliseconds
. It means a PHP script on your WordPress site tried to make an HTTP request to another server, waited for a response, and gave up after the timeout period expired. The remote server either did not respond at all, responded too slowly, or the connection was blocked somewhere between your server and theirs.
This error is different from most WordPress errors because the problem may not be on your server. WordPress and its plugins make outgoing HTTP requests constantly – checking for updates, validating licenses, sending emails via SMTP APIs, processing payments, fetching social media feeds, loading remote fonts, and communicating with CDNs. When any of these external connections fail, the plugin reports a cURL error 28.
Understanding what cURL is and how WordPress uses it makes diagnosing the source straightforward.
What cURL does in WordPress#
cURL is a PHP extension that makes HTTP requests to external servers. WordPress wraps cURL in its own HTTP API (
wp_remote_get()
,
wp_remote_post()
,
wp_remote_request()
), which is what plugins and themes use to communicate with external services.
Every outgoing HTTP request from WordPress goes through this chain:
- WordPress (or a plugin) calls
wp_remote_get('https://api.example.com/data') - WordPress passes the request to PHP’s cURL extension
- cURL resolves the hostname to an IP address via DNS
- cURL establishes a TCP connection to the remote server
- If HTTPS, cURL performs the TLS handshake
- cURL sends the HTTP request
- cURL waits for the response
- The response is returned to WordPress
A timeout can occur at steps 3, 4, 5, or 7. The cURL error 28 message tells you how long it waited but not which step failed. The timeout value and the context tell you where to look.
Common places this error appears#
The error surfaces in different places depending on which plugin or WordPress function made the request:
- Updates page – WordPress checks wordpress.org for plugin, theme, and core updates
- Plugin activation – some plugins call home to validate license keys on activation
- WooCommerce checkout – payment gateways communicate with Stripe, PayPal, or other processors
- REST API calls – plugins that use external REST APIs (Google, OpenAI, Mailchimp)
- WordPress cron – scheduled tasks that make external requests (backup plugins uploading to S3, email plugins syncing with SMTP services)
- Site Health page – WordPress runs connectivity tests to wordpress.org and your own loopback URL
The location tells you which service is being contacted and narrows the diagnosis.
Cause 1: External service is down#
The simplest explanation. The remote server your plugin is trying to reach is offline, overloaded, or experiencing its own issues.
How to confirm
Try accessing the external service from your browser or a different server. If the service’s status page shows an outage, the problem is on their end.
For WordPress.org connectivity:
curl -I https://api.wordpress.org
For a plugin’s API:
curl -I https://api.pluginname.com
If the curl command also times out from the command line, the service is unreachable from your server.
How to fix
Wait. If the external service is down, the error resolves when they come back up. There is nothing to fix on your end.
If the service has been down for a while and the error is blocking critical functionality (WooCommerce checkout failing because the payment gateway is down), most payment gateways have fallback mechanisms or status pages with estimated recovery times. Check the service’s status page.
Cause 2: DNS resolution failure#
Before cURL can connect to a remote server, it needs to resolve the hostname to an IP address. If DNS resolution fails or is extremely slow, cURL times out before even establishing a connection.
How to confirm
Test DNS resolution from the server:
dig api.wordpress.org
or:
nslookup api.wordpress.org
If these commands hang or return errors, DNS is the problem.
How to fix
Check the server’s DNS configuration:
cat /etc/resolv.conf
If the nameservers listed are unresponsive, switch to a public DNS resolver:
nameserver 1.1.1.1
nameserver 8.8.8.8
On managed hosting, DNS resolution is handled by the infrastructure and should not require manual configuration. If DNS queries are failing on managed hosting, contact support.
On Hostney, DNS resolution is handled at the server level with reliable resolvers. If a specific domain cannot be resolved, it is almost always a problem with the destination domain’s DNS records, not with your server’s resolver.
Cause 3: Server firewall blocking outgoing connections#
Some hosting providers restrict outgoing connections from their servers. This is a security measure to prevent compromised sites from communicating with command-and-control servers. But it can also block legitimate outgoing requests from WordPress plugins.
How to confirm
Outgoing connections to specific ports fail, but the destination is reachable from other networks:
# Test HTTPS (port 443)
curl -v https://api.wordpress.org --connect-timeout 5
# Test HTTP (port 80)
curl -v http://api.wordpress.org --connect-timeout 5
If port 443 times out but port 80 works (or vice versa), a firewall rule is blocking the specific port.
How to fix
Contact your hosting provider and ask them to allow outgoing connections on ports 80 and 443. These are required for WordPress to function normally (update checks, API communication, license validation).
If you manage the server, check the firewall rules:
# iptables
iptables -L OUTPUT -n
# firewalld
firewall-cmd --list-all
On Hostney, outgoing connections on standard ports (80, 443) are allowed by default. Outgoing connections to non-standard ports may be restricted depending on the hosting plan.
Cause 4: WordPress loopback request failure#
WordPress makes requests to itself (loopback requests) for several functions: cron execution, REST API health checks, and the Site Health test. If the server cannot reach itself via its public URL, these requests timeout.
How to confirm
The Site Health page (Tools > Site Health) shows “Your site could not complete a loopback request” or “The REST API encountered an unexpected result.”
How to fix
The loopback request goes through the full HTTP path: WordPress makes a request to your site’s public URL, which resolves via DNS, hits your server’s public IP, goes through Nginx, and reaches PHP. If any step in this chain does not work for requests originating from the server itself, the loopback fails.
Common causes:
- DNS not resolving to the server. If the server resolves its own domain to a different IP (like a CDN IP), the request goes to the CDN instead of to itself. This can timeout if the CDN does not route the request back correctly.
- Firewall blocking the server’s own IP. Some firewall configurations block requests from the server’s own IP address.
- HTTP authentication on wp-admin. If basic auth protects wp-admin, loopback requests to the REST API may fail because they do not include credentials.
A quick test:
# From the server, request its own homepage
curl -I https://yourdomain.com --connect-timeout 5
If this times out, the server cannot reach itself. Add the domain to
/etc/hosts
pointing to
127.0.0.1
, or configure Nginx to handle the request internally.
Cause 5: Slow external API response#
The remote server is reachable and responding, but too slowly. WordPress’s default cURL timeout for most operations is 5-10 seconds. If the API takes 15 seconds to respond, cURL times out at 10 seconds and reports error 28.
How to confirm
The cURL error appears intermittently rather than consistently. The external service works when you test it manually (because your manual test has a longer timeout), but fails from within WordPress.
How to fix
Some plugins allow you to configure the timeout. Check the plugin’s settings for a “timeout” or “connection timeout” option.
If you are writing custom code, set a longer timeout:
$response = wp_remote_get('https://api.example.com/data', array(
'timeout' => 30, // seconds
));
WordPress also provides a global filter to increase the timeout:
add_filter('http_request_timeout', function() {
return 30;
});
Be cautious with this global filter – a 30-second timeout on every outgoing request means that if an external service is down, each request blocks a PHP worker for 30 seconds. On a busy site, this can exhaust PHP-FPM workers quickly and cause 503 errors.
A better approach is to increase the timeout only for the specific request that needs it, not globally.
Cause 6: SSL certificate verification failure#
cURL verifies the remote server’s SSL certificate by default. If the server’s certificate is expired, self-signed, has an incomplete chain, or uses a cipher that your server’s OpenSSL does not support, cURL may hang during the TLS handshake and eventually timeout rather than returning a clear SSL error.
How to confirm
Test the SSL connection directly:
curl -v https://api.example.com --connect-timeout 5 2>&1 | grep -i ssl
If you see SSL-related errors or the connection hangs during the handshake, SSL verification is the issue.
How to fix
If the remote server’s SSL certificate is genuinely broken, contact the service provider. You should not bypass SSL verification in production code.
If your server’s CA certificate bundle is outdated (common on older servers), update it:
# On Rocky Linux / RHEL
yum update ca-certificates
# On Ubuntu / Debian
apt update && apt install ca-certificates
If WordPress cannot verify certificates for any remote server, the CA bundle may be misconfigured. Check the WordPress Site Health page for SSL-related warnings.
Cause 7: Plugin making excessive external requests#
Some plugins make external HTTP requests on every page load – checking license validity, loading remote assets, fetching live data. If the external service is slow (even by 500ms), this adds latency to every page and can timeout under load when multiple requests queue up.
How to confirm
Enable debugging and log all outgoing HTTP requests:
add_action('http_api_debug', function($response, $context, $class, $parsed_args, $url) {
error_log("HTTP request to: {$url} - Status: " . wp_remote_retrieve_response_code($response));
}, 10, 5);
Check
wp-content/debug.log
after loading several pages. If you see the same URL being called on every page load, that plugin is making redundant external requests.
How to fix
Enable object caching. With Memcached or Redis, WordPress caches transients in memory instead of the database. Plugins that use transients to cache API responses will hit the fast local cache instead of making external requests on every page load.
On Hostney, enable Memcached from the control panel and install the Hostney Cache plugin to handle the object cache integration automatically.
Check plugin settings. Some plugins have a “cache duration” or “update frequency” setting. A social media feed plugin checking Twitter every 60 seconds is unnecessary – set it to every 15 or 30 minutes.
Replace heavy plugins. If a plugin makes external requests on every page load and does not cache the results, it is poorly designed. Look for an alternative that caches responses properly.
cURL error 28 during WooCommerce checkout#
This deserves special attention because it directly affects revenue. If the payment gateway times out during checkout, the customer sees an error and the order may or may not have been processed.
Common payment gateway timeout causes:
- Gateway API is slow or down. Check the gateway’s status page (status.stripe.com, status.paypal.com).
- Network issue between your server and the gateway. Run a traceroute to the gateway’s API endpoint to identify where the latency is.
- Firewall blocking outgoing requests. Payment gateway APIs often use non-standard ports or specific IP ranges.
If payment gateway timeouts are recurring, consider:
- Increasing the timeout for payment requests specifically (most gateway plugins have this setting)
- Using the gateway’s webhook-based confirmation instead of synchronous API calls
- Setting up a fallback payment method so customers can complete checkout even if the primary gateway is slow
How Hostney handles outgoing connections#
Unrestricted standard ports. Outgoing connections on ports 80 and 443 are allowed by default, so WordPress update checks, plugin API calls, and payment gateway communication work without configuration.
Reliable DNS. DNS resolution is handled at the infrastructure level with performant resolvers. DNS-related cURL timeouts from resolver failures do not occur.
Container isolation. Each site’s outgoing requests run from its own container. One site making slow external requests cannot exhaust PHP workers for other sites. If a plugin on one site is stuck waiting for a slow API, only that site’s PHP workers are affected.
Summary#
cURL error 28 means an outgoing HTTP request from your WordPress site timed out. The cause is either the destination server being down or slow, DNS resolution failing, a firewall blocking the connection, or a loopback request failing because the server cannot reach itself.
Start by identifying which service the request was trying to reach (the error message or debug log usually includes the URL). Test that service from the command line with
curl
. If the service is reachable from the command line but not from WordPress, check plugin-specific timeout settings and WordPress’s HTTP API configuration. If the service is unreachable from the command line too, the problem is network-level (DNS, firewall, or the service itself). For a complete reference of WordPress errors and their quick fixes, see How to fix the most common WordPress errors.