Reverse Geocoding API

Convert geographic coordinates (latitude and longitude) back into human-readable addresses.

The Reverse Geocoding API converts geographic coordinates into human-readable addresses. This is useful for applications that need to display location information based on GPS coordinates, analyze geographic data, or provide location context.

Endpoint

GET /api/v1/reverse-geocode

Authentication

Requires API key authentication. Include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Request Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees (-90 to 90)
lngfloatYesLongitude in decimal degrees (-180 to 180)

Coordinate Format

  • Use decimal degrees format (e.g., 37.7749, -122.4194)
  • Positive latitudes are north of the equator
  • Negative latitudes are south of the equator
  • Positive longitudes are east of the Prime Meridian
  • Negative longitudes are west of the Prime Meridian

Response Format

Success Response

{
  "address": "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA"
}

Response Fields

FieldTypeDescription
addressstringComplete, formatted address for the given coordinates

Error Responses

Missing Parameters

{
  "error": {
    "code": 400,
    "message": "Both lat and lng parameters are required"
  }
}

Status Code: 400 Bad Request

Invalid Coordinates

{
  "error": {
    "code": 400,
    "message": "Invalid coordinates. Latitude must be between -90 and 90, longitude between -180 and 180"
  }
}

Status Code: 400 Bad Request

Location Not Found

{
  "error": {
    "code": 404,
    "message": "No address found for the given coordinates"
  }
}

Status Code: 404 Not Found

Insufficient Balance

{
  "error": {
    "code": 402,
    "message": "Insufficient balance. Please add funds to continue."
  }
}

Status Code: 402 Payment Required

Service Error

{
  "error": {
    "code": 500,
    "message": "Internal Server Error"
  }
}

Status Code: 500 Internal Server Error

Code Examples

cURL

curl -X GET "https://core.streetverify.com/api/v1/reverse-geocode?lat=37.4224764&lng=-122.0842499" \
  -H "Authorization: Bearer YOUR_API_KEY"

JavaScript

class ReverseGeocoder {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://core.streetverify.com/api/v1';
  }

  async getAddress(latitude, longitude) {
    const params = new URLSearchParams({
      lat: latitude,
      lng: longitude
    });

    const response = await fetch(`${this.baseUrl}/reverse-geocode?${params}`, {
      headers: {
        'Authorization': `Bearer ${this.apiKey}`
      }
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error?.message || `HTTP ${response.status}`);
    }

    return response.json();
  }

  async getAddressFromPosition() {
    // Get current position using browser's Geolocation API
    return new Promise((resolve, reject) => {
      if (!navigator.geolocation) {
        reject(new Error('Geolocation not supported'));
        return;
      }

      navigator.geolocation.getCurrentPosition(
        async (position) => {
          try {
            const result = await this.getAddress(
              position.coords.latitude,
              position.coords.longitude
            );
            resolve(result);
          } catch (error) {
            reject(error);
          }
        },
        (error) => reject(error)
      );
    });
  }
}

// Usage
const geocoder = new ReverseGeocoder('YOUR_API_KEY');

// With known coordinates
try {
  const result = await geocoder.getAddress(37.4224764, -122.0842499);
  console.log('Address:', result.address);
} catch (error) {
  console.error('Reverse geocoding failed:', error);
}

// With browser location
try {
  const result = await geocoder.getAddressFromPosition();
  console.log('Your location:', result.address);
} catch (error) {
  console.error('Location error:', error);
}

Python

import requests
from typing import Dict, Optional, Tuple

class ReverseGeocoder:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://core.streetverify.com/api/v1"
    
    def get_address(self, latitude: float, longitude: float) -> Dict:
        """Get address from coordinates."""
        headers = {"Authorization": f"Bearer {self.api_key}"}
        params = {
            "lat": latitude,
            "lng": longitude
        }
        
        response = requests.get(
            f"{self.base_url}/reverse-geocode",
            params=params,
            headers=headers
        )
        response.raise_for_status()
        
        return response.json()
    
    def validate_coordinates(self, lat: float, lng: float) -> Tuple[bool, Optional[str]]:
        """Validate coordinate bounds."""
        if not -90 <= lat <= 90:
            return False, "Latitude must be between -90 and 90"
        if not -180 <= lng <= 180:
            return False, "Longitude must be between -180 and 180"
        return True, None
    
    def get_address_safe(self, latitude: float, longitude: float) -> Dict:
        """Get address with coordinate validation."""
        valid, error = self.validate_coordinates(latitude, longitude)
        if not valid:
            raise ValueError(error)
        
        return self.get_address(latitude, longitude)

# Usage
geocoder = ReverseGeocoder("YOUR_API_KEY")

# Example coordinates (Googleplex)
lat, lng = 37.4224764, -122.0842499

try:
    result = geocoder.get_address_safe(lat, lng)
    print(f"Address: {result['address']}")
except ValueError as e:
    print(f"Invalid coordinates: {e}")
except requests.HTTPError as e:
    print(f"API error: {e}")

React Native

import React, { useState, useEffect } from 'react';
import { View, Text, Button, ActivityIndicator } from 'react-native';
import * as Location from 'expo-location';

const LocationToAddress = ({ apiKey }) => {
  const [location, setLocation] = useState(null);
  const [address, setAddress] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const getCurrentLocation = async () => {
    setLoading(true);
    setError(null);
    
    try {
      // Request permission
      const { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== 'granted') {
        throw new Error('Location permission denied');
      }
      
      // Get current position
      const position = await Location.getCurrentPositionAsync({
        accuracy: Location.Accuracy.High
      });
      
      setLocation(position.coords);
      
      // Reverse geocode
      const response = await fetch(
        `https://core.streetverify.com/api/v1/reverse-geocode?` +
        `lat=${position.coords.latitude}&` +
        `lng=${position.coords.longitude}`,
        {
          headers: {
            'Authorization': `Bearer ${apiKey}`
          }
        }
      );
      
      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.error?.message || 'Failed to get address');
      }
      
      setAddress(data.address);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={{ padding: 20 }}>
      <Button
        title="Get Current Address"
        onPress={getCurrentLocation}
        disabled={loading}
      />
      
      {loading && <ActivityIndicator style={{ marginTop: 20 }} />}
      
      {location && (
        <Text style={{ marginTop: 10 }}>
          Coordinates: {location.latitude.toFixed(6)}, {location.longitude.toFixed(6)}
        </Text>
      )}
      
      {address && (
        <Text style={{ marginTop: 10, fontWeight: 'bold' }}>
          Address: {address}
        </Text>
      )}
      
      {error && (
        <Text style={{ marginTop: 10, color: 'red' }}>
          Error: {error}
        </Text>
      )}
    </View>
  );
};

Use Cases

1. Photo Geotagging

Add location information to photos based on GPS coordinates:

const geotagPhoto = async (photo, latitude, longitude) => {
  const result = await geocoder.getAddress(latitude, longitude);
  
  return {
    ...photo,
    location: {
      coordinates: { latitude, longitude },
      address: result.address
    }
  };
};

2. Delivery Tracking

Show driver location with address context:

const trackDelivery = async (driverId) => {
  // Get driver's current GPS position
  const position = await getDriverPosition(driverId);
  
  // Convert to address
  const location = await geocoder.getAddress(
    position.latitude,
    position.longitude
  );
  
  return {
    driver: driverId,
    currentLocation: location.address,
    coordinates: position,
    lastUpdate: new Date().toISOString()
  };
};

3. Location Analytics

Analyze geographic distribution of events:

import pandas as pd
from collections import Counter

def analyze_locations(coordinates_list):
    """Analyze geographic distribution of coordinates."""
    geocoder = ReverseGeocoder(API_KEY)
    locations = []
    
    for lat, lng in coordinates_list:
        try:
            result = geocoder.get_address(lat, lng)
            locations.append({
                'address': result['address'],
                'lat': lat,
                'lng': lng
            })
        except Exception as e:
            print(f"Error for {lat},{lng}: {e}")
    
    # Create DataFrame
    df = pd.DataFrame(locations)
    
    # Analyze distribution by extracting from address strings
    # This is a simplified example - in production you might want to parse addresses
    
    return {
        'total_locations': len(locations),
        'dataframe': df
    }

4. Emergency Services

Quickly identify location details for emergency response:

class EmergencyLocator {
  constructor(apiKey) {
    this.geocoder = new ReverseGeocoder(apiKey);
  }
  
  async getEmergencyLocation(latitude, longitude) {
    try {
      const result = await this.geocoder.getAddress(latitude, longitude);
      
      // Format for emergency dispatch
      return {
        priority: 'HIGH',
        timestamp: new Date().toISOString(),
        location: {
          full_address: result.address,
          coordinates: { latitude, longitude }
        }
      };
    } catch (error) {
      // Fallback to coordinates only
      return {
        priority: 'HIGH',
        timestamp: new Date().toISOString(),
        location: {
          coordinates: { latitude, longitude },
          error: 'Address lookup failed - use GPS coordinates'
        }
      };
    }
  }
}

Best Practices

1. Coordinate Validation

Always validate coordinates before making API calls:

const isValidCoordinate = (lat, lng) => {
  return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
};

const reverseGeocodeSafe = async (lat, lng) => {
  if (!isValidCoordinate(lat, lng)) {
    throw new Error('Invalid coordinates');
  }
  
  return await geocoder.getAddress(lat, lng);
};

2. Error Handling

Implement graceful fallbacks for failed lookups:

const getLocationInfo = async (lat, lng) => {
  try {
    const result = await geocoder.getAddress(lat, lng);
    return {
      success: true,
      address: result.address
    };
  } catch (error) {
    // Fallback to coordinate-based info
    return {
      success: false,
      address: `${lat.toFixed(6)}, ${lng.toFixed(6)}`,
      error: error.message
    };
  }
};

3. Caching Results

Cache reverse geocoding results to reduce API calls:

class CachedReverseGeocoder {
  constructor(apiKey, cacheTime = 3600000) { // 1 hour
    this.geocoder = new ReverseGeocoder(apiKey);
    this.cache = new Map();
    this.cacheTime = cacheTime;
  }
  
  getCacheKey(lat, lng) {
    // Round to 5 decimal places for cache key
    return `${lat.toFixed(5)},${lng.toFixed(5)}`;
  }
  
  async getAddress(latitude, longitude) {
    const cacheKey = this.getCacheKey(latitude, longitude);
    const cached = this.cache.get(cacheKey);
    
    if (cached && Date.now() - cached.timestamp < this.cacheTime) {
      return cached.data;
    }
    
    const result = await this.geocoder.getAddress(latitude, longitude);
    
    this.cache.set(cacheKey, {
      data: result,
      timestamp: Date.now()
    });
    
    // Limit cache size
    if (this.cache.size > 1000) {
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    
    return result;
  }
}

4. Batch Processing

Process multiple coordinates efficiently:

const batchReverseGeocode = async (coordinates, options = {}) => {
  const {
    concurrency = 3,
    delayMs = 100,
    onProgress
  } = options;
  
  const results = [];
  const chunks = [];
  
  // Split into chunks for concurrent processing
  for (let i = 0; i < coordinates.length; i += concurrency) {
    chunks.push(coordinates.slice(i, i + concurrency));
  }
  
  for (const [index, chunk] of chunks.entries()) {
    const promises = chunk.map(coord => 
      geocoder.getAddress(coord.latitude, coord.longitude)
        .then(result => ({ ...coord, result }))
        .catch(error => ({ ...coord, error: error.message }))
    );
    
    const chunkResults = await Promise.all(promises);
    results.push(...chunkResults);
    
    if (onProgress) {
      onProgress(results.length, coordinates.length);
    }
    
    // Rate limiting delay
    if (index < chunks.length - 1) {
      await new Promise(resolve => setTimeout(resolve, delayMs));
    }
  }
  
  return results;
};

// Usage
const coordinates = [
  { id: 1, latitude: 37.7749, longitude: -122.4194 },
  { id: 2, latitude: 40.7128, longitude: -74.0060 },
  // ... more coordinates
];

const results = await batchReverseGeocode(coordinates, {
  concurrency: 5,
  onProgress: (completed, total) => {
    console.log(`Processed ${completed}/${total} locations`);
  }
});

Performance Tips

1. Precision Reduction

For nearby coordinates, reduce precision to improve cache hit rate:

const roundCoordinate = (value, precision = 5) => {
  return Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision);
};

2. Request Optimization

Combine reverse geocoding with other operations:

const enrichLocationData = async (event) => {
  const tasks = [];
  
  // Reverse geocode
  tasks.push(geocoder.getAddress(event.latitude, event.longitude));
  
  // Other enrichments in parallel
  tasks.push(getWeatherData(event.latitude, event.longitude));
  tasks.push(getTimezone(event.latitude, event.longitude));
  
  const [location, weather, timezone] = await Promise.all(tasks);
  
  return {
    ...event,
    address: location.data.formatted_address,
    weather: weather.data,
    timezone: timezone.data
  };
};

Rate Limits

The Reverse Geocoding API follows the standard rate limits:

Endpoint TypeRate LimitWindow
Reverse Geocoding100 requestsPer minute

All API calls are charged at $0.01 per request.