Stop turning off CURLOPT_SSL_VERIFYPEER and fix your PHP config

As Pádraic Brady points out in a recent article about PHP security, there’s a whole lot of misinformation about how to deal with the error “SSL certificate problem, verify that the CA cert is OK” from curl. Nearly everyone advises that you turn CURLOPT_SSL_VERIFYPEER off (in fact, countless comments on the PHP manual page for curl_setopt tell you this). This is bad, because it allows your nice, encrypted stream of confidential data to be silently highjacked by a bad guy. Don’t do that! Instead, just fix your PHP installation so that it doesn’t get that error.

The error is caused by not having an up-to-date bundle of CA root certificates. This is typically a text file with a bunch of cryptographic signatures that curl uses to verify a host’s SSL certificate. You need to make sure that your installation of PHP has one of these files, and that it’s up to date.

Anyone running a recent Linux distribution is probably already OK, because they get the curl libraries bundled in through their package managers and recent curl libraries come with the latest CA root certificate bundle from This means you can just turn CURLOPT_SSL_VERIFYPEER on and you won’t get any errors.

For a PHP installation that doesn’t come with this file, like the Windows PHP distribution, you need to download the CA root certificate bundle and tell PHP where to find it. Luckily this is really easy. The curl website has the latest CA root certificate bundle ready to go, just download the .pem and save it where your PHP installation can access it.

Then you just need to edit your php.ini file to tell curl where you saved the .pem file. On my Windows test VM, I have several PHP versions under c:\php, so I put the file into that folder and added this line to each php.ini file:


After restarting the web service, curl now has a valid CA root certificate bundle and it can verify the SSL certificates of remote servers just fine. If it does get an error, it’s because the certificate is invalid — and that’s what you want it to do.

Job is done, safely.

  • Dude you saved my life, LOL. I had no idea that the windows distribution of PHP didn’t come with the certs and after spending a few days narrowing down my searches I found this blog entry. Thanks for this! :)


  • Thanks Ross, great post. I wasn’t aware you could set the value in PHP.INI, that makes it much easier to manage different certs on a per-domain bases on a cpanel/whm server.

    • G’day Josh,

      Note that you can also explicitly set the path to the certificate bundle in the call to curl(), by setting the CURLOPT_CAINFO option. Thus, if you have a web application that needs to access servers with self-signed certificates, you can add the .pem file to your web application and tell curl() to use that one instead. This is especially useful if you have to mix it up between public servers and servers with self-signed certs.


  • Eric Caron

    On Linux, the code to append to php.ini looks like

    curl.cainfo = "/etc/ssl/certs/ca-certificates.crt"

    Thanks for this great blog post! Far too many people turn off VERIFYPEER and I hope more sysadmins come across this blog and start doing it right!

  • Pingback: WordPress update failing because of missing SSL certificate – Franz Josef Kaiser()

  • Thank you man! You saved my life.

  • Alex Gusev

    Thanks a lot! It’s just I need!!!

  • Natsu

    Well, doesn’t helped for the problem with WP and Jetpack – error still occures:

    The Jetpack server was unable to communicate with your site https://XXX [IXR -32300: transport error: http_request_failed SSL certificate problem: unable to get local issuer certificate]

    Have replaced my URL wit XXX hope that this line is enough for this.
    Hope to get a little help why the error still occures.

    • Your problem there is that Jetpack won’t accept self-signed or otherwise invalid certificates. see here for details. Maybe you can install a free SSL certificate from StartSSL.


  • Dude, this is awesome! I was hesitant to make a global server change as is suggested all over SO. Your solution worked flawlessly on a win 7 dev environment.


  • Kenton Kenton

    Thank you for this. Two additional notes for WAMP users. I needed the path to be of the form

    for it to work.
    Secondly, you need to restart WAMP.

  • blodan

    Another option you’d also want is
    openssl.cafile = /usr/local/share/certs/ca-root-nss.crt

  • This solution worked for me. In my case I had to restart my machine for Apache to take updated php.ini settings.

  • sholan

    thank you for this usefull post really worth it

  • pramod

    for wamp, path must be with forward slashes!


    • Mizan

      Thanks a lot

  • Jeremy

    Thank you for taking the time to explain the proper fix. I appreciate it. Works like a charm!

  • Prins Prem

    Hi anyone know how can i enable curl and ssl_curl in my server

    • Best to talk to your hosting provider, they can help you configure your server.

  • Juan Cruz Hurtado

    I can’t make it work! I have done everything you recommend, but I am still getting the error “SSL certificate problem: self signed certificate in certificate chain” on a Windows Server
    Any suggestions? Thank you!!!!!

    • jkhan

      Hi Juan!

      this is the same issue i have. i am running it under or company’s webproxy and i get this error. if i run the script outside the proxy then it is fine. did you get any work around to solve this.


  • Kopack

    Thanks a lot

  • jkhan

    I am having this issue in Xampp. i did the curl.cainfo entry in the script also in the php.ini file but it doesn’t work on the windows local. but if i upload the script to external server (goDaddy) with pointing it to the cacert.pem, then it work fine.

    can you guys please advise, what am i missing in windows config of xampp or php?

  • jeliasson

    Any thoughts on how to fix this problem on the Azure Web App-service? “cainfo” is not part of the user space, rather than system space.

  • Will Craig

    Awesome thanks this is much better than disabling CURLOPT_SSL_VERIFYPEER

  • Erik Kalkoken

    Thanks for the great article. I was running without SSL on my WAMP for a while, but have it fixed now.

  • Chandra Nakka

    Excellent solution. Thank you very much :)

  • Scott Jimmy

    Thanks for the tip – will make sure this is how I setup it up locally from now on.

  • Divya

    Thanks, Its works like a charm. You saved my time. :)

  • Dakota Hipp

    I’m on windows with wamp, coping and pasting the cacert file contents from the link provided above was not working for me. I found this to be the problem thanks to GeoffGordon’s comment on this post: Here is a link they provided that will automatically download a clean copy of the file and then you can just place the file where you need it: This solution finally worked for me.

    • Indeed, you should not copy/paste the cacert.pem file, just download it without modification.

  • twiddly

    Thank you! I was having issue testing on local php7 xampp server [with payeezy] and this did the trick. You’re a lifesaver.