Creating a Choropleth Map

With Datawrapper, you can create maps for over 1,000 different regions, using the same API endpoints that you use for charts. In this tutorial, you'll learn to create & edit a choropleth map. To learn how to create locator maps, visit this article instead.

📘

You need an API Access Token

Everything you need to follow this tutorial is a Datawrapper account and an API Access Token. Both are available for free. You can create an API Access Token with the click of a button in your Datawrapper settings. Learn how to do so in this article.

Create a map

Let's start with a short POST request to create our map. To do so, we'll define the visualization type in the API request. (Defining the title is not necessary, but it can't hurt.)

curl --request POST \
  --url https://api.datawrapper.de/v3/charts \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  --header 'content-type: application/json' \
  --data '{ "title": "Literacy rates in Africa", "type":"d3-maps-choropleth"}'

This will give you back a response with your id. In our case, that's HpeMi. You should remember your map ID, because you will need it for many of your following API requests. For example, if your chart id was th4ns, you'll need to insert that in the examples below every time you'll see the placeholder <ID> – otherwise, your requests won't work.

That was easy! But we still need to decide on the data we want to display, and the kind of map we want to use to do so:

Decide on a basemap

Choropleth maps differ from charts and locator maps in one important way: they require a basemap for your data to be plotted on.

Basemaps contain the administrative borders that are used to display the data. Datawrapper offers over 1,000 basemaps out of the box, like Denmark ZIP codes, Quebec Electoral Districts, countries in Africa or US states. To retrieve a list of all available basemaps, you can use the following API endpoint:

curl --request GET \
  --url https://api.datawrapper.de/plugin/basemaps

The response lists all basemaps and their IDs. The beginning of it looks like this:

{
  "status": "ok",
  "data": [
    {
      "id": "world",
      "label": "World",
      "keys": [
        {
          "value": "id",
          "label": "ISO-Codes",
          "description": "The three-letter ISO-code of the country."
        },
        {
          "value": "ADMIN",
          "label": "Names",
          "description": "The written name of the country."
        },
        {
          "value": "WB_NAME",
          "label": "World Bank Names",
          "description": "The written name of the country."
        },
        {
          "value": "ADMIN_GER",
          "label": "Names (German)",
          "description": "The written name of the country in German."
        }
      ]
    },
    {
      "id": "africa",
      "label": "Africa",
      "keys": [
        {
          "value": "ADMIN",
          "label": "Names",
          "description": "The written name of the country."
        },
        {
          "value": "ADM0_A3",
          "label": "ISO ",
          "description": "iso  code of the country"
        }
      ]
    },
    {
      "id": "europe",
      "label": "Europe",
      ...
    },
    ...
    }
  ]
}

Decide on a map key

For each basemap, you will find one or several keys. Keys are a crucial part of creating choropleth maps with Datawrapper. Their purpose is to match your dataset to the correct regions on the map. For example, for the world map, you can upload your dataset if it contains either ISO codes, the respective names of the countries according to the World Bank standard or the Natural Earth Data standard, or German names.

Let's say we want to create a map of Africa using the ISO code of the countries. According to the API response above, the ADM0_A3 key contains the ISO code of the countries. To retrieve all of them, you can make a request like this:

curl --request GET \
  --url https://api.datawrapper.de/plugin/basemaps/africa/ADM0_A3

The response will contain information about that particular key, and an array with all possible values:

{
  "status": "ok",
  "data": {
    "value": "ADM0_A3",
    "label": "ISO ",
    "description": "iso  code of the country",
    "values": [
      "ETH",
      "SDS",
      "SOM",
        ...
      "COM",
      "STP",
      "CPV"
    ]
  }
}

Using this data, we can ensure that the dataset we upload will match correctly with the data format that our basemap expects.

Upload the data

To create a map, all we still need is the actual data. We will upload the literacy rate in African countries, that we got from Our World in Data. We can prepare the data as a CSV.

📘

You will need to upload at least two columns – one with the key and one with the values. But you can upload as many columns as you like. For example, you might want to fill the tooltips on your map with additional information that you get from an extra column you've uploaded.

We prepare three columns: the country names, the ISO codes and our values:

country,code,literacy-rate
Angola,AGO,71.2
Burundi,BDI,85.5
Benin,BEN,38.4
Burkina Faso,BFA,37.7
Botswana,BWA,88.2
Central African Republic,CAF,36.8
Cote de Ivoire,CIV,43.3
Cameroon,CMR,75
Democratic Republic of Congo,COD,77.2
Congo,COG,79.3
Comoros,COM,78.1
Cape Verde,CPV,88.5
Algeria,DZA,79.6
Egypt,EGY,75.8
Eritrea,ERI,73.8
Ethiopia,ETH,49
Gabon,GAB,83.2
Ghana,GHA,76.6
Guinea,GIN,30.5
Gambia,GMB,55.6
Guinea-Bissau,GNB,59.8
Equatorial Guinea,GNQ,95.2
Kenya,KEN,78
Liberia,LBR,47.6
Libya,LBY,91.4
Lesotho,LSO,79.4
Morocco,MAR,71.7
Madagascar,MDG,64.7
Mali,MLI,33.1
Mozambique,MOZ,58.8
Mauritania,MRT,52.1
Malawi,MWI,66
Namibia,NAM,90.8
Niger,NER,19.1
Nigeria,NGA,59.6
Rwanda,RWA,71.2
Sudan,SDN,58.6
Senegal,SEN,55.6
Sierra Leone,SLE,48.4
Sao Tome and Principe,STP,91.7
Swaziland,SWZ,87.5
Chad,TCD,40
Togo,TGO,66.5
Tunisia,TUN,81.1
Tanzania,TZA,80.4
Uganda,UGA,73.8
South Africa,ZAF,94.6
Zambia,ZMB,85.1
Zimbabwe,ZWE,86.9

Now that we have some data, let's upload it. Make sure to replace our ID with your own one in this and all following requests!

curl --request PUT \
  --url https://api.datawrapper.de/v3/charts/<ID>/data \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  --header 'content-type: text/csv' \
  --data "country,code,literacy-rate
Angola,AGO,71.2
Burundi,BDI,85.5
Benin,BEN,38.4
Burkina Faso,BFA,37.7
...
Tanzania,TZA,80.4
Uganda,UGA,73.8
South Africa,ZAF,94.6
Zambia,ZMB,85.1
Zimbabwe,ZWE,86.9"

(You might need to get rid of the ' in Cote d'Ivoire to run the query successfully.)

Once we've uploaded the data, we can update the chart with the correct basemap and key to ensure the data gets displayed. We'll use a PATCH request to do so:

curl  --request PATCH \
  --url https://api.datawrapper.de/v3/charts/<ID> \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  --header 'content-type: application/json' \
  --data \
  '{
    "metadata": {
      "axes": {
          "keys": "code",
          "values": "literacy-rate"
      },
      "visualize": {
          "basemap": "africa",
          "map-key-attr": "ADM0_A3"
      }
    }
  }'

Note that metadata.visualize.basemap is set to the map name africa, and metadata.visualize.basemap.map-key-attr is set to the key name ADM0_A3.

Also, metadata.axes are set to the corresponding columns in our dataset, code and literacy-rate. Using these settings, the map will now render correctly. We can check if this is the case when we paste our ID in the URL https://app.datawrapper.de/map/HpeMi/visualize.

Edit the map

Now we can already publish our map (to do so, jump to the next section). But we can also add some settings to our map before we do so, like tooltips, colors, or the URL to the data source. They will all go into the property metadata.

📘

Play around to find all metadata properties

We won't have the capacity to explain every single property within metadata for choropleth maps. To learn the names of the properties (to then change them with API requests), consider creating a map within the Datawrapper app. You can change settings there, and then pull the property information for this chart from the API to learn what the changed settings are called.

Let's use the following PATCH request to give the map a proper description and source:

curl  --request PATCH \
  --url https://api.datawrapper.de/v3/charts/<ID> \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  --header 'content-type: application/json' \
  --data \
  '{
    "metadata": {
      "describe": {
          "source-name": "Our World in Data",
          "source-url": "https://ourworldindata.org/literacy",
          "intro": "Share of the population older than 14 years that is able to read and write, in African countries, 2015"
      }
    }
}'

We can add as many PATCH requests as we want to add or overwrite settings.

For example, to add tooltips, we'll add a property called metadata.visualize.tooltip with yet another PATCH request:

curl  --request PATCH \
  --url https://api.datawrapper.de/v3/charts/<ID> \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
  --header 'content-type: application/json' \
  --data \
  '{
    "metadata": {
      "visualize": {
        "tooltip": {
          "body": "{{ literacy_rate }}% of adults in this country can read.",
          "title": "{{ country }}",
          "fields": {
            "code": "code",
            "country": "country",
            "literacy_rate": "literacy-rate"
          }
        }
      }
    }
}'

Publish the map

To publish the map, run the following request. Afterwards, you can check if the map got published when opening the following URL: https://www.datawrapper.de/_/HpeMi/. In both cases, make sure you replace our map ID (HpeMi) with your own.

curl --request POST \
  --url https://api.datawrapper.de/charts/<ID>/publish \
  --header 'Authorization: Bearer <YOUR_TOKEN_HERE>'

And that's it! We successfully published a choropleth map. You will find the embed codes in the response to the last query. Learn more about how to publish visualizations with our API and how to read the response to a publish query.

This is what our final map looks like: