Map Tiles API

The MapTiles API returns an embeddable HTML response to render maps based on either:

  • Tile Mode – Loads base map tiles for a given location and zoom level.
  • Point Mode – Loads map tiles with an address point (not a marker) visually highlighted at the given coordinates.

This API is ideal for integrating dynamic map views directly into your web applications.

🔑 Authentication

  • All requests must include your API key.
  • Header Example:
  • Authorization: X-Authorization-Token (Get your token HERE)

📥 Request Parameters

ParameterTypeRequiredDescription
ModeStringYes"tile" (for base map tiles) or "point" (for address point overlay)
LatFloatYesLatitude of the location
LongFloatYesLongitude of the location
zoom intyesZoom level (1 to 20)

🔧 Mode Details

🧩 Tile Mode (mode=tile)

  • Loads only the base map tiles centered around the given latitude and longitude.
  • No overlays or points are displayed.
  • Use this for showing general map areas or as a base layer.

📤 Sample Request


   curl --location 'https://naksha.latlong.ai/tiles?latitude=12.979450&longitude=77.590929&zoom=18&angle=45&style=light&pan=On&zoom_control=On'  

📦 Sample Response

<!DOCTYPE html> 

<html> 

    <head> 

        <title>Latlong Maptiles</title> 

        <style> 

        body, html { 

            height: 100%; 

            margin: 0; 

            padding: 0; 

            overflow: hidden; 

        } 

 

        #map { 

            height: 100%; 

            width: 100%; 

            position: relative; 

        } 

 

        .dialog-box { 

            position: absolute; 

            top: -50px; 

            left: 50%; 

            transform: translateX(-50%); 

            background-color: white; 

            padding: 10px; 

            border: 1px solid #ccc; 

            border-radius: 5px; 

            z-index: 1; 

            display: none; 

            width: auto; 

            white-space: nowrap; 

        } 

         

        .zoom-buttons { 

            position: absolute; 

            top: 10px; 

            left: 10px; 

            z-index: 1; 

        } 

         

        .pitch-button { 

            position: absolute; 

            top: 10px; 

            left: 50px; 

            z-index: 1; 

        } 

    </style> 

        <script src='https://api.mapbox.com/mapbox-gl-js/v2.4.1/mapbox-gl.js'></script> 

        <link href='https://api.mapbox.com/mapbox-gl-js/v2.4.1/mapbox-gl.css' rel='stylesheet' /> 

    </head> 

    <body> 

        <div id='map'></div> 

        <div class='dialog-box' id='dialogBox'> 

            <!-- Description content goes here --> 

     

        </div> 

        <!-- <div class='zoom-buttons'><button onclick='zoomIn()'>Zoom In</button><button onclick='zoomOut()'>Zoom Out</button></div><div class='pitch-button'><button onclick='adjustPitch()'>3D View</button></div> --> 

    <script> 

        mapboxgl.accessToken = 'pk.eyJ1Ijoib21wcmFrYXNoNzc3IiwiYSI6ImNsZzI5NHp1dzAzN2sza3BoemVxanFnbjEifQ.3rBOIqoJFkN_DDXEVxV3Cw'; // Replace with your Mapbox access token 

 

        var latitude = 12.979450; // Provided latitude from Flask API 

        var longitude = 77.590929; // Provided longitude from Flask API 

        var description = ''; // Provided description from Flask API (may be an empty string or None) 

        var zoom = 18; // Provided zoom from Flask API or None if not provided 

        var angle = 45; // Provided angle from Flask API or None if not provided 

        var addMarker = false; // Convert add_marker value to boolean 

        var visibleTileCount = 0; // Initialize visible tile count to 0 

        var tileCount = 0; // Initialize total tile count to 0 

        var prevVisibleTileCount = 0; // Initialize previous visible tile count to 0 

        var x_access_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJUb2tlbklEIjoiNTliNGNlYjktNmI5OS00YTdmLTllOWUtZDc3M2NlNGQxZGE1IiwiQ2xpZW50SUQiOiI3OWQ5OTM2Ny1iNzM5LTRiZmYtODRkNC1lNzcyMzk3MjEzMTYiLCJCdW5pdElEIjoxMDE5NiwiQXBwTmFtZSI6IlJhaHVsIC0gU2lnbiB1cCIsIkFwcElEIjoxMDE5NiwiVGltZVN0YW1wIjoiMjAyMy0wNC0xNyAwOToyODo0OSIsImV4cCI6MTcxNDEyMzcyOX0.NAlCJAzTMCJlTbbzZx_DgfRtUsAAlxPxLeAgeC41gCI' 

        var pan = "on"; // Control Panning  

        var zoom_control = "on"; // Control for zoom 

 

        // Set the default zoom value to 9 if not provided 

        if (zoom === null) { 

            zoom = 9; 

        } 

 

        var dragPanOption = true; // Default value 

 

        if (pan) { 

            if (pan.toLowerCase() === 'on') { 

                dragPanOption = true; 

            } else if (pan.toLowerCase() === 'off') { 

                dragPanOption = false; 

            } 

        } else { 

            dragPanOption = false; 

        } 

 

        var styleParam = 'light'; // Provided style from Flask API (may be 'light' or 'dark') 

        var mapStyleUrl = styleParam === 'dark' ? 'https://tiles.latlong.in/openmaptilesdark.json' : 'https://tiles.latlong.in/openmapstyle.json'; 

 

        var map = new mapboxgl.Map({ 

            container: 'map', 

            style: mapStyleUrl, // Use the style URL based on the styleParam value 

            center: [longitude, latitude], 

            zoom: zoom, // Set the initial zoom level based on the provided zoom value or the default value (9) 

            pitch: angle, // Set the pitch (tilt) of the map based on the provided angle value or 0 if not provided, 

            attributionControl: false, // Disable the default Mapbox attribution 

            dragPan: dragPanOption, 

        }); 

 

        // Disable scroll zoom if zoom_control is 'Off' 

        if (zoom_control.toLowerCase() === 'off') { 

            map.scrollZoom.disable(); 

        } 

 

        // Add zoom in/out buttons 

        map.addControl(new mapboxgl.NavigationControl(), 'bottom-right'); 

 

        // Initialize the GeolocateControl. 

        const geolocate = new mapboxgl.GeolocateControl({ 

            positionOptions: { 

                enableHighAccuracy: true 

            }, 

            trackUserLocation: true 

        }); 

        // // Add the control to the map. 

        // map.addControl(geolocate, 'bottom-right'); 

        // // Set an event listener that fires 

        // // when a trackuserlocationend event occurs. 

        // geolocate.on('trackuserlocationend', () => { 

        //     console.log('A trackuserlocationend event has occurred.'); 

        // }); 

 

        // Function to show the dialog box with the provided text 

        function showDialogBox(text) { 

            var dialogBox = document.getElementById('dialogBox'); 

            dialogBox.innerHTML = text; 

            dialogBox.style.display = 'block'; 

        } 

 

        // Function to hide the dialog box 

        function hideDialogBox() { 

            var dialogBox = document.getElementById('dialogBox'); 

            dialogBox.style.display = 'none'; 

        } 

 

        // Function to add a marker at the specified latitude and longitude 

        function addMarkerToMap() { 

            var marker = new mapboxgl.Marker() 

                .setLngLat([longitude, latitude]) 

                .addTo(map); 

 

            // Check if description is provided and not None or empty string, then show the dialog box 

            if (description && description.trim() !== '' && description.toLowerCase() !== 'none') { 

                var dialogBox = document.getElementById('dialogBox'); 

                var markerElement = marker.getElement(); 

                markerElement.appendChild(dialogBox); 

                showDialogBox(description); 

            } 

        } 

 

        // Check if addMarker is true to add a marker 

        if (addMarker) { 

            map.on('load', function () { 

                addMarkerToMap(); 

            }); 

        } 

 

        // Function to count tiles in the visible map area 

        function countVisibleTiles() { 

            var bounds = map.getBounds(); 

            var zoom = map.getZoom(); 

            var tileSize = 512; // Mapbox default tile size 

 

            var ne = map.project(bounds.getNorthEast()); 

            var sw = map.project(bounds.getSouthWest()); 

 

            var width = ne.x - sw.x; 

            var height = sw.y - ne.y; 

 

            var xTiles = Math.ceil(width / tileSize); 

            var yTiles = Math.ceil(height / tileSize); 

 

            return xTiles * yTiles; 

        } 

 

        // Function to send the tile count to the Flask API 

        function sendTileCount() { 

            prevVisibleTileCount = visibleTileCount; 

            visibleTileCount = countVisibleTiles(); 

            var tileCountChange = visibleTileCount - prevVisibleTileCount; 

            tileCount += tileCountChange; 

 

            // console.log('Tile count:', tileCount); 

 

            fetch('https://naksha.latlong.ai/tile_count', { 

                method: 'POST', 

                headers: { 

                    'Content-Type': 'application/json', 

    }, 

                body: JSON.stringify({ count: tileCount, latitude: latitude, longitude: longitude, description: description, zoom: zoom, styleParam: styleParam,x_access_token: x_access_token }), 

            }) 

            .then((response) => response.json()) 

            .then((data) => { 

                // console.log('Tile count sent to Flask API:', data); 

            }) 

            .catch((error) => { 

                console.error('Error sending tile count:', error); 

            }); 

        } 

 

        // Add event listeners to call sendTileCount function when the map is moved or clicked 

        map.on('load', function () { 

            // console.log("tile count") 

            sendTileCount(); 

            map.on('moveend', function () { 

                sendTileCount(); 

            }); 

        }); 

 

        // Function to add subway lines to the map 

        function addSubwayLines(subwayData) { 

            var features = subwayData.map(function (row) { 

                var geometry = JSON.parse(row[0]); // Parse the geometry from GeoJSON 

 

                // Reverse the order of coordinates from [longitude, latitude] to [latitude, longitude] 

                var coordinates = geometry.coordinates.map(function(coord) { 

                    return [coord[0], coord[1]]; 

                }); 

 

                return { 

                    type: 'Feature', 

                    geometry: { 

                        type: 'LineString', 

                        coordinates: coordinates // Use the reversed coordinates 

                    }, 

                    properties: { 

                        ref: row[1], // Get the color from the 'ref' column 

                    }, 

                }; 

            }); 

 

            map.on('load', function () { 

                map.addSource('subway-lines', { 

                    type: 'geojson', 

                    data: { 

                        type: 'FeatureCollection', 

                        features: features, 

                    }, 

                }); 

 

                map.addLayer({ 

                    id: 'subway-lines-layer', 

                    type: 'line', 

                    source: 'subway-lines', 

                    paint: { 

                        'line-color': ["get", "ref"], // Use the "ref" property to set line color 

                        'line-width': { 

                            stops: [ 

                                [10, 0], // Hide the line when zoomed out to level 10 or lower 

                                [15, 3]  // Show the line with thickness 3 when zoomed in to level 15 or higher 

                            ] 

                        }, 

                    }, 

                }); 

            }); 

        } 

 

        // AJAX call to get subway data from Flask API 

        if (map.getZoom() > 5) { 

            fetch('https://naksha.latlong.ai/subway') 

                .then((response) => response.json()) 

                .then((data) => { 

                    addSubwayLines(data); 

                }) 

                .catch((error) => { 

                    console.error('Error fetching subway data:', error); 

                }); 

        } 

         

        // Zoom in function 

        function zoomIn() { 

            map.zoomIn(); 

        } 

         

        // Zoom out function 

        function zoomOut() { 

            map.zoomOut(); 

        } 

         

        // Adjust pitch for 3D view 

        function adjustPitch() { 

            var newPitch = map.getPitch() === 0 ? 60 : 0; // Toggle between 0 (2D) and 60 (3D) pitch 

            map.easeTo({ pitch: newPitch }); 

        } 

    </script> 

</body> 

</html>  

⚠️ Errors

Status CodeMessageDescription
400Missing required parametersWhen query is not provided
401UnauthorizedAPI key missing or invalid
500Internal Server ErrorSomething went wrong on our side

Best Practices

  • Use Tile Mode for static map views
  • Use Point Mode for visual address emphasis without traditional pins
  • Ensure zoom levels are optimized for your use case (e.g., 15+ for specific locations)
  • Embed the returned HTML in iframe or div containers