This is the Leaflet version of our Address Autocomplete example. If you've seen the MapLibre GL tutorial, this follows the same UX pattern: users can search for an address and see it on an interactive map with a marker.
Try the live demo:
β‘οΈ View on CodePen
APIs used:
- Address Autocomplete API - real-time suggestions as users type
- Map Tiles - raster map tiles for Leaflet
- Map Marker Icon API - custom marker icons
π§ Table of Contents
- Leaflet vs MapLibre: Which Should You Choose?
- Set Up a Leaflet Map
- Add the Address Autocomplete Field
- Sync Selection with Leaflet Map
- Explore the Demo
- Summary
- FAQ
Leaflet vs MapLibre: Which Should You Choose?
Both Leaflet and MapLibre GL work seamlessly with Geoapify's Address Autocomplete. The choice depends on your project requirements:
| Feature | Leaflet | MapLibre GL |
|---|---|---|
| Tile format | Raster (PNG) | Vector (MVT) + WebGL |
| Bundle size | ~42 KB gzip | ~258 KB gzip |
| Coordinate order | [lat, lng] |
[lng, lat] (GeoJSON) |
| 3D/Terrain support | β No | β Yes |
| Zoom behavior | Raster tile zoom levels | Continuous vector re-rendering |
| Basemap styling | Swap tile layers | Full runtime control (style spec) |
| Learning curve | Easier | Moderate |
| Best for | Lightweight raster maps, UI overlays | Vector maps, smooth camera, 3D terrain |
Choose Leaflet if you need a lightweight solution with raster tiles and flexible overlay styling (markers, popups, polylines).
Choose MapLibre GL if you want vector maps with smooth camera animations, runtime basemap styling, or 3D terrain.
π See the MapLibre version: Add Address Autocomplete to a MapLibre GL Map with Click-to-Address Reverse Geocoding
The autocomplete widget code is identical for both libraries - only the map integration differs.
Step 1: Set Up a Leaflet Map
Start by loading Leaflet and initializing a map with Geoapify raster tiles.
Include Leaflet
Add the CSS and JavaScript from a CDN:
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<!-- Leaflet JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
Create the map container
<div id="map"></div>
Style it to fill the viewport:
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
}
Initialize the map
Create a Leaflet map with Geoapify tile layer:
const myAPIKey = "YOUR_API_KEY";
const map = L.map("map", { zoomControl: false }).setView(
[38.908838755401035, -77.02346458179596], // Washington DC
12
);
// Retina displays require different tile quality
const isRetina = L.Browser.retina;
const baseUrl = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey={apiKey}";
const retinaUrl = "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}@2x.png?apiKey={apiKey}";
L.tileLayer(isRetina ? retinaUrl : baseUrl, {
attribution: 'Powered by <a href="https://www.geoapify.com/" target="_blank">Geoapify</a> | Β© OpenMapTiles Β© OpenStreetMap contributors',
apiKey: myAPIKey,
maxZoom: 20
}).addTo(map);
// Add zoom control to bottom-right
L.control.zoom({ position: "bottomright" }).addTo(map);
Leaflet uses raster (PNG) tiles, while MapLibre uses vector tiles. Geoapify provides both formats. The @2x tiles are for retina displays.
π API Key: Sign up at geoapify.com to get a free API key.
A Leaflet map initialized with Geoapify raster tiles.
Step 2: Add the Address Autocomplete Field
The autocomplete setup is identical to the MapLibre example.
Include the Geocoder Autocomplete library
<!-- Geoapify Geocoder Autocomplete CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@geoapify/geocoder-autocomplete@3.0.1/styles/minimal.css" />
<!-- Geoapify Geocoder Autocomplete JS -->
<script src="https://cdn.jsdelivr.net/npm/@geoapify/geocoder-autocomplete@3.0.1/dist/index.min.js"></script>
Create the autocomplete container
Position it over the map:
<div class="autocomplete-panel">
<div id="autocomplete" class="autocomplete-container"></div>
</div>
.autocomplete-panel {
position: absolute;
top: 10px;
left: 10px;
width: 400px;
z-index: 1002;
}
Initialize the autocomplete widget
const autocompleteInput = new autocomplete.GeocoderAutocomplete(
document.getElementById("autocomplete"),
myAPIKey,
{ /* options */ }
);
The GeocoderAutocomplete widget works the same way regardless of which map library you use.
The autocomplete dropdown appears as the user types.
Step 3: Sync Selection with Leaflet Map
When the user selects an address, pan the map and place a marker.
Create a custom marker icon
Use the Geoapify Map Marker Icon API to generate a custom pin:
const markerIcon = L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=%232ea2ff&size=large&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [38, 56],
iconAnchor: [19, 51],
popupAnchor: [0, -60]
});
The iconAnchor defines which point of the icon corresponds to the marker's coordinates. For a pin icon, this should be near the bottom tip.
Handle the select event
let marker;
autocompleteInput.on("select", (location) => {
// Remove existing marker
if (marker) {
marker.remove();
}
if (location) {
// Add marker at the selected location
marker = L.marker([location.properties.lat, location.properties.lon], {
icon: markerIcon
}).addTo(map);
// Pan to the selected location
map.panTo([location.properties.lat, location.properties.lon]);
}
});
Note the coordinate order difference: Leaflet uses [lat, lon], while MapLibre uses [lon, lat].
After selecting an address, the map pans to the location and displays a marker.
Step 4: Explore the Demo
The live CodePen demo shows the complete implementation.
Try these flows
- Type an address β Select from dropdown β Map pans and marker appears
- Try different themes β Use the theme selector to switch light/dark modes
Theme switcher
The demo includes a theme selector that switches both the autocomplete style and map tiles:
const mapTiles = {
light: {
baseUrl: "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey={apiKey}",
retinaUrl: "https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}@2x.png?apiKey={apiKey}"
},
dark: {
baseUrl: "https://maps.geoapify.com/v1/tile/dark-matter-brown/{z}/{x}/{y}.png?apiKey={apiKey}",
retinaUrl: "https://maps.geoapify.com/v1/tile/dark-matter-brown/{z}/{x}/{y}@2x.png?apiKey={apiKey}"
}
};
Want reverse geocoding?
For click-to-address functionality (clicking on the map to get an address), see the MapLibre GL tutorial. The same Reverse Geocoding API call works with Leaflet - just replace the MapLibre marker code with Leaflet's L.marker().
π Try it in the interactive demo:
Summary
You've built a Leaflet map with address autocomplete:
- Leaflet map - raster tiles with retina support
- Address autocomplete - same Geoapify widget as MapLibre
- Custom marker - using the Marker Icon API
The main differences from MapLibre:
- Leaflet uses raster tiles (PNG), MapLibre uses vector tiles
- Coordinate order: Leaflet is
[lat, lon], MapLibre is[lon, lat] - Marker API:
L.marker()vsmaplibregl.Marker()
Useful links:
FAQ
Q: What's the difference between Leaflet and MapLibre?
A: Leaflet uses raster (PNG) tiles and is lighter weight. MapLibre uses vector tiles, supports 3D, and offers smoother zooming. Both work great with Geoapify APIs.
Q: How do I restrict autocomplete results to a specific country?
A: Use the filter option with countrycode, rect (bounding box), or circle parameters. For example: filter: { countrycode: ["us", "ca"] } limits results to USA and Canada. See the Address Autocomplete API docs.
Q: Can I use the autocomplete with React or Angular?
A: Yes. We provide dedicated wrapper libraries:
Q: How can I experiment with these APIs before coding?
A: Use our interactive playgrounds:
- Map Tiles Playground - try different map styles
- Marker Icon Playground - design custom markers
- Autocomplete Playground - test address search
Try It Now
π Open the Live Demo
Sign up at geoapify.com and get your free API key to start building Leaflet maps with address autocomplete.



Top comments (0)