Claude
Skills
Sign in
โ† Back

free-geocoding-and-maps

Included with Lifetime
$97 forever

Geocode addresses and get map data using free OpenStreetMap Nominatim API. Use when: (1) Converting addresses to coordinates, (2) Reverse geocoding coordinates to addresses, (3) Location-based features, or (4) Validating addresses.

Backend & APIs

What this skill does


# Free Geocoding and Maps โ€” OpenStreetMap Nominatim

Geocode addresses to coordinates and reverse geocode coordinates to addresses using free OpenStreetMap Nominatim API. Privacy-respecting alternative to Google Maps API ($5-40/1000 requests).

## Why This Replaces Paid Geocoding APIs

**๐Ÿ’ฐ Cost savings:**
- โœ… **100% free** โ€” no API keys required
- โœ… **No rate limits** โ€” generous 1 request/second for public instances
- โœ… **Open source** โ€” self-hostable for unlimited usage
- โœ… **Privacy-first** โ€” no tracking, no data collection

**Perfect for AI agents that need:**
- Address validation and geocoding
- Reverse geocoding (coordinates to address)
- Location search and mapping
- Geospatial data without Google Maps API costs

## Quick comparison

| Service | Cost | Rate limit | Privacy | API key required |
|---------|------|------------|---------|------------------|
| Google Maps Geocoding | $5/1000 requests | 40,000/month free | โŒ Tracked | โœ… Yes |
| Mapbox Geocoding | $0.50/1000 after 100k free | 100k/month free | โŒ Tracked | โœ… Yes |
| **Nominatim (OSM)** | **Free** | **1 req/sec** | **โœ… Private** | **โŒ No** |

## Skills

### geocode_address

Convert address to coordinates (latitude/longitude).

```bash
# Geocode an address
ADDRESS="1600 Amphitheatre Parkway, Mountain View, CA"
curl -s "https://nominatim.openstreetmap.org/search?q=${ADDRESS}&format=json&limit=1" \
  | jq -r '.[0] | {lat: .lat, lon: .lon, display_name: .display_name}'

# Geocode with structured address
curl -s "https://nominatim.openstreetmap.org/search" \
  -G \
  --data-urlencode "street=1600 Amphitheatre Parkway" \
  --data-urlencode "city=Mountain View" \
  --data-urlencode "state=California" \
  --data-urlencode "country=USA" \
  --data-urlencode "format=json" \
  | jq -r '.[0] | {lat: .lat, lon: .lon}'

# Get multiple results
curl -s "https://nominatim.openstreetmap.org/search?q=London&format=json&limit=5" \
  | jq -r '.[] | {name: .display_name, lat: .lat, lon: .lon}'
```

**Node.js:**

```javascript
async function geocodeAddress(address, limit = 1) {
  const params = new URLSearchParams({
    q: address,
    format: 'json',
    limit: limit.toString()
  });
  
  const res = await fetch(`https://nominatim.openstreetmap.org/search?${params}`, {
    headers: {
      'User-Agent': 'AI-Agent/1.0' // Required by Nominatim usage policy
    }
  });
  
  if (!res.ok) {
    throw new Error(`Geocoding failed: ${res.status}`);
  }
  
  const results = await res.json();
  
  if (results.length === 0) {
    return null;
  }
  
  return results.map(r => ({
    lat: parseFloat(r.lat),
    lon: parseFloat(r.lon),
    displayName: r.display_name,
    type: r.type,
    importance: r.importance
  }));
}

// Usage
// geocodeAddress('Eiffel Tower, Paris')
//   .then(results => {
//     if (results) {
//       console.log(`Location: ${results[0].displayName}`);
//       console.log(`Coordinates: ${results[0].lat}, ${results[0].lon}`);
//     }
//   });
```

### reverse_geocode

Convert coordinates to address (reverse geocoding).

```bash
# Reverse geocode coordinates
LAT=40.7589
LON=-73.9851

curl -s "https://nominatim.openstreetmap.org/reverse?lat=${LAT}&lon=${LON}&format=json" \
  | jq -r '.display_name'

# Get detailed address components
curl -s "https://nominatim.openstreetmap.org/reverse?lat=${LAT}&lon=${LON}&format=json" \
  | jq -r '.address | {
    road: .road,
    city: .city,
    state: .state,
    country: .country,
    postcode: .postcode
  }'

# Reverse geocode with zoom level (detail level)
curl -s "https://nominatim.openstreetmap.org/reverse?lat=${LAT}&lon=${LON}&format=json&zoom=18" \
  | jq -r '.display_name'
```

**Node.js:**

```javascript
async function reverseGeocode(lat, lon, zoom = 18) {
  const params = new URLSearchParams({
    lat: lat.toString(),
    lon: lon.toString(),
    format: 'json',
    zoom: zoom.toString()
  });
  
  const res = await fetch(`https://nominatim.openstreetmap.org/reverse?${params}`, {
    headers: {
      'User-Agent': 'AI-Agent/1.0'
    }
  });
  
  if (!res.ok) {
    throw new Error(`Reverse geocoding failed: ${res.status}`);
  }
  
  const data = await res.json();
  
  return {
    displayName: data.display_name,
    address: {
      road: data.address?.road,
      city: data.address?.city || data.address?.town || data.address?.village,
      state: data.address?.state,
      country: data.address?.country,
      postcode: data.address?.postcode
    },
    lat: parseFloat(data.lat),
    lon: parseFloat(data.lon)
  };
}

// Usage
// reverseGeocode(48.8584, 2.2945)  // Eiffel Tower coordinates
//   .then(result => {
//     console.log('Address:', result.displayName);
//     console.log('City:', result.address.city);
//     console.log('Country:', result.address.country);
//   });
```

### search_nearby_places

Search for places near coordinates or within a bounding box.

```bash
# Search for places near coordinates
LAT=40.7589
LON=-73.9851
RADIUS_KM=1

curl -s "https://nominatim.openstreetmap.org/search?q=restaurant&format=json&limit=10&lat=${LAT}&lon=${LON}" \
  | jq -r '.[] | {name: .display_name, distance: .distance}'

# Search within bounding box (viewbox)
# Format: left,top,right,bottom (min_lon,max_lat,max_lon,min_lat)
curl -s "https://nominatim.openstreetmap.org/search" \
  -G \
  --data-urlencode "q=cafe" \
  --data-urlencode "format=json" \
  --data-urlencode "viewbox=-0.1278,51.5074,-0.1,51.52" \
  --data-urlencode "bounded=1" \
  | jq -r '.[] | {name: .display_name, lat: .lat, lon: .lon}'
```

**Node.js:**

```javascript
async function searchNearby(query, lat, lon, limit = 10) {
  const params = new URLSearchParams({
    q: query,
    format: 'json',
    limit: limit.toString(),
    lat: lat.toString(),
    lon: lon.toString()
  });
  
  const res = await fetch(`https://nominatim.openstreetmap.org/search?${params}`, {
    headers: {
      'User-Agent': 'AI-Agent/1.0'
    }
  });
  
  if (!res.ok) {
    throw new Error(`Search failed: ${res.status}`);
  }
  
  const results = await res.json();
  
  return results.map(r => ({
    name: r.display_name,
    lat: parseFloat(r.lat),
    lon: parseFloat(r.lon),
    type: r.type,
    importance: r.importance
  }));
}

// Usage
// searchNearby('coffee shop', 40.7589, -73.9851, 5)
//   .then(results => {
//     console.log(`Found ${results.length} places:`);
//     results.forEach(p => console.log(`- ${p.name}`));
//   });
```

### calculate_distance

Calculate distance between two coordinates using Haversine formula.

```bash
# Calculate distance (requires bc calculator)
calculate_distance() {
  local lat1=$1 lon1=$2 lat2=$3 lon2=$4
  
  # Haversine formula in bash (simplified)
  bc -l <<EOF
define haversin(lat1, lon1, lat2, lon2) {
  r = 6371  /* Earth radius in km */
  dlat = (lat2 - lat1) * 0.017453292519943295
  dlon = (lon2 - lon1) * 0.017453292519943295
  a = s(dlat/2)^2 + c(lat1*0.017453292519943295) * c(lat2*0.017453292519943295) * s(dlon/2)^2
  c = 2 * a(sqrt(a)/sqrt(1-a))
  return r * c
}
haversin($lat1, $lon1, $lat2, $lon2)
EOF
}

# Usage
calculate_distance 40.7589 -73.9851 34.0522 -118.2437
# Output: ~3935 km (NYC to LA)
```

**Node.js:**

```javascript
function calculateDistance(lat1, lon1, lat2, lon2) {
  // Haversine formula
  const R = 6371; // Earth radius in km
  
  const toRad = (deg) => deg * Math.PI / 180;
  
  const dLat = toRad(lat2 - lat1);
  const dLon = toRad(lon2 - lon1);
  
  const a = 
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  
  return R * c; // Distance in km
}

// Usage
// const distanceKm = calculateDistance(40.7589, -73.9851, 34.0522, -118.2437);
// console.log(`Distance: ${distanceKm.toFixed(2)} km`);
// console.log(`Distance: ${(distanceKm * 0.621371).toFixed(2)} miles`);
```

### batch_geocode_with_rate_limit

Geocode multiple addresses with rate limiting (1 req/sec for Nominatim).

```bash
#!/bin/

Related in Backend & APIs