Search code examples
sslpython-2.xgeopy

Reverse gecoding - geopy.Nominatim module throws urlopen error [SSL: UNKNOWN PROTOCOL]


I am trying to get the address details from Latitude and Longitude using geopy.Nominatim module. Am getting "<'urlopen error [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:727)>" error.

Version Details :
Python version : 2.7
geopy version : 1.23.0
geographiclib : 1.50  (Dependency with geopy)
requests : 2.25.1
chardet : 3.0.4 (Dependency with requests)
urllib3 : 1.25.10 (Dependency with requests)
idna : 2.10 (Dependency with requests)
certifi : 2020.6.20 (Dependency with requests)
Code:
=====
from geopy.geocoders.osm import Nominatim
from geopy.exc import GeocoderServiceError
 

def reverse(lat,long):

    app = Nominatim(user_agent='reverse-geocoding')
    coordinates = "{},{}".format(lat,long) # not giving the actual co-ordinates
    try:
        address_details = app.reverse(coordinates,language="en").raw
        return address_details
    except GeocoderServiceError as e1:
        print (str(e1))

result = reverse(lat,long)
print(result)

================ I have used the following workarounds with the same script.Am getting "<'urlopen error [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:727)>" error

workaround 1: To use the CA bundle used by requests library:

from geopy.geocoders.osm import Nominatim
from geopy.geocoders import options
from geopy.exc import GeocoderServiceError
import ssl
import certifi

def reverse(lat,long):
    ctx = ssl.create_default_context(cafile=certifi.where())
    options.default_ssl_context = ctx
    app = Nominatim(user_agent='reverse-geocoding')
    coordinates = "{},{}".format(lat,long) # not giving the actual co-ordinates
    try:
        address_details = app.reverse(coordinates,language="en").raw
        return address_details
    except GeocoderServiceError as e1:
        print (str(e1))

result = reverse(lat,long)
print(result)

Workaround 2: To disable TLS certificate verification completely:

from geopy.geocoders.osm import Nominatim
from geopy.geocoders import options
from geopy.exc import GeocoderServiceError
import ssl


def reverse(lat,long):
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    options.default_ssl_context = ctx
    app = Nominatim(user_agent='reverse-geocoding')
    coordinates = "{},{}".format(lat,long) # not giving the actual co-ordinates
    try:
        address_details = app.reverse(coordinates,language="en").raw
        return address_details
    except GeocoderServiceError as e1:
        print (str(e1))

result = reverse(lat,long)
print(result)

Could anyone please help me to find a fix for this issue.


Solution

  • The error UNKNOWN PROTOCOL is in all probability due to the fact that your request is going via a proxy.

    I looked into your code mentioned in Workaround 2. Please mention the proxy explicitly in your code. Try using below code lines:

    ctx = ssl.create_default.context()
    ctx.check_hostname = True
    ctx.verify_mode = ssl.CERT_REQUIRED
    options.default_ssl_context = ctx
    proxies = {'https':'https://your-proxy-server.com:port'}
    app = Nominatim(user_agent="your-agent", proxies=proxies, timeout=10)
    

    This will also help you not to ignore SSL verification completely.