This library allows Python to connect to OGC services such as WMS, WFS, SOS etc. by creating URLs and requesting their contents. The project description from PyPI is:

OWSLib is a Python package for client programming with Open Geospatial Consortium (OGC) web service (hence OWS) interface standards, and their related content models. OWSLib provides a common API for accessing service metadata and wrappers for numerous OGC Web Service interfaces.

A few notes:

  • Full documentation is available at http://geopython.github.io/OWSLib
  • OWSLib is a “pure Python” library - all the code is written in Python. There are no C/C++ compiled DLLs used or installed by OWSLib.
  • OWSLib uses the requests library for HTTP requests. This is widely used in Python libraries and scripts for connecting to remote servers using HTTP, and is described as HTTP for Humans.
  • API is an Application Programming Interface (the interaction with the library from Python scripts, as opposed to a UI, user interface)
  • For a list of all OGC standards see http://www.opengeospatial.org/standards (not all of these are supported by OWSLib)

Use Cases

  • Automating retrieval of data from remote servers
  • Testing WMS and WFS configurations on servers

Irish OGC Servers

There are a number or publicly accessible servers in Ireland that serve data using OGC standards such as WMS and WFS. There can be found via data portals such as:

Below are a couple of scripts to view what datasets are available on these servers using Python.

Web Map Service (WMS)

from owslib.wms import WebMapService

def get_details(url, version="1.3.0"):
    wms = WebMapService(url, version=version)
    # list all layers available in the WMS service
    for layer in wms.contents:

# GSI OneGeology INSPIRE View Service
gsi_url = "http://spatial.dcenr.gov.ie/geoserver/wms?"

# EPA WMS (Water Framework Directive) server
epa_wms = "http://gis.epa.ie/geoserver/wfd/wms?"
# only supports version 1.1.1 or get the following error
# ValueError: <Element '{http://www.opengis.net/wms}Style' at 0x5dec400> missing name or title
get_details(epa_wms, version="1.1.1")

# Marine Institute (each theme has a different Mapfile)
mi_wms = "http://atlas.marine.ie/mapserver/?map=C:/MapServer/apps/miatlas/Fisheries_wms.map&"

Web Feature Service (WFS)

WFS services typically return GML Geography_Markup_Language. The inbuilt xml Python library is used to parse the XML.

import xml.dom.minidom # WFS returns GML - this library is used to parse it
from owslib.wfs import WebFeatureService

def get_details(url, version="1.1.0"):
    wfs = WebFeatureService(url, version=version)
    # list all layers available in the WMS service
    for layer in wfs.contents:

    return wfs

# EPA WFS (Water Framework Directive) server
epa_wfs = "http://gis.epa.ie/geoserver/wfd/wfs?"

# GSI OneGeolgy INSPIRE View Service
gsi_url = "http://spatial.dcenr.gov.ie/geoserver/wfs?"
wfs = get_details(gsi_url)

# get a sample feature from the first layer
typename = "GSIEGDI:oge_1m_surface_geologicunits"
response = wfs.getfeature(typename, maxfeatures=1)
# print(response.read())
xml = xml.dom.minidom.parse(response) # or xml.dom.minidom.parseString(xml_string)
print(xml.toprettyxml(indent="    "))


Session Script


A minor change is required to the MapServer Mapfile (its configuration file) to get the test script to run. Run the following from the command line to open the Mapfile in a text editor, with write permissions:

sudo leafpad /usr/local/www/docs_maps/mapserver_demos/itasca/itasca.map

Next the line below needs to be commented out using a hash (#) symbol:

# WMS_ONLINERESOURCE "http://localhost.localdomain/mapserver_demos/itasca/index.html"

The Mapfile displays data from Itasca, Minnesota.

from owslib.wms import WebMapService
url = "http://localhost/cgi-bin/mapserv?map=/usr/local/www/docs_maps/mapserver_demos/workshop/itasca.map"
wms = WebMapService(url, version='1.1.1')

# list all layers available in the WMS service

# let's work with the Lakes layer
lake_layer = wms["lakespy2"]
print(lake_layer.title) # Lakes and Rivers

# now get the lakes bounding box and projection
bbox = lake_layer.boundingBox # (393234.0, 5208170.0, 495403.0, 5303960.0, 'EPSG:26915')
proj = bbox[-1]
bbox = bbox[:-1]

# print(lake_layer.styles) # the lakes layer has a "default" style

img = wms.getmap(layers=['lakespy2'],
                    size=(400, 400),

# now output the map to a png image file

with open('lakes.png', 'wb') as f: