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
Parameter | Type | Required | Description |
---|---|---|---|
lat | float | Yes | Latitude in decimal degrees (-90 to 90) |
lng | float | Yes | Longitude 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
Field | Type | Description |
---|---|---|
address | string | Complete, 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 Type | Rate Limit | Window |
---|---|---|
Reverse Geocoding | 100 requests | Per minute |
All API calls are charged at $0.01 per request.
Related Endpoints
- Geocoding - Convert addresses to coordinates
- Address Verification - Validate addresses
- Autocomplete - Real-time address suggestions