Two sites. Only one works.

I have two SSL-enabled sites running on Heroku, both of which provide APIs. I bought the SSL certificates from different sources.

When I use Ruby and Python to make some POST calls to Site #1's API, everything works fine.

However, when I use Ruby and Python to make some POST calls to Site #2's API, I get SSL: certificate verify failed errors. (Even though everything looks fine when I access the site in Chrome)

Ruby error for site 2:
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Python error for site 2:
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)

Is a "Domain Validated" certificate enough?

I'd like other users to be able to access Site #2's API, without having to hack to get around this error. But I'm not sure what the problem is -- is it that my certificate is inherently insecure (it's only domain validated, but I believe certificate #1 is also only domain validated, so I'm not sure why that one works fine), or is it possible I messed something up when setting up SSL for Site #2 (so I can fix the problem without buying another certificate)?

If I do need to buy another certificate, do I need to make sure it's an OV or EV certificate? Or would a DV certificate from a certain source work? (I don't have an official company set up yet, so would prefer a DV certificate for now, even though I know it's less trustworthy-seeming.)

(I've googled these errors, but all the solutions seem to suggest some kind of local Ruby/Python problem, whereas I think I have a certificate problem.)

More details

More details about the troublesome certificate:

  • Issued by COMODO RSA Domain Validation Secure Server CA.
  • The "common name" is actually different from the domain I'm trying to access. (because this is intended to be a multi-domain certificate)
  • If I view the details of the certificate in Chrome, Chrome says Valid Certificate: The connection to this site is using a valid, trusted server certificate.
  • ssllabs.com (https://www.ssllabs.com/ssltest/analyze.html) gives the domain 3 A+ ratings.
  • Is the domain you're accessing covered in the "Subject Alternative Names" of the certificate? Does the server provide all the needed intermediate certificates? Look in "Alternative names" and "Certification Paths" shown on Qualis' tester.
    – Z.T.
    Nov 8, 2016 at 5:13
  • Yup, the domain I'm accessing (hybridml.com) is covered in the Alternative Names. I don't see any issues listed in the Certification Paths (ssllabs.com/ssltest/…), but I'm not sure what I'm looking for. I do get three A+ ratings.
    – haelcuoe
    Nov 8, 2016 at 5:37
  • 2
    If you have (or can get) openssl on the same system, use openssl s_client -connect www.hybridml.com:443 -servername www.hybridml.com -showcerts to see (1) whether openssl validates the chain (I don't know if it will use the same truststore as python and ruby; it will differ from Chrome) and (2) either way capture the certs received and look at each one with openssl x509 -text to see if they are the ones you expect from your server or if imposterization is occurring as @Steffen hypothesizes. Nov 8, 2016 at 9:58
  • 2
    ... And if you know where your truststores are (for python and ruby, and openssl), check for the COMDO RSA Certificate Authority root with SHA1 fingerprint afe5d244a8d1194230ff479fe2f897bbcd7a8cb4 . Nov 8, 2016 at 10:02
  • @haelcuoe: Did you manage to solve this problem? How? Aug 5, 2017 at 18:09

1 Answer 1


I have no problems accessing www.hybridml.com with python and requests library. Tested with 2.7.6., 2.7.12 and 3.5.2. Also the SSLLabs report looks fine, i.e. no missing chain certificates and the subject matches. And the browsers work fine.

This together suggests that you have something that is intercepting the SSL connection. Such SSL man in the middle results in a new certificate for the target site signed by the CA of the interception software. Since the browser throws no warnings this is probably legal interception, typically done by a corporate firewall but also by various antivirus solutions for desktop. It might also be that the browser and the proxy is connecting differently to the target, i.e. one through a proxy and the other not. Such differences can happen because python and ruby neither share the list of trusted CA nor the proxy settings with the browser.

I suggest that you check the certificate chain inside the browser and see if it actually results to the expected Comodo CA as a root or something else, i.e. the CA from the man in the middle.

  • I'm not so sure. In SSLLabs for I see two paths: #1 (after EE and Comodo RSA DomainVal) to root with SHA1 beginning afe5d24 which is dated 2010 but in the easiest source for me to check, Oracle Java, was added only in May 2015 (8u51). #2 goes through bridge cert with SHA1 beginning f5ad0bcc -- which is still offered as current at support.comodo.com/index.php?/Knowledgebase/Article/View/966/… -- to AddTrust, but is flagged 'Extra Download' i.e. not from server. ... Nov 8, 2016 at 9:45
  • ... Does python (or ruby) have its own cacerts info or use system-provided ones? OP didn't identify OS or distro. I'd check that also. Nov 8, 2016 at 9:48
  • 1
    @dave_thompson_085: This depends. Python requests usually uses its own CA store based on Mozilla CA. Nov 8, 2016 at 12:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .