Address Search
Search for places by name and display results on the map Each library has its own approach: here's how they compare.
Quick Recommendations
Leaflet — The right choice when you want a lightweight geocoding search input with autocomplete using the MapTiler Geocoding API and DOM controls.
MapLibre GL JS — Makes the most sense when address search results should integrate with MapLibre's source/layer model for custom result rendering.
OpenLayers — A strong fit when geocoding must work alongside OGC feature layers and OpenLayers' projection system.
MapTiler SDK — A strong choice for the simplest integration: the SDK includes built-in geocoding helpers that work with the configured API key.
At a Glance
| Leaflet | MapLibre | OpenLayers | SDK | |
|---|---|---|---|---|
| Coordinates | [lat, lng] | [lng, lat] | fromLonLat([lng, lat]) | [lng, lat] |
| Rendering | DOM + Canvas (2D) | WebGL (GPU, 60fps) | Canvas + WebGL | WebGL (GPU, 60fps) |
| Bundle size | ~42 KB gzipped | ~250 KB gzipped | ~290 KB gzipped (tree-shakeable) | ~280 KB gzipped (includes MapLibre) |
| Learning curve | Easiest (simple API, great tutorials) | Moderate (source/layer model, expressions) | Steepest (projections, OGC standards, verbose API) | Easy (MapLibre API with convenience helpers) |
| 3D support | No native 3D (2D only) | Full: terrain, fill-extrusion, globe, sky | Limited: WebGL layers, no native globe | Full (same as MapLibre) |
| Code lines | 32 | 37 | 34 | 35 |
Code Snippets
Click a library to expand its code. Each snippet shows only the core logic: the scaffold handles HTML boilerplate.
Leaflet32 linesShow code
const map = L.map('map').setView([48.8566, 2.3522], 5);
L.tileLayer('https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', {
tileSize: 256,
attribution: '© <a href="https://www.maptiler.com/">MapTiler</a> © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
let marker, timeout;
const input = document.getElementById('search-box');
const results = document.getElementById('results');
input.addEventListener('input', () => {
clearTimeout(timeout);
const q = input.value.trim();
if (q.length < 3) { results.style.display = 'none'; return; }
timeout = setTimeout(async () => {
const res = await fetch('https://api.maptiler.com/geocoding/' + encodeURIComponent(q) + '.json?key=YOUR_MAPTILER_KEY&limit=5');
const data = await res.json();
results.innerHTML = '';
results.style.display = data.features.length ? 'block' : 'none';
data.features.forEach(f => {
const div = document.createElement('div');
div.textContent = f.place_name;
div.onclick = () => {
const [lng, lat] = f.center;
if (marker) marker.remove();
marker = L.marker([lat, lng]).addTo(map).bindPopup(f.place_name).openPopup();
map.setView([lat, lng], 14);
results.style.display = 'none';
input.value = f.place_name;
};
results.appendChild(div);
});
}, 300);
});MapLibre GL JS37 linesShow code
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets-v4/style.json?key=YOUR_MAPTILER_KEY',
center: [14.42, 50.08],
zoom: 5
});
let marker, timeout;
const input = document.getElementById('search-box');
const results = document.getElementById('results');
input.addEventListener('input', () => {
clearTimeout(timeout);
const q = input.value.trim();
if (q.length < 3) { results.style.display = 'none'; return; }
timeout = setTimeout(async () => {
const res = await fetch('https://api.maptiler.com/geocoding/' + encodeURIComponent(q) + '.json?key=YOUR_MAPTILER_KEY&limit=5');
const data = await res.json();
results.innerHTML = '';
results.style.display = data.features.length ? 'block' : 'none';
data.features.forEach(f => {
const div = document.createElement('div');
div.textContent = f.place_name;
div.onclick = () => {
const [lng, lat] = f.center;
if (marker) marker.remove();
marker = new maplibregl.Marker({ color: '#2196F3' })
.setLngLat([lng, lat])
.setPopup(new maplibregl.Popup().setHTML('<b>' + f.place_name + '</b>'))
.addTo(map);
marker.togglePopup();
map.flyTo({ center: [lng, lat], zoom: 14 });
results.style.display = 'none';
input.value = f.place_name;
};
results.appendChild(div);
});
}, 300);
});OpenLayers34 linesShow code
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', attributions: '© <a href="https://www.maptiler.com/copyright/">MapTiler</a>' }) })
],
view: new ol.View({ center: ol.proj.fromLonLat([2.3522, 48.8566]), zoom: 5 })
});
var marker = new ol.layer.Vector({ source: new ol.source.Vector(), style: new ol.style.Style({ image: new ol.style.Circle({ radius: 8, fill: new ol.style.Fill({ color: '#e63946' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) }) }) });
map.addLayer(marker);
var input = document.getElementById('search-input');
var resultsDiv = document.getElementById('results');
input.addEventListener('input', function() {
var q = input.value.trim();
if (q.length < 3) { resultsDiv.style.display = 'none'; return; }
fetch('https://api.maptiler.com/geocoding/' + encodeURIComponent(q) + '.json?key=YOUR_MAPTILER_KEY')
.then(function(r) { return r.json(); })
.then(function(data) {
resultsDiv.innerHTML = '';
resultsDiv.style.display = data.features.length ? 'block' : 'none';
data.features.forEach(function(f) {
var div = document.createElement('div');
div.textContent = f.place_name;
div.style.cssText = 'padding:8px 12px;cursor:pointer;border-bottom:1px solid #eee;';
div.onclick = function() {
marker.getSource().clear();
marker.getSource().addFeature(new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat(f.center)) }));
map.getView().animate({ center: ol.proj.fromLonLat(f.center), zoom: 14 });
resultsDiv.style.display = 'none';
input.value = f.place_name;
};
resultsDiv.appendChild(div);
});
});
});MapTiler SDK35 linesShow code
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
container: 'map',
style: maptilersdk.MapStyle.STREETS,
center: [2.3522, 48.8566],
zoom: 5
});
let marker, timeout;
const input = document.getElementById('search-box');
const results = document.getElementById('results');
input.addEventListener('input', () => {
clearTimeout(timeout);
const q = input.value.trim();
if (q.length < 3) { results.style.display = 'none'; return; }
timeout = setTimeout(async () => {
const res = await fetch('https://api.maptiler.com/geocoding/' + encodeURIComponent(q) + '.json?key=YOUR_MAPTILER_KEY&limit=5');
const data = await res.json();
results.innerHTML = '';
results.style.display = data.features.length ? 'block' : 'none';
data.features.forEach(f => {
const div = document.createElement('div');
div.textContent = f.place_name;
div.onclick = () => {
const [lng, lat] = f.center;
if (marker) marker.remove();
marker = new maptilersdk.Marker({ color: '#9C27B0' }).setLngLat([lng, lat]).addTo(map);
new maptilersdk.Popup().setLngLat([lng, lat]).setHTML('<b>' + f.place_name + '</b>').addTo(map);
map.flyTo({ center: [lng, lat], zoom: 14 });
results.style.display = 'none';
input.value = f.place_name;
};
results.appendChild(div);
});
}, 300);
});Things to Know
Implementation-specific details that matter for address search.
Uses the MapTiler Geocoding API directly via fetch(); the search UI and result list must be built manually or with a control plugin.
Can use @maptiler/geocoding-control for a drop-in search widget, or call the Geocoding API directly and place results as markers.
Geocoding results return [lng, lat] which must be transformed to the map projection with ol.proj.fromLonLat().
The SDK's built-in maptilersdk.geocoding namespace provides typed geocoding methods; GeocodingControl is in a separate package.
Which Library to Use?
Add an autocomplete address search dropdown to a Leaflet map using the MapTiler Geocoding API.
The right choice when you want a lightweight geocoding search input with autocomplete using the MapTiler Geocoding API and DOM controls.
Search for places by name using the MapTiler Geocoding API and display results on a MapLibre GL JS map.
Makes the most sense when address search results should integrate with MapLibre's source/layer model for custom result rendering.
Search for places using the MapTiler Geocoding API and display results on an OpenLayers map.
A strong fit when geocoding must work alongside OGC feature layers and OpenLayers' projection system.
Search for a place name and display the result on the map using the MapTiler Geocoding API and SDK.
A strong choice for the simplest integration: the SDK includes built-in geocoding helpers that work with the configured API key.
Build Maps with AI
Generate code like these examples using mapping library skills in your IDE.