Ola Map SDK

Elevation API

Guide to getting elevation data for single and multiple locations

Elevation API

The Elevation API provides terrain elevation data for any location worldwide, useful for outdoor activities, engineering projects, and geographic analysis.

Overview

The Elevation API offers two main functions:

  • Get Elevation - Get elevation for a single location
  • Get Multi-Elevation - Get elevations for up to 25 locations in one request

Get Elevation

Retrieve elevation data for a specific location.

Basic Usage

const elevation = await client.elevation.getElevation(12.93126, 77.61638);

Response Example

{
    status: "OK",
    results: [
        {
            elevation: 920.5,      // Elevation in meters
            location: {
                lat: 12.93126,
                lng: 77.61638
            },
            resolution: 30         // Data resolution in meters
        }
    ]
}

Parameters

ParameterTypeRequiredDescription
latnumberYesLatitude (-90 to 90)
lngnumberYesLongitude (-180 to 180)

Error Handling

try {
    const elevation = await client.elevation.getElevation(12.93126, 77.61638);
    console.log(`Elevation: ${elevation.results[0].elevation}m`);
} catch (error) {
    if (error.message.includes('must be numbers')) {
        console.error('Invalid coordinates - latitude and longitude must be numbers');
    } else {
        console.error('Elevation API error:', error.message);
    }
}

Get Multi-Elevation

Retrieve elevation data for multiple locations in a single request.

Basic Usage

const elevations = await client.elevation.getMultiElevation([
    '12.93126,77.61638',
    '12.89731,77.65136',
    '12.95000,77.60000'
]);

Response Example

{
    status: "OK",
    results: [
        {
            elevation: 920.5,
            location: {
                lat: 12.93126,
                lng: 77.61638
            },
            resolution: 30
        },
        {
            elevation: 875.2,
            location: {
                lat: 12.89731,
                lng: 77.65136
            },
            resolution: 30
        },
        {
            elevation: 905.8,
            location: {
                lat: 12.95000,
                lng: 77.60000
            },
            resolution: 30
        }
    ]
}

Parameters

ParameterTypeRequiredDescription
locationsarrayYesArray of "lat,lng" strings (max 25 locations)

Limitations

  • Maximum 25 locations per request
  • Each location must be in "lat,lng" string format
  • Exceeding the limit will throw an error
// ❌ This will fail - too many locations
const tooMany = await client.elevation.getMultiElevation(
    Array(30).fill('12.93,77.61')
);

// ✅ Split into multiple requests
const batch1 = locations.slice(0, 25);
const batch2 = locations.slice(25);

const [results1, results2] = await Promise.all([
    client.elevation.getMultiElevation(batch1),
    client.elevation.getMultiElevation(batch2)
]);

Real-World Examples

Hiking Trail Profile

Create an elevation profile for a hiking trail:

async function createTrailElevationProfile(trailCoordinates) {
    // Split into batches of 25
    const batches = [];
    for (let i = 0; i < trailCoordinates.length; i += 25) {
        batches.push(trailCoordinates.slice(i, i + 25));
    }
    
    // Get elevation for all batches
    const allResults = [];
    for (const batch of batches) {
        const locations = batch.map(c => `${c.lat},${c.lng}`);
        const response = await client.elevation.getMultiElevation(locations);
        allResults.push(...response.results);
        
        // Small delay to avoid rate limiting
        await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    // Calculate statistics
    const elevations = allResults.map(r => r.elevation);
    const minElevation = Math.min(...elevations);
    const maxElevation = Math.max(...elevations);
    const totalAscent = calculateTotalAscent(elevations);
    const avgGradient = calculateAverageGradient(allResults);
    
    return {
        profile: allResults,
        statistics: {
            minElevation,
            maxElevation,
            elevationGain: maxElevation - minElevation,
            totalAscent,
            averageGradient,
            distance: calculateTotalDistance(allResults)
        }
    };
}

function calculateTotalAscent(elevations) {
    let ascent = 0;
    for (let i = 1; i < elevations.length; i++) {
        if (elevations[i] > elevations[i - 1]) {
            ascent += elevations[i] - elevations[i - 1];
        }
    }
    return ascent;
}

// Usage
const trailCoords = [
    { lat: 12.93126, lng: 77.61638 },
    { lat: 12.93200, lng: 77.61700 },
    { lat: 12.93300, lng: 77.61800 }
    // ... more points
];

createTrailElevationProfile(trailCoords)
    .then(profile => console.log('Trail profile:', profile))
    .catch(console.error);

Construction Site Analysis

Analyze terrain for construction planning:

async function analyzeConstructionSite(boundaryPoints) {
    // Get elevations at boundary points
    const locations = boundaryPoints.map(p => `${p.lat},${p.lng}`);
    const response = await client.elevation.getMultiElevation(locations);
    
    const elevations = response.results.map(r => r.elevation);
    const minElev = Math.min(...elevations);
    const maxElev = Math.max(...elevations);
    const avgElev = elevations.reduce((a, b) => a + b, 0) / elevations.length;
    
    // Calculate earthwork estimation
    const area = calculateArea(boundaryPoints); // in square meters
    const cutFillVolume = estimateCutFillVolume(avgElev, minElev, maxElev, area);
    
    return {
        siteAnalysis: {
            averageElevation: avgElev.toFixed(2) + 'm',
            elevationRange: {
                min: minElev + 'm',
                max: maxElev + 'm'
            },
            terrainVariation: (maxElev - minElev).toFixed(2) + 'm',
            estimatedEarthwork: cutFillVolume + ' cubic meters'
        },
        rawElevations: response.results
    };
}

// Usage
const siteBoundary = [
    { lat: 28.7041, lng: 77.1025 },
    { lat: 28.7045, lng: 77.1030 },
    { lat: 28.7043, lng: 77.1035 },
    { lat: 28.7039, lng: 77.1030 }
];

analyzeConstructionSite(siteBoundary)
    .then(analysis => console.log('Site analysis:', analysis))
    .catch(console.error);

Cycling Route Planner

Plan cycling routes with elevation considerations:

class CyclingRoutePlanner {
    async getRouteDifficulty(routeCoordinates) {
        // Get elevations for route
        const locations = routeCoordinates.map(c => `${c.lat},${c.lng}`);
        const response = await client.elevation.getMultiElevation(locations);
        
        const elevations = response.results.map(r => r.elevation);
        
        // Calculate difficulty metrics
        const totalClimbing = this.calculateTotalClimbing(elevations);
        const maxGradient = this.calculateMaxGradient(elevations);
        const elevationPoints = this.countElevationPoints(elevations);
        
        // Assign difficulty rating
        let difficulty = 'Easy';
        if (totalClimbing > 1000 || maxGradient > 10) {
            difficulty = 'Hard';
        } else if (totalClimbing > 500 || maxGradient > 6) {
            difficulty = 'Moderate';
        }
        
        return {
            difficulty,
            metrics: {
                totalClimbing: `${totalClimbing}m`,
                maxGradient: `${maxGradient}%`,
                climbingPoints: elevationPoints,
                averageElevation: Math.round(elevations.reduce((a, b) => a + b, 0) / elevations.length) + 'm'
            },
            elevationProfile: response.results
        };
    }
    
    calculateTotalClimbing(elevations) {
        let climbing = 0;
        for (let i = 1; i < elevations.length; i++) {
            const diff = elevations[i] - elevations[i - 1];
            if (diff > 0) climbing += diff;
        }
        return Math.round(climbing);
    }
    
    calculateMaxGradient(elevations) {
        let maxGrad = 0;
        for (let i = 1; i < elevations.length; i++) {
            const diff = elevations[i] - elevations[i - 1];
            const gradient = (diff / 100) * 100; // Assume 100m between points
            if (gradient > maxGrad) maxGrad = gradient;
        }
        return Math.round(maxGrad * 10) / 10;
    }
    
    countElevationPoints(elevations) {
        return elevations.filter((_, i) => {
            if (i === 0 || i === elevations.length - 1) return false;
            return elevations[i] > elevations[i - 1] && elevations[i] > elevations[i + 1];
        }).length;
    }
}

// Usage
const route = [
    { lat: 12.93126, lng: 77.61638 },
    { lat: 12.94000, lng: 77.62000 },
    { lat: 12.95000, lng: 77.63000 }
];

const planner = new CyclingRoutePlanner();
planner.getRouteDifficulty(route)
    .then(difficulty => console.log('Route difficulty:', difficulty))
    .catch(console.error);

Flood Risk Assessment

Assess flood risk based on elevation:

async function assessFloodRisk(areaCoordinates, riverLevel) {
    const locations = areaCoordinates.map(c => `${c.lat},${c.lng}`);
    const response = await client.elevation.getMultiElevation(locations);
    
    const riskAssessment = response.results.map(point => {
        const elevationAboveRiver = point.elevation - riverLevel;
        let riskLevel = 'Low';
        
        if (elevationAboveRiver < 2) {
            riskLevel = 'Very High';
        } else if (elevationAboveRiver < 5) {
            riskLevel = 'High';
        } else if (elevationAboveRiver < 10) {
            riskLevel = 'Moderate';
        }
        
        return {
            location: point.location,
            elevation: point.elevation,
            elevationAboveRiver: elevationAboveRiver,
            floodRisk: riskLevel
        };
    });
    
    const highRiskPoints = riskAssessment.filter(p => 
        p.floodRisk === 'High' || p.floodRisk === 'Very High'
    );
    
    return {
        overallRisk: highRiskPoints.length > 0 ? 'High' : 'Low',
        highRiskAreas: highRiskPoints,
        recommendations: highRiskPoints.length > 0 
            ? 'Implement flood mitigation measures in identified areas'
            : 'Area has low flood risk'
    };
}

// Usage
const riversideArea = [
    { lat: 26.1151, lng: 91.7032 },
    { lat: 26.1160, lng: 91.7040 },
    { lat: 26.1170, lng: 91.7050 }
];

assessFloodRisk(riversideArea, 45.5) // River level at 45.5m
    .then(assessment => console.log('Flood risk assessment:', assessment))
    .catch(console.error);

Best Practices

1. Batch Requests Efficiently

async function getElevationsForLargeDataset(coordinates) {
    const results = [];
    const batchSize = 25;
    
    for (let i = 0; i < coordinates.length; i += batchSize) {
        const batch = coordinates.slice(i, i + batchSize);
        const locations = batch.map(c => `${c.lat},${c.lng}`);
        
        try {
            const response = await client.elevation.getMultiElevation(locations);
            results.push(...response.results);
        } catch (error) {
            console.error(`Batch ${i / batchSize} failed:`, error);
        }
        
        // Avoid rate limiting
        if (i + batchSize < coordinates.length) {
            await new Promise(resolve => setTimeout(resolve, 100));
        }
    }
    
    return results;
}

2. Validate Coordinates

function isValidCoordinate(lat, lng) {
    return (
        typeof lat === 'number' &&
        typeof lng === 'number' &&
        lat >= -90 && lat <= 90 &&
        lng >= -180 && lng <= 180
    );
}

async function safeGetElevation(lat, lng) {
    if (!isValidCoordinate(lat, lng)) {
        throw new Error('Invalid coordinates provided');
    }
    
    return await client.elevation.getElevation(lat, lng);
}

3. Cache Elevation Data

const elevationCache = new Map();

async function getCachedElevation(lat, lng) {
    const key = `${lat.toFixed(5)},${lng.toFixed(5)}`;
    
    if (elevationCache.has(key)) {
        return elevationCache.get(key);
    }
    
    const result = await client.elevation.getElevation(lat, lng);
    elevationCache.set(key, result);
    
    // Cache for 24 hours
    setTimeout(() => elevationCache.delete(key), 86400000);
    
    return result;
}

4. Handle Edge Cases

async function getElevationWithFallback(lat, lng) {
    try {
        const result = await client.elevation.getElevation(lat, lng);
        
        if (!result.results || result.results.length === 0) {
            console.warn('No elevation data available for this location');
            return { elevation: null, reason: 'no_data' };
        }
        
        return result.results[0];
    } catch (error) {
        console.error('Elevation request failed:', error);
        throw error;
    }
}

Use Cases

Outdoor Recreation

  • Hiking: Calculate trail difficulty and elevation gain
  • Cycling: Plan routes with appropriate climbing
  • Running: Analyze course elevation profiles
  • Skiing: Determine slope steepness and vertical drop

Engineering & Construction

  • Site Planning: Assess terrain for construction feasibility
  • Road Design: Calculate gradients and earthwork requirements
  • Drainage Analysis: Understand water flow patterns
  • Foundation Design: Determine excavation needs

Environmental Studies

  • Flood Modeling: Identify flood-prone areas
  • Watershed Analysis: Map drainage basins
  • Habitat Mapping: Correlate elevation with ecosystems
  • Climate Studies: Analyze elevation-temperature relationships

Agriculture

  • Irrigation Planning: Design gravity-fed irrigation systems
  • Crop Planning: Match crops to elevation zones
  • Erosion Control: Identify erosion-prone slopes
  • Vineyard Management: Optimize grape growing conditions

Data Resolution

The Elevation API uses data with approximately 30-meter resolution, which means:

  • Elevation values represent the average elevation within a 30m × 30m area
  • Suitable for most planning and analysis applications
  • May not capture very fine terrain features
  • For higher precision needs, consider specialized surveying

Next Steps

  • Learn about Tiles API for map tiles and static maps
  • Explore Map Display to visualize elevation on maps
  • Check Examples for more elevation use cases

On this page