Skip to main content

Browser Maps APIs

Which mapping library makes your use case simple and your budget sustainable?

Maps are one of the most common browser APIs to integrate — and one of the easiest to overpay for. The right choice depends on your job to be done, not the feature list.

Selection Checklist

Score each option against your requirements before committing.

#CriterionQuestionWeight
1Cost at scaleWhat's the monthly bill at 100K, 1M, 10M loads?Critical
2Tile sourceDo you need satellite imagery, street-level, or vector only?High
3InteractivityStatic pins or dynamic drawing, clustering, real-time updates?High
4Offline capabilityMust the map work without network?Medium
53D and terrainDo you need elevation, building extrusion, globe view?Medium
6GeocodingAddress-to-coordinates and reverse?Medium
7RoutingDirections, distance matrix, isochrones?Medium
8Data volumeRendering 100 markers or 100K? How does it handle density?High
9React integrationFirst-party React wrapper or community-maintained?Medium
10Self-hostingCan you host your own tile server?Low-High
11Bundle sizeHow much JS ships to the client?Medium
12LicensingOpen source, freemium, or enterprise-only?Critical

Comparison

DimensionGoogle MapsMapbox GL JSMapLibre GL JSLeafletDeck.glApple MapKit JS
LicenseProprietaryProprietary (BSL)BSD-3-ClauseBSD-2-ClauseMITProprietary
Cost$200 free/mo credit, then per-load50K free loads/mo, then per-loadFree (bring tiles)Free (bring tiles)Free (bring tiles)250K free/day
RenderingRaster + VectorWebGL vectorWebGL vectorCanvas/SVG rasterWebGL overlayWebGL vector
3D supportLimitedFull (terrain, extrusion)Full (terrain, extrusion)NoneFull (point clouds, arcs)Limited
React wrapper@vis.gl/react-google-mapsreact-map-glreact-map-glreact-leaflet@deck.gl/reactNone (vanilla JS)
Large datasetsModerateGood (clustering, expressions)Good (same engine)Poor above 10K markersExcellent (millions of points)Moderate
GeocodingBuilt-inBuilt-inBring your ownBring your ownN/A (viz layer)Built-in
RoutingBuilt-inBuilt-in (Directions API)Bring your ownBring your ownN/A (viz layer)Built-in (limited)
Offline tilesNoYes (mobile SDKs)Yes (PMTiles, MBTiles)Yes (with plugins)N/ANo
Bundle size~200KB (async)~210KB~210KB~40KB~300KB+~30KB (thin client)
Globe viewNoYesYesNoYesYes
Street ViewYesNoNoNoNoLook Around (limited)
Best forFamiliar UX, Places APICustom styling, production appsCost-sensitive, self-hostedLightweight, quick prototypesData viz, geospatial analysisApple ecosystem apps

Jobs To Be Done

Match your use case to the right tool.

JobBest FitWhy
Show a location on a contact pageGoogle Maps embed or LeafletSimplest integration, familiar UX
Property or asset map with filtersMapbox or MapLibreCustom styling, clustering, interactive popups
Real estate listing browserMapbox or MapLibre + react-map-glDraw-to-search, price overlays, smooth transitions
Fleet or device tracking (DePIN)MapLibre + Deck.glReal-time updates, thousands of moving points, no per-load cost
Route planning and navigationGoogle Maps or MapboxBuilt-in routing, traffic, turn-by-turn
Geospatial data visualizationDeck.gl + MapLibreHeatmaps, arcs, hex grids at scale
Offline field appMapLibre + PMTilesSelf-hosted vector tiles, zero API cost
Satellite imagery overlayGoogle Maps or MapboxHigh-res tile sets included
Custom branded map styleMapbox or MapLibreFull style spec control, design studio

React Integration

react-map-gl (Mapbox and MapLibre)

The standard React wrapper for GL-based maps. Works with both Mapbox and MapLibre by swapping the mapLib prop.

import Map, { Marker, Popup, NavigationControl } from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";

function PropertyMap({ listings }) {
return (
<Map
initialViewState={{ longitude: 174.77, latitude: -41.29, zoom: 12 }}
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_TOKEN}
mapStyle="mapbox://styles/mapbox/streets-v12"
>
<NavigationControl position="top-right" />
{listings.map((listing) => (
<Marker key={listing.id} longitude={listing.lng} latitude={listing.lat} />
))}
</Map>
);
}

Switch to MapLibre (zero cost)

import Map from "react-map-gl/maplibre";
import "maplibre-gl/dist/maplibre-gl.css";

<Map
initialViewState={{ longitude: 174.77, latitude: -41.29, zoom: 12 }}
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
/>;

Tile Sources

Free and paid tile providers for MapLibre and Leaflet.

ProviderTypeCostQuality
OpenStreetMapRasterFree (fair use)Good
CARTO basemapsVectorFreeGood
ProtomapsVector (PMTiles)Self-hosted, freeGood
Stadia MapsRaster + VectorFree tier, then paidGood
MaptilerVectorFree tier, then paidExcellent
MapboxVector50K free, then paidExcellent
GoogleRaster$200 credit, then paidExcellent

Decision Tree

Need Street View or Places API?
YES → Google Maps
NO ↓

Need custom styling + production quality?
YES ↓
Budget for per-load pricing?
YES → Mapbox GL JS
NO → MapLibre GL JS + free tiles
NO ↓

Visualizing large datasets (10K+ points)?
YES → Deck.gl + MapLibre base
NO ↓

Quick prototype or simple embed?
YES → Leaflet

Context

Questions

When does the cost of "free" open-source tiles exceed the cost of a managed service?

  • At what data volume does Leaflet's canvas renderer break down and WebGL become necessary?
  • If your map is the product (not a feature), does that change which library you choose?
  • What's the real cost of switching map providers after you've built custom styles and interactions?