To create an interactive map for your website, load a basemap in a JavaScript map library such as MapLibre GL, then connect location APIs to the things users do: search, click, plan a route and explore. A static map only shows a place; an interactive map answers questions like "where is this address?", "what is this building?" and "what can I reach on foot in 15 minutes?". This guide builds that map in six steps, with real Geoapify requests and responses around the San Francisco Ferry Building. At the end, you'll find six working examples and a neutral comparison of map libraries, GIS platforms and no-code tools.
On this page
What Makes a Map Interactive?
An interactive map is a web map that responds to user input: it lets people search, click, measure and filter, and it changes what it shows based on their answers. Panning and zooming are the minimum. The interactions that make users stay are the ones that answer a location question for them.
Each of those interactions needs a data source behind it. The map library draws the map, while location APIs supply the addresses, routes, areas and places. The table below maps common interactions to the Geoapify API that serves each one and its cost in credits:
| User action | Geoapify API | What the user sees | Cost |
|---|---|---|---|
| Pans and zooms | Map Tiles | A styled basemap | 0.25 credits per tile |
| Types an address | Address Autocomplete | Suggestions, then a marker | 1 credit per request |
| Clicks a point | Reverse Geocoding | The nearest postal address | 1 credit per request |
| Clicks a building | Place Details | Name, website, opening hours, outline | 1 credit per 20 returned features (minimum 1) |
| Asks for directions | Routing | A route line, distance and time | 1 credit per pair of waypoints |
| Asks "what can I reach?" | Isoline | A travel-time polygon | 1 credit per 5 minutes of travel time |
| Looks for cafés or shops | Places | Markers or a list | 1 credit per 20 places |
The Free plan includes 3,000 credits per day. All of these APIs return GeoJSON, so you can draw their results with MapLibre GL, Leaflet or OpenLayers. If you're still deciding whether your site needs its own map at all, read why websites need their own interactive maps even though Google Maps exists.
Step 1: How Do You Add a Basemap to Your Website?
Every interactive map starts with a basemap: the background layer of streets, buildings, water and labels. You need two things for it: a map library that renders the map in the browser, and a map style or tile service that supplies the data.
Load a Geoapify vector style in MapLibre GL
MapLibre GL JS renders vector maps with WebGL and accepts a style.json URL. Geoapify provides a style file for each map style, for example osm-bright, positron, dark-matter or klokantech-basic:
import * as maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";
const map = new maplibregl.Map({
container: "map", // id of the map's <div>
style: "https://maps.geoapify.com/v1/styles/osm-bright/style.json?apiKey=YOUR_API_KEY",
center: [-122.3935, 37.7955], // [longitude, latitude]: San Francisco Ferry Building
zoom: 14
});
map.addControl(new maplibregl.NavigationControl());The style file contains the layers, fonts, maximum zoom and attribution, so the required "Powered by Geoapify" and OpenStreetMap credits appear on the map automatically. Vector styles can also be changed at runtime: How to Change the Style of a Map shows how to switch between a light and a dark theme with map.setStyle() or recolor single layers.
Raster tiles for Leaflet and OpenLayers
If your project already uses Leaflet, use the raster ZXY URL of the same style: https://maps.geoapify.com/v1/tile/osm-bright/{z}/{x}/{y}.png?apiKey=YOUR_API_KEY (use @2x.png for high-resolution screens). Vector tiles are rendered at 512×512 px, so an 800×600 px map needs about 4–9 vector tiles instead of 12–20 raster tiles of 256×256 px. That matters for cost, since every tile request costs 0.25 credits.
Not sure which library to pick? How to Choose Between MapLibre GL, Leaflet, and OpenLayers compares them by requirement. The Map Tiles Playground lets you preview all styles before you choose one.
Step 2: How Do Users Search for an Address on the Map?
Address search is the interaction users try first, and one that many maps still lack. The Address Autocomplete API returns suggestions while the user types, so they can pick a result instead of typing the full address. It has its own endpoint, separate from forward geocoding: /v1/geocode/autocomplete.
Request suggestions as the user types
Here, a user has typed "ferry building san" and the search is limited to the United States:
https://api.geoapify.com/v1/geocode/autocomplete?text=ferry%20building%20san&filter=countrycode:us&limit=3&apiKey=YOUR_API_KEYThe response is a GeoJSON FeatureCollection with one feature per suggestion. Simplified response (first of three suggestions):
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "San Francisco Ferry Building",
"formatted": "San Francisco Ferry Building, 1 The Embarcadero, San Francisco, CA 94111, United States of America",
"result_type": "amenity",
"lat": 37.7955487,
"lon": -122.3934746,
"rank": { "confidence": 0.9 },
"place_id": "…"
},
"geometry": { "type": "Point", "coordinates": [-122.3934746, 37.7955487] }
}
]
}All three suggestions are mapped objects of the same landmark with a confidence of 0.9, so show formatted in the dropdown and keep the place_id of the result the user picks. Useful parameters include type (for example city or postcode), filter, bias, lang and limit; see the Address Autocomplete API reference. Each request costs 1 credit.
Fly to the selected address
When the user picks a suggestion, add a marker and move the map to it:
const marker = new maplibregl.Marker();
function onSuggestionSelected(feature) {
const [lon, lat] = feature.geometry.coordinates;
marker.setLngLat([lon, lat]).addTo(map);
map.flyTo({ center: [lon, lat], zoom: 16 });
}You don't have to build the input field yourself: the @geoapify/geocoder-autocomplete package provides a ready-made field, and separate packages wrap it for React and Angular. For marker styles and icons, see How to Add Markers to a Map. Try your own queries in the Autocomplete Playground.
Step 3: What Should Happen When Users Click the Map?
A click should answer "what is here?". Two APIs answer two different versions of that question, and choosing the wrong one is a common source of confusing popups:
| Reverse Geocoding | Place Details (by coordinates) | |
|---|---|---|
| Question it answers | "What is the address here?" | "What is this object?" |
| Returns | The nearest address or place, with distance in metres | The most specific mapped object at the point: a place, building, area or water body |
| Typical fields | housenumber, street, postcode, formatted | name, categories, website, opening_hours, building outline |
| When nothing is at the point | Returns the nearest result and its distance | Returns an empty features array with HTTP 200 |
| Use for | Delivery forms, "drop a pin" address pickers | Info cards for buildings, shops and landmarks |
Get the address of a clicked point
Suppose a user clicks a spot near Union Square. The Reverse Geocoding API takes lat and lon as separate parameters:
https://api.geoapify.com/v1/geocode/reverse?lat=37.7882&lon=-122.4067&apiKey=YOUR_API_KEYSimplified response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"housenumber": "240",
"street": "Stockton Street",
"suburb": "Union Square",
"city": "San Francisco",
"state_code": "CA",
"postcode": "94108",
"formatted": "240 Stockton Street, San Francisco, CA 94108, United States of America",
"result_type": "building",
"distance": 11.379597999830525
}
}
]
}The address is 11 metres from the click, so it's safe to show it in a popup. In MapLibre GL, the click handler reads event.lngLat and opens a popup with the formatted address:
map.on("click", async (event) => {
const { lng, lat } = event.lngLat;
const url = `https://api.geoapify.com/v1/geocode/reverse?lat=${lat}&lon=${lng}&apiKey=YOUR_API_KEY`;
const { features } = await (await fetch(url)).json();
if (!features.length) return;
new maplibregl.Popup()
.setLngLat([lng, lat])
.setText(features[0].properties.formatted)
.addTo(map);
});Test any point in the Reverse Geocoding Playground.
Show details of a clicked building or place
For an info card, call the Place Details API with the clicked coordinates. A click inside the Ferry Building:
https://api.geoapify.com/v2/place-details?lat=37.7953&lon=-122.3932&apiKey=YOUR_API_KEYSimplified response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"feature_type": "details",
"name": "San Francisco Ferry Building",
"formatted": "San Francisco Ferry Building, 1 The Embarcadero, San Francisco, CA 94111, United States of America",
"categories": ["building", "building.commercial", "building.historic", "building.tourism", "building.transportation", "commercial", "commercial.shopping_mall", "public_transport", "public_transport.ferry", "tourism", "tourism.attraction", "tourism.sights", "wheelchair", "wheelchair.yes"],
"website": "https://www.ferrybuildingmarketplace.com/",
"opening_hours": "Mo-Fr 07:00-22:00; Sa 07:00-22:00; Su 07:00-22:00"
},
"geometry": { "type": "Polygon", "coordinates": ["…"] }
}
]
}The Polygon geometry is the building outline, so you can highlight the clicked building on the map. Keep in mind that a coordinate lookup returns the object at the point, not the nearest named place: a click about 55 metres away, at 37.7956, -122.3937, returns "Ferry Building Bike Rentals" (rental.bicycle) instead. Check categories before you render the card, and once the user confirms a place, use its place_id for later requests. How to Get Place Details by Place ID or Coordinates covers all lookup methods and edge cases.
Step 4: How Do You Draw a Route on the Map?
Once users can find two places, the next question is how to get from one to the other. The Routing API returns the route as GeoJSON together with distance, travel time and turn-by-turn instructions. A walking route from the Ferry Building to Union Square:
https://api.geoapify.com/v1/routing?waypoints=37.7955487,-122.3934746|37.7879363,-122.4075174&mode=walk&apiKey=YOUR_API_KEYNote the order: waypoints takes latitude,longitude pairs separated by |, while GeoJSON coordinates in the response are [longitude, latitude]. Simplified response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"mode": "walk",
"distance": 1610,
"distance_units": "meters",
"time": 1501.544,
"legs": [
{
"steps": [
{ "instruction": { "text": "Walk southwest on the walkway." } },
{ "instruction": { "text": "Continue on Market Street." } },
"… 21 more steps"
]
}
]
},
"geometry": { "type": "MultiLineString", "coordinates": ["…"] }
}
]
}The walk is 1.6 km and takes about 25 minutes (time is in seconds). To draw it, add the whole response as a GeoJSON source and style it as a line:
const route = await (await fetch(routeUrl)).json();
map.addSource("route", { type: "geojson", data: route });
map.addLayer({
id: "route-line",
type: "line",
source: "route",
paint: { "line-color": "#3366ff", "line-width": 5 }
});The same request works for drive, truck, bicycle, transit and other travel modes. A two-waypoint route costs 1 credit. For a complete example with markers and step-by-step instructions, follow the tutorial on drawing routes on a MapLibre GL map, or compare modes in the Routing Playground.
Step 5: How Do You Show Areas Reachable in 15 Minutes?
A travel-time area (also called an isochrone) shows everywhere a person can reach from a point within a given time. It answers questions a route can't: which neighborhoods are within a 15-minute walk of this office? or who lives within a 30-minute drive of our store? The Isoline API calculates these areas for drive, walk, bicycle, transit and the other routing modes.
Request a 15-minute walking area
For a time-based isoline, set type=time and range in seconds; range=900 is 15 minutes:
https://api.geoapify.com/v1/isoline?lat=37.7955487&lon=-122.3934746&type=time&mode=walk&range=900&apiKey=YOUR_API_KEYSimplified response:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"lat": 37.7955487,
"lon": -122.3934746,
"mode": "walk",
"type": "time",
"range": 900,
"id": "e18adad9394557b1d329bd64cfe82649"
},
"geometry": { "type": "MultiPolygon", "coordinates": ["…"] }
}
]
}Add the result as a GeoJSON source and draw it with a semi-transparent fill layer below your markers; How to Style GeoJSON Lines and Polygons has ready-made layer styles for MapLibre GL, Leaflet and OpenLayers. Keep the id: Step 6 uses it to search inside the area.
Costs and long calculations
Time-based isolines cost 1 credit per 5 minutes, so this 15-minute area costs 3 credits. When a calculation takes longer than usual, the API returns HTTP 202 with an empty FeatureCollection; keep the id and request the result again with https://api.geoapify.com/v1/isoline?id=<id>&apiKey=YOUR_API_KEY. You may cache or store calculated isolines on your side without restrictions. Try different modes and ranges in the Isoline Playground.
Step 6: How Do You Show Nearby Places?
Restaurants, fitness studios, schools and pharmacies are often the reason people open a map in the first place. The Places API returns points of interest by category, and you can limit the search to a circle, a rectangle, a city boundary or the travel-time area from Step 5.
Search inside the travel-time area
Pass the isoline id as filter=geometry:<id> and sort results by distance with bias=proximity:lon,lat. Unlike the Isoline API, bias and filter take longitude first:
https://api.geoapify.com/v2/places?categories=catering.cafe&filter=geometry:e18adad9394557b1d329bd64cfe82649&bias=proximity:-122.3934746,37.7955487&limit=20&apiKey=YOUR_API_KEYSimplified response, the first four of 20 results:
{
"type": "FeatureCollection",
"features": [
{ "properties": { "name": "A16", "categories": ["catering", "catering.cafe", "wheelchair", "wheelchair.yes"], "distance": 15 } },
{ "properties": { "name": "El Porteño", "categories": ["catering", "catering.cafe", "wheelchair", "wheelchair.yes"], "distance": 18 } },
{ "properties": { "name": "Tsar Nicolai Caviar", "categories": ["catering", "catering.cafe", "wheelchair", "wheelchair.yes"], "distance": 25 } },
{ "properties": { "name": "Blue Bottle Coffee", "categories": ["catering", "catering.cafe", "catering.cafe.coffee", "catering.cafe.coffee_shop"], "distance": 37 } }
]
}With limit=500, the same request returns all 68 cafés inside the 15-minute walking area; the farthest one is 967 metres from the Ferry Building in a straight line. Places requests cost 1 credit per 20 returned places, so the full list costs 4 credits. One caveat from the docs: if the Places API doesn't recognize the geometry ID, it ignores the filter without an error, so check that the results lie inside the polygon you draw. How to Find Places Within Walking Distance walks through the full workflow.
Load places for the current map view
On a map that users pan around, request places for the visible area instead. The rect filter takes west, south, east and north coordinates, which come straight from map.getBounds():
async function loadPlacesInView() {
const b = map.getBounds();
const rect = `${b.getWest()},${b.getSouth()},${b.getEast()},${b.getNorth()}`;
const url = `https://api.geoapify.com/v2/places?categories=catering.cafe&filter=rect:${rect}&limit=100&apiKey=YOUR_API_KEY`;
const places = await (await fetch(url)).json();
map.getSource("places").setData(places); // a GeoJSON source with a circle or symbol layer
}
map.on("moveend", loadPlacesInView);How to Show Places in the Current Map View has the same pattern for MapLibre GL, Leaflet and OpenLayers. You can browse categories and filters in the Places Playground.
What Do the Best Interactive Maps Look Like? Six Examples
The best interactive maps do one job well: they answer a specific location question in one or two clicks. Each example below was built with Geoapify APIs and an open-source map library, and each links to a guide with the code.
Address on map click
The map calls Reverse Geocoding where the user clicks, then fills an address form: name, house number, street, postcode, city, state and country. It's a common pattern for checkout and registration forms, where users can confirm their address by pointing at their building.
Address autocomplete above a map
An address field with suggestions sits above a Leaflet map of Washington, D.C.; choosing a suggestion moves the map and places a marker. The tutorial adds the whole widget to a WordPress page with Custom HTML blocks.
Multi-stop route on a MapLibre GL map
A route through four stops in western Switzerland is drawn as a blue line, with white dots at the positions of the turn-by-turn instructions. The tutorial shows how to turn the Routing API response into line and circle layers.
Public transport travel-time map
A 60-minute isochrone built with approximated public transit data covers most of Greater London and reaches out along rail lines to towns such as Watford, Slough and Gravesend. Maps like this are popular on real estate and travel websites.
Places by category in a city area
Places API results for one category appear as red markers in north-eastern Paris, with everything outside the city boundary greyed out. It's a starting point for store locators and "what's nearby" pages.
Delivery route optimization
Three trucks share pickups and deliveries in Stuttgart. Each route has its own color, numbered stops and a timeline below the map, and clicking a stop shows its address and orders. The routes come from the Route Planner API, which assigns stops to vehicles and puts them in order.
Library or No-Code Tool: Which Fits Your Interactive Map?
The six steps above assume you write JavaScript. That's the most flexible option, but not the only one: no-code map builders and GIS platforms can also publish interactive maps. The right choice depends on who maintains the map and how much custom behavior it needs.
| Option | Examples | Best for | Trade-offs |
|---|---|---|---|
| JavaScript map library + location APIs | MapLibre GL JS, Leaflet, OpenLayers | Custom interactions inside your own site or app: search, routing, filters, your own data | You write, host and maintain the code |
| No-code map builder | Mapifator, uMap, Google My Maps | Maps with pins, descriptions and photos, shared by link or embedded | Limited custom logic; features depend on the builder |
| GIS platform | ArcGIS Online, QGIS with the qgis2web plugin, Felt | Analysts publishing layers, attribute data and thematic maps | Learning curve; licensing and export options vary by platform |
Among the libraries, MapLibre GL suits vector styles and many data-driven layers, Leaflet suits simple raster maps with plugins, and OpenLayers suits GIS formats and projections. Our comparison of Leaflet, MapLibre GL and OpenLayers adds download trends and feature details. If you only need a map with pins and no code, start with a builder such as Mapifator.
Frequently Asked Questions
How do I make a map interactive on my website?
Render a basemap with a JavaScript library such as MapLibre GL or Leaflet, then connect APIs to user actions: Address Autocomplete for search, Reverse Geocoding or Place Details for clicks, Routing for directions, Isoline for travel-time areas and Places for nearby points of interest. Draw the GeoJSON results as layers on the map.
What is the best library for an interactive web map?
It depends on your hardest requirement. MapLibre GL is a strong choice for vector styles, runtime styling and many data-driven layers; Leaflet for simple raster maps and a mature plugin ecosystem; OpenLayers for GIS formats, projections and complex layer composition. See How to Choose Between MapLibre GL, Leaflet, and OpenLayers.
Which GIS is best for sharing interactive maps?
There is no single best tool. GIS platforms such as ArcGIS Online or Felt suit analysts who publish layers and attribute data, and QGIS can export web maps with the qgis2web plugin. No-code builders such as uMap or Mapifator are quicker for maps with pins. For custom behavior on your own website, a JavaScript map library with location APIs is the most flexible option.
What are the best interactive maps for a website?
The best interactive maps answer one location question quickly: an address picker, a store locator, a route planner, a travel-time map or a "what's nearby" map. See the six examples in this article, each with a tutorial and code, and the Geoapify Playgrounds to try the APIs behind them.
Can I use Geoapify maps for free on a commercial website?
Yes. The Free plan includes 3,000 credits per day and can be used for commercial websites and apps in production, as long as you stay within its limits and show the required Geoapify and data-source attribution. Geoapify map styles include the attribution when you load them with style.json. See commercial use on the Free plan.
Do I need Google Maps to build an interactive map?
No. Open-source libraries such as MapLibre GL JS, Leaflet and OpenLayers render the map, and Geoapify Map Tiles based on OpenStreetMap data supply the basemap. Geocoding, routing, isolines and places come from separate APIs that work with any of these libraries.
What is the difference between Reverse Geocoding and Place Details?
Reverse Geocoding returns the nearest address to a point, with its distance in metres. Place Details by coordinates returns the most specific mapped object at the point, such as a building, shop, neighborhood or water body, with fields like website and opening hours when they are mapped. Use Reverse Geocoding for address forms and Place Details for info cards. See How to Get Place Details by Place ID or Coordinates.

