{"id":23464,"date":"2023-04-09T13:19:53","date_gmt":"2023-04-09T13:19:53","guid":{"rendered":"https:\/\/www.highcharts.com\/blog\/?p=23464"},"modified":"2026-01-13T11:29:53","modified_gmt":"2026-01-13T11:29:53","slug":"highcharts-maps-python-asynchronous-map-data","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/integration\/highcharts-maps-python-asynchronous-map-data\/","title":{"rendered":"Highcharts Maps for Python &#8211; Working with Asynchronous Map Data"},"content":{"rendered":"<p>Map visualizations are more complicated than standard charts because you\u2019re actually visualizing two distinct types of data: yes, you still have your quantitative data that you want to visualize but you also have to provide <b>Highcharts Maps for Python<\/b> with the map data on which your quantitative data should be visualized.<\/p>\n<p>How you supply your map data to Highcharts Maps for Python is a very important question because it can have significant performance implications for your code. Map data can be very verbose, and as such it can take a relatively time on the wire. For this reason, Highcharts Maps for Python lets you choose where your map data actually gets loaded: in your Python code, or in the JavaScript code produced by Highcharts Maps for Python.<\/p>\n<p><i><b>Tip<\/b><br \/>\n<b>Best practice<\/b>: Because map data can be verbose and relatively large on the wire, we typically prefer to load it asynchronously in the JavaScript code produced by Highcharts Maps for Python. We\u2019ll only load it synchronously in Python if our use case really calls for it (for example, programmatic creation of charts for download).<\/i><\/p>\n<h2>Applying Map Data<\/h2>\n<p>If you load your map data synchronously in your Python code, you\u2019ll configure your map data using a <code>MapData<\/code> instance. If you load your map data asynchronously in your JavaScript code, then in Python you\u2019ll set your configuration up using an <code>AsyncMapData<\/code> instance.<\/p>\n<p>In both cases, you can apply your map data to either the Chart instance as a whole using the <code>Chart<\/code> instance\u2019s <code><a href=\"https:\/\/maps-docs.highchartspython.com\/en\/latest\/api\/chart.html#highcharts_maps.chart.Chart.set_map_data\" target=\"_blank\" rel=\"noopener\">.set_map_data()<\/a><\/code> method, or to a specific series instance using that series instance\u2019s <code>.set_map_data()<\/code> method. The syntax for this method is the same, whether you\u2019re using <code>AsyncMapData<\/code> or <code>MapData<\/code>. Assuming your <code>Chart<\/code> instance is called <code>my_chart<\/code> and your map data is in a variable called <code>my_map_data<\/code> you just call:<\/p>\n<pre># Set the chart\u2019s map data, configured to load asynchronously\r\nmy_chart.set_map_data(my_map_data)<\/pre>\n<p>And that\u2019s it! Highcharts Maps for Python offers some convenience capabilities as well. For example, if you pass the <code>.set_map_data()<\/code> method a URL, Highcharts Maps for Python will automatically convert that to an <code>AsyncMapData<\/code> instance that will download your map data from that URL.<\/p>\n<h2>Configuring Your AsyncMapData<\/h2>\n<p>While setting up asynchronous map data can be as simple as supplying a URL to the <code>.set_map_data()<\/code> method, there are often situations where it can prove more complicated. For example, what if to access your map data you need to provide authentication credentials? Or what if you need to download a bunch of map data, but only use a subset of that map data in your visualization? Highcharts Maps for Python has you covered: The <code>AsyncMapData<\/code> class offers you a wide range of configuration options.<\/p>\n<h2>Authentication Credentials and Fetch Configuration<\/h2>\n<p>Highcharts Maps for Python gives you complete control over how your JavaScript code fetches your map data. When creating your <code>AsyncMapData<\/code> instance, you can supply a <code>fetch_config<\/code> property which configures how the JavaScript <code>fetch()<\/code> call is executed.<\/p>\n<p>The <code>fetch_config<\/code> property accepts a <code><a href=\"https:\/\/maps-docs.highchartspython.com\/en\/latest\/api\/utility_classes\/fetch_configuration.html\" target=\"_blank\" rel=\"noopener\">FetchConfiguration<\/a><\/code> instance. In a typical use case, you would use the <code>FetchConfiguration<\/code>\u2019s <code>credentials<\/code> and <code>header<\/code> properties to supply authentication credentials with your request. Let\u2019s imagine you are using Bearer authentication. You would set your <code>AsyncMapData<\/code> instance up as follows:<\/p>\n<pre>from highcharts_maps.options.series.data.map_data\r\nimport AsyncMapData\r\nfrom highcharts_maps.utility_classes.fetch_configuration\r\nimport FetchConfiguration\r\n# Set the chart\u2019 s map data, configured to load asynchronously\r\nmy_fetch_config = FetchConfiguration(headers = {\r\n  'Authorization\u2019: '\r\n  Bearer '\r\n})\r\nmy_map_data = AsyncMapData(url = 'https:\/\/www.my-map-data-url.dev\/map-data.topo.json',\r\n  fetch_config = my_fetch_config)<\/pre>\n<p>And that\u2019s it! By default, the <code>AsyncMapData<\/code> uses the HTTP GET method to download your map data, but if you need to use a different HTTP method (like POST or something similar) you can easily override the default using the <code>fetch_config<\/code> properties.<\/p>\n<h2>Using Selector Functions for Subsets of Map Data<\/h2>\n<p>Sometimes, you want to use only a subset of your map data in your data visualization. For example, you might want to show a map inset with more granular detail, or your geometry may contain multiple areas but your user is only interested in one, or perhaps you want to optimize your client-side performance by having your user download geometries once to cache them locally, and then rapidly switch between areas that are visualized. Highcharts Maps for Python allows you to do that by defining the <code>.selector<\/code> property on your <code>AsyncMapData<\/code> instance.<\/p>\n<p>The <code>.selector<\/code> property lets you define a JavaScript callback function which receives one argument: <code>topology<\/code>, which retrieves the map data downloaded from your <code>AsyncMapData<\/code> instance\u2019s <code>.url<\/code> property. Your JavaScript function can then perform whatever manipulations it needs to on the originally-downloaded topology. This can include selecting a subset of geometries from it, or even modifying the geometries that have been received. It\u2019s entirely up to you \u2013 provided that when all of your function\u2019s work is done, it returns a single JSON (or GeoJSON, or TopoJSON) object with a new set of geometries that your chart will then visualize.<\/p>\n<p>But how do you define a JavaScript function in Python? Using Highcharts Maps for Python, that is pretty simple: you create a <code>CallbackFunction<\/code> instance and supply it to the <code>.selector<\/code> property.<\/p>\n<p>There are two ways to do this. The easiest way is to pass your JavaScript function as a string to the <code>selector<\/code> keyword argument when creating your <code>AsyncMapData<\/code> instance. Highcharts Maps for Python will automatically take that string and convert it to a <code>CallbackFunction<\/code> instance:<\/p>\n<pre>from highcharts_maps.options.series.data.map_data\r\nimport AsyncMapData\r\nfrom highcharts_maps.utility_classes.fetch_configuration\r\nimport FetchConfiguration\r\n# Set the chart\u2019 s map data, configured to load asynchronously\r\nmy_map_data = AsyncMapData(url = 'https:\/\/www.my-map-data-url.dev\/map-data.topo.json',\r\n  selector = \"\"\r\n  \"function (topology) { \r\n  ...\r\n  return newTopology;\r\n}\r\n\"\"\r\n\")<\/pre>\n<p>As you can see, in the example above we\u2019re just passing a JavaScript function as a string to the <code>selector<\/code> argument. That function takes one argument: <code>topology<\/code> (the name matters) and it returns one object (its name does not matter, but we called it newTopology just to differentiate).<\/p>\n<p><i><b>Tip<\/b><br \/>\n<b>Best practice<\/b>: When supplying JavaScript code as strings to Highcharts Maps for Python, we recommend that you wrap the string in three double quotes, rather than a more conventional single quote, or even the sometimes seen double-quote. This is because by wrapping your string in three double quotes you will likely be able to avoid any escape characters in your JavaScript, making it much more readable and maintainable.<\/i><\/p>\n<p>We find that this approach is the easiest way to do it, since Highcharts Maps for Python does the heavy lifting for you. But if you want to create a CallbackFunction instance manually, you can do so as well:<\/p>\n<pre>from highcharts_maps.options.series.data.map_data\r\nimport AsyncMapData\r\nfrom highcharts_maps.utility_classes.javascript_functions\r\nimport CallbackFunction\r\n# Define your CallbackFunction instance\r\nmy_selector = CallbackFunction(arguments = ['topology'],\r\n    body = \"\"\r\n    \"\r\n    ...\r\n    return newTopology;\r\n    \"\"\r\n    \")\r\n    # Set the chart\u2019 s map data, configured to load asynchronously my_map_data = AsyncMapData(url = 'https:\/\/www.my-map-data-url.dev\/map-data.topo.json',\r\n      selector = my_selector)<\/pre>\n<p>The code above is equivalent to the first code sample provided \u2013 just in this case we are manually creating a <code>CallbackFunction<\/code> instance.<\/p>\n<p>And that\u2019s it! You\u2019ve now got your map visualizations loading and managing your geographies asynchronously in your client-side environment.<\/p>\n<h2>Visualizing Your Visualizations<\/h2>\n<p>Now when you call your <code>Chart<\/code> instance\u2019s <code>.to_js_literal()<\/code> method, Highcharts Maps for Python will generate several JavaScript statements:<\/p>\n<ol>\n<li>The first will issue an asynchronous <code>fetch()<\/code> call to download your map geometry.<\/li>\n<li>The second will \u2013 if your <code>AsyncMapData<\/code> instance is using a <code>selector<\/code> function \u2013 run your selector function on the downloaded map data.<\/li>\n<li>And the last one will actually visualize your chart, supplying the relevant map data to it as configured.<\/li>\n<\/ol>\n<p>And that\u2019s it!<\/p>\n<h2>More Resources<\/h2>\n<p>The above tutorial is just a really simple example of how you can create rich visualizations with just a handful of method calls using Highcharts for Python. But the library offers so much more! We recommend you take a look at the following additional resources which you may find useful:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/using-highcharts-for-python-basic-tutorial\" target=\"_blank\" rel=\"noopener\">Highcharts for Python: Tutorials<\/a><\/li>\n<li><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/highcharts-maps-python-basic-tutorial\" target=\"_blank\" rel=\"noopener\">Using Highcharts Maps for Python &#8211; Basic Tutorial <\/a><\/li>\n<li><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/exporting-static-charts-highcharts-python\" target=\"_blank\" rel=\"noopener\">Exporting Static Charts using Highcharts for Python<\/a><\/li>\n<li><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/templating-and-shared-options-highcharts-python\" target=\"_blank\" rel=\"noopener\">Using Templating and Shared Options in Highcharts for Python <\/a><\/li>\n<li><a href=\"https:\/\/maps-docs.highchartspython.com\/en\/latest\/\" target=\"_blank\" rel=\"noopener\"> Highcharts for Python: API Reference Documentation<\/a><\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h2><strong>Related posts<\/strong><\/h2>\n<ul>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/us-map-of-top-100-cities-using-highcharts\/\">US map of top 100 cities using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/visualizing-geospatial-data-with-highcharts-maps\/\">Visualizing geospatial data with Highcharts Maps<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/maps-with-latitude-longitude-using-highcharts\/\">Maps with latitude longitude using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/choropleth-map-examples-using-highcharts\/\">Choropleth map examples using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/inspirations\/javascript-maps-with-highcharts\/\">JavaScript maps with Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/inspirations\/map-library-by-highcharts\/\">Map library by Highcharts<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A step-by-step tutorial to learn how to use Asynchronous Map Data with python and Highcharts Maps<\/p>\n","protected":false},"author":273,"featured_media":23579,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"meta_title":"","meta_description":"","hc_selected_options":[],"footnotes":""},"categories":[1105],"tags":[876,885],"coauthors":[983],"class_list":["post-23464","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-integration","tag-highcharts-maps","tag-python"],"_links":{"self":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/23464","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/users\/273"}],"replies":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/comments?post=23464"}],"version-history":[{"count":2,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/23464\/revisions"}],"predecessor-version":[{"id":26013,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/23464\/revisions\/26013"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/23579"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=23464"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=23464"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=23464"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=23464"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}