How to make an interactive map using Python and open source libraries

Today we are sharing with you a step-by-step guide to creating interactive maps for a web application or blog. Just bookmark this article. While there is, for example, a d3.js library that can create custom maps, there are a few tools that are even simpler. In this post, we’ll look at and work with three easy-to-use, yet powerful open source Python libraries.

When the documentation gets stuck

A few months ago, I wanted to create an interactive map for an interesting web application that we were developing. I spent hours on the internet looking for the perfect library to get started, but it was very difficult for me to look at the documentation as there was no proper step-by-step guide to implement and customize the visuals as needed. I wished I had a manual comparing features and correct implementation along with details on customization. This article is an attempt to write such a guide.

The article goes on to compare implementations of an interactive background map (choropleth) using three popular libraries available for Python, and the details and customization of the final result.

  1. Altair – simple and fast implementation with an easily accessible set of functions.
  2. Plotly – has rich functionality. Includes Mapbox, custom settings and styling.
  3. FoliumLeaflet – fully customizable and interactive. Includes tooltips, pop-ups and more.


A chorus map requires two kinds of data in the background, one of which is geospatial data, geographic boundaries to populate the map (usually a vector file .shp (Shapefile) or GeoJSON), and two data points on each square of the map to color-code the map based on the data itself.

Geo Pandas library is useful when you need to get data in the required format. The example uses the Indian states GeoJSON file. You can start with any public Shapefile or GeoJSON.


Altair Is a visualization library for Python based on Vega… The chorus is implemented with minimal effort and includes interactive elements – highlighting, tooltips, etc.

Altair is compatible with fastpages… You can create simple blog posts in minutes by simply converting Jupyter Notebook files with a minimum of code. Check out Readme on GitHub.

Snippet of code:

# Importing required Libraries
import geopandas as gpd
import json
import altair as alt
import pandas as pd

We read the Shapefile as a GeoPandas frame:

gdf = gpd.read_file('states_india.shp')

The frame looks like this:

Create a base layer and a choropleth layer:

# Creating configs for color,selection,hovering
multi = alt.selection_multi(fields=['count','state'], bind='legend')
color = alt.condition(multi,
                  alt.Color('count', type="ordinal",
hover = alt.selection(type="single", on='mouseover', nearest=True,
                      fields=['x', 'y'])
#Creating an altair map layer
choro = alt.Chart(gdf).mark_geoshape(
# Legend
c1 = alt.layer(choro).configure_legend(
    direction = 'horizontal',
    padding = 10,
    rowPadding = 15
#Adding Labels
labels = alt.Chart(gdf).mark_text().encode(
c2 = alt.Chart(gdf).mark_geoshape(

The code above should render an interactive map with the function of displaying a tooltip and highlighting on selection (click).


  • Simple and fast implementation. Includes a predefined set of features to speed up your work.
  • Fastpages compatible


  • Few customization options and limited interactivity.
  • It is not possible to use external stylized parts of the map such as OSM, Mapbox, etc.
  • The API is poorly documented.

Implementation with Plotly

Library Plotly for charting in Python, renders ready-to-publish maps with a lot of interactive and customizable features.

Custom basemap configurations from Mapbox, OSM and other styling options are available, as well as simple implementation with Plotly Express and extensive documentation. This makes Plotly one of the preferred options for creating interactive maps.

Snippet of code:

# Importing required libraries

from plotly.graph_objs import Scatter, Figure, Layout
import plotly
import plotly.graph_objs as go
import json
import numpy as np
import geopandas as gpd

Importing Shapefile:

gdf = gpd.read_file('states_india.shp')
with open('states_india_1.json') as response:
 india = json.load(response)

Creating a base layer and adding parts of the map:

fig = go.Figure(go.Choroplethmapbox(geojson=india, locations=gdf['st_nm'], z=gdf['state_code'],featureidkey="properties.st_nm",colorscale="Viridis", zmin=0, zmax=25,marker_opacity=0.5, marker_line_width=1))
                  mapbox_zoom=3.5,mapbox_center = {"lat":23.537876 , "lon": 78.292142} ) 

The code above should render an interactive map with tooltip display and zoom function. This implementation includes a large number of other features, which are described in more detail. here


  • Very simple implementation with charting libraries and Plotly Express. There is extensive documentation.
  • Lots of settings and customizable styling options.
  • Compatible with Dash and other options for embedding snippets in external web applications.


  • There is no way to add pop-ups and other interactive elements beyond the predefined options.
  • May require token access to work with multiple external styles. Limited control over scaling limits and associated interactivity.

Implementation with Folium

Folium combines the ease of use of the Python ecosystem with the strengths of the leaflet.js mapping library. It allows you to render customizable, responsive and interactive choropleth maps, as well as transfer rich vector, raster, HTML visualizations as markers on the map.

The library has a number of built-in sets of map tiles from OpenStreetMap, Mapbox and Stamen, and also supports custom sets through the Mapbox or Cloudmade APIs. Images, videos, GeoJSON and TopoJSON are supported.

Snippet of code:

# Importing required Libraries
import geopandas as gpd
import pandas as pd
import folium
import branca
import requests
import json
from folium.features import GeoJson, GeoJsonTooltip, GeoJsonPopup

Importing Shapefile:

gdf = gpd.read_file('states_india.shp')
with open('states_india_1.json') as response:
    india = json.load(response)
#Creating a custom tile (optional)
import branca
# Create a white image of 4 pixels, and embed it in a url.
white_tile = branca.utilities.image_to_url([[1, 1], [1, 1]])

Adding base layers and Choropleth layers:

#Base layer
f = folium.Figure(width=680, height=750)
m = folium.Map([23.53, 78.3], maxZoom=6,minZoom=4.8,zoom_control=True,zoom_start=5,
               scrollWheelZoom=True,maxBounds=[[40, 68],[6, 97]],tiles=white_tile,attr="white tile",
#Add layers for Popup and Tooltips
popup = GeoJsonPopup(
    aliases=['State',"Data points"], 
    style="background-color: yellow;",
tooltip = GeoJsonTooltip(
    aliases=['State',"Data points"],
        background-color: #F0EFEF;
        border: 1px solid black;
        border-radius: 3px;
        box-shadow: 3px;
# Add choropleth layer
g = folium.Choropleth(
    columns=['st_nm', 'cartodb_id'],
    legend_name="Data Points",
    style_function=lambda feature: {
        'fillColor': '#ffff00',
        'color': 'black',
        'weight': 0.2,
        'dashArray': '5, 5'

The code above should display an interactive choropleth map with hover hint, click to zoom in and custom popup on click.


  • A number of settings and customizable style options along with unique interactive features like custom pop-ups / map parts / backgrounds and click-to-zoom zoom.
  • Option to transfer vector, raster, HTML visualizations as markers on the map.
  • The option to display the map as HTML and other options for embedding the fragment in external web applications.
  • A decent amount of documentation to explore all the available functions.


  • Depends on multiple libraries.


These three tools allow you to create custom interactive maps for your websites without much hassle.

Dear readers, have you ever made such interactive maps for your projects?