Visualize LiDAR Point Clouds in the Browser with maplibre-gl-lidar
I am excited to share maplibre-gl-lidar, a new open-source MapLibre GL JS plugin for visualizing large-scale LiDAR point clouds directly in the browser. It handles LAS, LAZ, and COPC (Cloud Optimized Point Cloud) formats, supports data stored locally or hosted on the web, and comes with an interactive GUI for customizing visualization on the fly. It can render tens of millions of points smoothly, and it also works inside Jupyter Notebooks.
In this tutorial, I walk through the plugin’s features using the live demo viewer and show how to set it up on your own machine.
Video tutorial: Visualize LiDAR Point Clouds in the Browser with maplibre-gl-lidar
What You Will Need¶
A modern web browser (Chrome, Firefox, or Edge) to use the live demo
Node.js if you want to run or customize the viewer locally
Optionally, Docker for containerized deployment
Try the Live Demo¶
The fastest way to get started is the live demo viewer. It runs entirely in the browser with no server required (deployed on GitHub Pages).
Open the viewer.
Click Viewer from the demo options.
Select one of the sample datasets from the dropdown, or paste a URL to any COPC file hosted on the web.
The point cloud loads and renders instantly.
The first sample dataset (from Hobu, courtesy of Howard Butler) includes RGB attributes and contains over 10 million points.
Interact with the Point Cloud¶
Once a dataset is loaded, you can navigate the 3D scene:
Scroll to zoom in and out
Click and drag to pan
Ctrl + drag to rotate and tilt the view
The plugin uses HTTP range requests to stream COPC data on demand based on your viewport, so it does not download the entire file upfront.
Visualization Modes¶
The control panel on the right side lets you switch between four visualization modes:
Elevation¶
The default view. Points are colored by height using a graduated color ramp (blue for low elevation, yellow for high). By default, a 2nd-98th percentile clip is applied to remove extreme outliers. Turning off the percentile clip shows the raw range, which often appears too dark due to outlier values.
Intensity¶
A grayscale view based on the LiDAR return signal strength. Brighter areas indicate higher reflectance (e.g., concrete, rooftops), while darker areas indicate lower reflectance (e.g., vegetation, water).
Classification¶
Points are colored by their embedded classification labels. The legend shows all available classes (ground, water, low/medium/high vegetation, buildings, etc.), and you can toggle individual classes on and off. This is useful for isolating specific features, such as showing only ground points for terrain analysis or only buildings for urban modeling.
RGB¶
If the dataset includes red, green, and blue attributes per point, this mode renders a natural-color view that resembles aerial imagery. When you zoom in, you can see the individual colored points. Not all datasets have RGB attributes; if they are missing, the view falls back to elevation coloring.
Additional Controls¶
Point size¶
Adjust the slider to make points larger (smoother appearance) or smaller (more detailed). The default is 2. For zoomed-out views with many overlapping points, a smaller size works well.
Opacity¶
Control the transparency of the point cloud to see the basemap underneath.
Elevation filter¶
Slide the range handles to show only points within a specific elevation band. This is useful for slicing through the data vertically, for example, isolating a particular floor level or removing ground points to see only elevated features.
Z offset¶
LiDAR stores absolute elevation (meters above sea level), but the map renders relative to the ground. The plugin automatically calculates a Z offset to bring the points down to ground level. You can adjust this manually if the automatic calculation does not fit well.
Point picking¶
Enable point picking to inspect individual points. Hover over any point to see it highlighted in yellow and view its attributes: coordinates, elevation, intensity, classification, RGB values, and more.
Load Your Own Data¶
The viewer supports two ways to load custom data:
Paste a URL: Enter the URL of any COPC file hosted on the web.
Open from your computer: Click the open button to load a local LAS, LAZ, or COPC file. The data is read directly in the browser without uploading to any server.
You can load multiple datasets at once. Each one appears as a separate layer that can be toggled independently.
Jupyter Notebook Support¶
The plugin also works inside Jupyter Notebooks through the anymap-ts package. You can create a map, add a LiDAR layer, and interact with the same GUI controls, all within a notebook cell:
import anymap
m = anymap.Map()
m.add_lidar("path/to/pointcloud.copc.laz")
mAll the visualization features (elevation, intensity, classification, RGB, elevation filter, point picking) work the same way in the notebook environment.
Run the Viewer Locally¶
Using npm¶
git clone https://github.com/opengeos/maplibre-gl-lidar.git
cd maplibre-gl-lidar
npm install
npm run build
npm run devThis starts a local development server with the same viewer interface as the live demo.
Using Docker¶
docker pull ghcr.io/opengeos/maplibre-gl-lidar
docker run -p 8080:80 ghcr.io/opengeos/maplibre-gl-lidarOpen http://localhost:8080 in your browser.
Using npm as a dependency¶
If you want to integrate the plugin into your own web application:
npm install maplibre-gl-lidarThe package works with both TypeScript and React. See the examples in the repository for starter templates.
How It Works¶
Under the hood, the plugin uses:
copc.js for reading Cloud Optimized Point Cloud files with HTTP range requests
MapLibre GL JS for rendering
WebGPU acceleration (when available) for smooth performance with tens of millions of points
Automatic coordinate system transformation, so point clouds in any projection render correctly on the map
Resources¶
Live Demo: lidar
-viewer .gishub .org GitHub Repository: github
.com /opengeos /maplibre -gl -lidar npm Package: npmjs
.com /package /maplibre -gl -lidar
This is a new project with more features planned, including tighter integration with the anymap-ts package for notebook workflows. If you find it useful, please star the repository so more people can discover it. Feel free to open an issue or feature request on GitHub if you run into any problems or have ideas for improvements.