Skip to main content

Engineering Notes

Using PHP cURL over HTTPS — and what 2011 got wrong about certificates

In 2011 we published a quick fix for PHP cURL’s HTTPS errors: switch certificate verification off. It worked, everyone did it — and it was wrong. This revision preserves the original technique as history, explains the risk plainly, and shows the approach we use today.

By E Multitech Solution Engineering Team Published Substantially revised 4 min read

Historical technique — superseded. The original 2011 technique below is preserved for historical accuracy and is no longer recommended. See the “right way today” section for current guidance.

The 2011 problem

Calling an https:// URL from PHP’s cURL extension in 2011 frequently failed with SSL errors — missing CA bundles on shared hosting were endemic, and error messages were unhelpful. The original article began, sensibly, by checking that cURL existed at all:

if (!function_exists('curl_init')) {
    die('cURL is not enabled or installed!');
}

The 2011 fix (and its hidden cost)

The era’s standard remedy — the one our original post shared — was a single line:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

It made the errors vanish, which is why it spread across a decade of forum answers. But the line does not fix certificate verification — it abandons it. With peer verification off, your request will happily complete against any server presenting any certificate, which is precisely the situation TLS exists to prevent. For requests carrying credentials or payment data, it converts an encryption layer into a decoration.

The right way today

The correct fix, then and now, is to give cURL a certificate authority bundle to verify against — modern PHP installations ship with one configured, and when they do not, you point to one explicitly:

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => true,   // the default — leave it on
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_CAINFO => '/path/to/cacert.pem', // only if the system bundle is absent
]);
$response = curl_exec($ch);

A current CA bundle is distributed by the curl project itself, and every mainstream PHP platform since PHP 5.6 verifies peers by default — the language ultimately fixed what hosting culture had broken.

The durable lesson

Present-day editorial perspective.

The 2011 post is a small time capsule of a real industry habit: when security friction meets a deadline, the switch gets turned off. Our practice’s rule today is the opposite — make the secure path the easy path, in this case by baking CA bundles into base images so no engineer is ever tempted by VERIFYPEER, false again. Sometimes the most valuable thing an old article can teach is why it needed correcting.