is a powerful open source geospatial analysis tool for large-scale data sets.
Alternatives To
Project NameStarsDownloadsRepos Using ThisPackages Using ThisMost Recent CommitTotal ReleasesLatest ReleaseOpen IssuesLicenseLanguage
Deck.gl10,9012801312 days ago553September 16, 2022219mitJavaScript
WebGL2 powered visualization framework
Kepler.gl9,407315a day ago15September 16, 2021558mitTypeScript is a powerful open source geospatial analysis tool for large-scale data sets.
L73,0712425 days ago475September 20, 2022113mitTypeScript
🌎 Large-scale WebGL-powered Geospatial Data Visualization analysis engine
6 days ago21mitPython
A Python package for interactive mapping with Google Earth Engine, ipyleaflet, and ipywidgets.
4 days ago5mitPython
A Python package for interactive mapping and geospatial analysis with minimal coding in a Jupyter environment
Lets Plot87513 days ago44June 20, 202293mitKotlin
An open-source plotting library for statistical data.
Leaflet Dvf651
45 years ago4February 16, 201758mitJavaScript
Leaflet Data Visualization Framework
Streamlit Geospatial617
2 months ago2mitPython
A multi-page streamlit app for geospatial
4 months ago23June 09, 202233apache-2.0Python
Build & deploy geospatial applications quick and easy.
Kaggle Talkingdata Visualization326
6 years ago2JavaScript
Source code for blog post: Interactive Data Visualization of Geospatial Data using D3.js, DC.js, Leaflet.js and Python
Alternatives To
Select To Compare

Alternative Project Comparisons

version build stars MIT License Fossa | Website | Demo App | Docs Demo is a data-agnostic, high-performance web-based application for visual exploration of large-scale geolocation data sets. Built on top of Mapbox GL and, can render millions of points representing thousands of trips and perform spatial aggregations on the fly. is also a React component that uses Redux to manage its state and data flow. It can be embedded into other React-Redux applications and is highly customizable. For information on how to embed in your app take a look at this step-by-step tutorial on



Use Node 10.15.0 or above, older node versions have not been supported/ tested. For best results, use nvm nvm install.


Install node (> 10.15.0), yarn, and project dependencies

npm install --save
// or
yarn add is built upon mapbox. You will need a Mapbox Access Token to use it.

If you don't use a module bundler, it's also fine. npm package includes precompiled production UMD builds in the umd folder. You can add the script tag to your html file as it follows:

<script src="" />

or if you would like, you can load a specific version

<script src="[email protected]/umd/keplergl.min.js" />


Take a look at the development guide to develop locally.

Basic Usage

Here are the basic steps to import into your app. You also take a look at the examples folder. Each example in the folder can be installed and run locally.

1. Mount reducer uses Redux to manage its internal state, along with react-palm middleware to handle side effects.

You need to add taskMiddleware of react-palm to your store too. We are actively working on a solution where react-palm will not be required, however it is still a very lightweight side effects management tool that is easier to test than react-thunk.

import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import keplerGlReducer from '';
import {enhanceReduxMiddleware} from '';

const initialState = {};
const reducers = combineReducers({
  // <-- mount reducer in your app
  keplerGl: keplerGlReducer,

  // Your other reducers here
  app: appReducer

// using createStore
export default createStore(
      /* Add other middlewares here */

Or if use enhancer:

// using enhancers
const initialState = {};
const middlewares = enhanceReduxMiddleware([
  // Add other middlewares here
const enhancers = [applyMiddleware(...middlewares)];

export default createStore(reducer, initialState, compose(...enhancers));

If you mount reducer in another address instead of keplerGl, or the reducer is not mounted at root of your state, you will need to specify the path to it when you mount the component with the getState prop.

Read more about Reducers.

2. Mount Component

import KeplerGl from '';

const Map = props => (


id (String, required)
  • Default: map

The id of this KeplerGl instance. id is required if you have multiple KeplerGl instances in your app. It defines the prop name of the KeplerGl state that is stored in the KeplerGl reducer. For example, the state of the KeplerGl component with id foo is stored in

In case you create multiple instances using the same id, the state defined by the entry will be overridden by the latest instance and reset to a blank state.

mapboxApiAccessToken (String, required*)
  • Default: undefined

By default, uses mapbox-gl.js to render its base maps. You can create a free account at mapbox and create a token at

If you replaced default map styles with your own, and they are not Mapbox styles. mapboxApiAccessToken will not be reuiqred.

Read more about Custom Map Styles.

getState (Function, optional)
  • Default: state => state.keplerGl

The path to the root keplerGl state in your reducer.

width (Number, optional)
  • Default: 800

Width of the KeplerGl UI.

height (Number, optional)
  • Default: 800
appName (String, optional)
  • Default: Kepler.Gl

App name displayed in side panel header

version (String, optional)
  • Default: v1.0

version displayed in side panel header

onSaveMap (Function, optional)
  • Default: undefined

Action called when click Save Map Url in side panel header.

onViewStateChange (Function, optional)
  • Default: undefined
  • Parameter: viewState - An updated view state object containing parameters such as longitude, latitude, zoom etc

Action triggered when map viewport is updated.

getMapboxRef(mapbox, index) (Function, optional)
  • Default: undefined

Function called when KeplerGL adds or removes a MapContainer component having an inner Mapbox map.

The mapbox argument is an InteractiveMap when added or null when removed.

The index argument is 0 for a single map or 1 for an additional map (since KeplerGL supports an optional split map view).

actions (Object, optional)
  • Default: {}

Actions creators to replace default action creator. Only use custom action when you want to modify action payload.

mint (Boolean, optional)
  • Default: true

Whether to load a fresh empty state when component is mounted. when parse mint: true component will always load a fresh state when re-mount the same component, state inside this component will be destroyed once its unmounted. By Parsing mint: false will keep the component state in the store even when it is unmounted, and use it as initial state when re-mounted again. This is useful when mounting in a modal, and keep the same map when re-open.

Read more about Components.

theme (Object | String, optional)
  • default: null

One of "dark", "light" or "base" You can pass theme name or object used to customize style. provide an 'light' theme besides the default 'dark' theme. When pass in a theme object will use the value passed as input to override values from theme.

Read more about Custom Theme

mapboxApiUrl (String, optional)

  • Default:

If you are using your own mapbox tile server, you can pass in your own tile server api url.

mapStylesReplaceDefault (Boolean, optional)

  • Default: false provide 4 map styles to choose from. Pass true if you want to supply your own mapStyles. See Below.

mapStyles (Array, optional)

  • Default: []

You can supply additional map styles to be displayed in map style selection panel. By default, additional map styles will be added to default map styles. If pass mapStylesReplaceDefault: true, they will replace the default ones. will attempt to group layers of your style based on its id naming convention and use it to allow toggle visibility of base map layers. Supply your own layerGroups to override default for more accurate layer grouping.

Each mapStyles should has the following properties:

  • id (String, required) unique string that should not be one of these reserved dark light muted. muted_night
  • label (String, required) name to be displayed in map style selection panel
  • url (String, required) mapbox style url or a url pointing to the map style json object written in Mapbox GL Style Spec.
  • icon (String, optional) image icon of the style, it can be a url, or an image data url
  • layerGroups (Array, optional)
const mapStyles = [
    id: 'my_dark_map',
    label: 'Dark Streets 9',
    url: 'mapbox://styles/mapbox/dark-v9',
    icon: `${apiHost}/styles/v1/mapbox/dark-v9/static/-122.3391,37.7922,9.19,0,0/400x300?access_token=${accessToken}&logo=false&attribution=false`,
    layerGroups: [
        slug: 'label',
        filter: ({id}) => id.match(/(?=(label|place-|poi-))/),
        defaultVisibility: true
        // adding this will keep the 3d building option
        slug: '3d building',
        filter: () => false,
        defaultVisibility: false

Read more about Custom Map Styles.

initialUiState (object, optional)

  • Default: undefined

Intial UI State applied to uiState reducer, value will be shallow merged with default INITIAL_UI_STATE

localeMessages (object, optional)

  • Default: undefined Modify default translation or add new translation

Read more about Localization.

3. Dispatch custom actions to keplerGl reducer.

One advantage of using the reducer over React component state to handle keplerGl state is the flexibility to customize its behavior. If you only have one KeplerGl instance in your app or never intend to dispatch actions to KeplerGl from outside the component itself, you don’t need to worry about forwarding dispatch and can move on to the next section. But life is full of customizations, and we want to make yours as enjoyable as possible.

There are multiple ways to dispatch actions to a specific KeplerGl instance.

  • In the root reducer, with reducer updaters.

Each action is mapped to a reducer updater in You can import the reducer updater corresponding to a specific action, and call it with the previous state and action payload to get the updated state. e.g. updateVisDataUpdater is the updater for ActionTypes.UPDATE_VIS_DATA (take a look at each reducer reducers/vis-state.js for action to updater mapping). Here is an example how you can listen to an app action QUERY_SUCCESS and call updateVisDataUpdater to load data into Kepler.Gl.

import keplerGlReducer, {visStateUpdaters} from '';

// Root Reducer
const reducers = combineReducers({
  keplerGl: keplerGlReducer,

  app: appReducer

const composedReducer = (state, action) => {
  switch (action.type) {
    case 'QUERY_SUCCESS':
      return {
        keplerGl: {

          // 'map' is the id of the keplerGl instance
          map: {
            visState: visStateUpdaters.updateVisDataUpdater(
              {datasets: action.payload}
  return reducers(state, action);

export default composedReducer;

Read more about using updaters to modify state

  • Using redux connect

You can add a dispatch function to your component that dispatches actions to a specific keplerGl component, using connect.

// component
import KeplerGl from '';

// action and forward dispatcher
import {toggleFullScreen, forwardTo} from '';
import {connect} from 'react-redux';

const MapContainer = props => (
    <button onClick={() => props.keplerGlDispatch(toggleFullScreen())}/>

const mapStateToProps = state => state
const mapDispatchToProps = (dispatch, props) => ({
 keplerGlDispatch: forwardTo(‘foo’, dispatch)

export default connect(
  • Wrap action payload

You can also simply wrap an action into a forward action with the wrapTo helper

// component
import KeplerGl from '';

// action and forward dispatcher
import {toggleFullScreen, wrapTo} from '';

// create a function to wrapper action payload to 'foo'
const wrapToMap = wrapTo('foo');
const MapContainer = ({dispatch}) => (
    <button onClick={() => dispatch(wrapToMap(toggleFullScreen())} />

Read more about forward dispatching actions

4. Customize style. implements css styling using Styled-Components. By using said framework offers the ability to customize its style/theme using the following approaches:

  • Passing a Theme prop
  • Styled-Components ThemeProvider

The available properties to customize are listed here theme.

Custom theme example.

Passing a Theme prop.

You can customize theme by passing a theme props to react component as it follows:

const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'

return (

As you can see the customTheme object defines certain properties which will override default style rules.

Styled-Components Theme Provider.

In order to customize theme using ThemeProvider you can simply wrap using ThemeProvider as it follows:

import {ThemeProvider} from 'styled-components';

const white = '#ffffff';
const customTheme = {
  sidePanelBg: white,
  titleTextColor: '#000000',
  sidePanelHeaderBg: '#f7f7F7',
  subtextColorActive: '#2473bd'

return (
  <ThemeProvider theme={customTheme}>

5. Render Custom UI components.

Everyone wants the flexibility to render custom components. has a dependency injection system that allow you to inject components to KeplerGl replacing existing ones. All you need to do is to create a component factory for the one you want to replace, import the original component factory and call injectComponents at the root component of your app where KeplerGl is mounted. Take a look at examples/demo-app/src/app.js and see how it renders a custom side panel header in

import {injectComponents, PanelHeaderFactory} from '';

// define custom header
const CustomHeader = () => <div>My app</div>;
const myCustomHeaderFactory = () => CustomHeader;

// Inject custom header into, replacing default
const KeplerGl = injectComponents([
  [PanelHeaderFactory, myCustomHeaderFactory]

// render KeplerGl, it will render your custom header instead of the default
const MapContainer = () => (
    <KeplerGl id="foo" />

Using withState helper to add reducer state and actions to customized component as additional props.

import {
} from '';
import {visStateLens} from '';

// custom action wrap to mounted instance
const addTodo = text =>
  wrapTo('map', {
    type: 'ADD_TODO',

// define custom header
const CustomHeader = ({visState, addTodo}) => (
  <div onClick={() => addTodo('hello')}>{`${
  } dataset loaded`}</div>

// now CustomHeader will receive `visState` and `addTodo` as additional props.
const myCustomHeaderFactory = () =>
    // keplerGl state lenses
    // customMapStateToProps
    // actions

Read more about replacing UI component

6. How to add data to map

To interact with a instance and add new data to it, you can dispatch the addDataToMap action from anywhere inside your app. It adds a dataset or multiple datasets to a instance and updates the full configuration (mapState, mapStyle, visState).


  • data Object *required

    • datasets (Array<Object> | Object) *required datasets can be a dataset or an array of datasets Each dataset object needs to have info and data property.

      • Object -info of a dataset
        • string id of this dataset. If config is defined, id should matches the dataId in config.
        • string A display name of this dataset
      • Object *required The data object, in a tabular format with 2 properties fields and rows
        • Array<Object> *required Array of fields,
          • string *required Name of the field,
        • Array<Array> *required Array of rows, in a tabular format with fields and rows
    • options Object

      • options.centerMap boolean default: true if centerMap is set to true will place the map view within the data points boundaries
      • options.readOnly boolean default: false if readOnly is set to true the left setting panel will be hidden
      • options.keepExistingConfig boolean default: false whether to keep exiting map config, including layers, filters and splitMaps.
  • config Object this object will contain the full instance configuration {mapState, mapStyle, visState} provides an easy API KeplerGlSchema.getConfigToSave to generate a json blob of the current kepler instance configuration.


// app.js
import {addDataToMap} from '';

const sampleTripData = {
  fields: [
    {name: 'tpep_pickup_datetime', format: 'YYYY-M-D HⓂ️s', type: 'timestamp'},
    {name: 'pickup_longitude', format: '', type: 'real'},
    {name: 'pickup_latitude', format: '', type: 'real'}
  rows: [
    ['2015-01-15 19:05:39 +00:00', -73.99389648, 40.75011063],
    ['2015-01-15 19:05:39 +00:00', -73.97642517, 40.73981094],
    ['2015-01-15 19:05:40 +00:00', -73.96870422, 40.75424576]

const sampleConfig = {
  visState: {
    filters: [
        id: 'me',
        dataId: 'test_trip_data',
        name: 'tpep_pickup_datetime',
        type: 'timeRange',
        view: 'enlarged'

    datasets: {
      info: {
        label: 'Sample Taxi Trips in New York City',
        id: 'test_trip_data'
      data: sampleTripData
    option: {
      centerMap: true,
      readOnly: false
    config: sampleConfig

Read more about addDataToMap and Saving and loading maps with schema manager.

Popular Geospatial Projects
Popular Data Visualization Projects
Popular Mapping Categories
Related Searches

Get A Weekly Email With Trending Projects For These Categories
No Spam. Unsubscribe easily at any time.
Data Visualization