The M-Pesa API cURL error 28: Connection timed out after 5001 milliseconds means that your request is not reaching Safaricom’s API in time.
✅ How to Fix It:
1. Increase the Timeout Duration
The default timeout (5 seconds) may be too short. Increase it to 30 seconds.
PHP cURL Example:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Increase timeout
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // Increase connection timeout
$response = curl_exec($ch);
curl_close($ch);
Laravel HTTP Client:
$response = Http::timeout(30)->post($url, $data);
2. Check M-Pesa API Endpoints
Make sure you’re using the correct Sandbox or Production URLs:
✅ Sandbox:
https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest
✅ Production:
https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest
🚨 If you’re using sandbox credentials on a production URL, the request will fail.
3. Verify Your Access Token
An expired or incorrect access token can cause timeout issues. Ensure you’re generating the token correctly:
$access_token = Http::withBasicAuth($consumer_key, $consumer_secret)
->post('https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials')
->json()['access_token'];
Use this token in your API calls.
4. Check Internet Connectivity & Firewall
- Test internet connection:
ping api.safaricom.co.ke
- If using shared hosting, ask the hosting provider if they allow outbound cURL requests.
- If on VPS or dedicated server, check your firewall settings.
5. Confirm Safaricom API is Working
Sometimes, Safaricom’s API goes down or has high latency. Check:
🔗 https://developer.safaricom.co.ke
Or contact Safaricom API support.
6. Try a Different Network or VPN
If you suspect ISP blocking, switch to another network or use a VPN to test.
7. Use Asynchronous Requests
If you’re handling a large number of API requests, use asynchronous processing instead of waiting for immediate responses.
🚀 Final Step: Debug the Response
Enable cURL error tracking to see the exact issue:
if (curl_errno($ch)) {
echo 'Curl error: ' . curl_error($ch);
}
Try these fixes and let me know what worked! 🔥🚀