Building a location-based app? Geocoding APIs convert addresses to coordinates (and vice versa), enabling maps, delivery tracking, and location search. This guide compares the best free geocoding APIs for developers in 2026.
Quick Comparison Table
| Provider | Free Tier | Rate Limit | Best For |
|---|---|---|---|
| Google Maps | $200/mo credit | 50 req/sec | Accuracy |
| Mapbox | 100K req/mo | 600 req/min | Modern apps |
| OpenCage | 2,500 req/day | 1 req/sec | Privacy |
| Nominatim | Unlimited | 1 req/sec | Open source |
| HERE | 250K req/mo | 5 req/sec | Enterprise |
| LocationIQ | 5K req/day | 2 req/sec | Budget |
| Geoapify | 3K req/day | 5 req/sec | EU data |
| Positionstack | 25K req/mo | - | Simple |
1. Google Maps Geocoding API
Google Maps offers the most accurate geocoding with comprehensive global coverage.
Free Tier:
- $200 monthly credit (covers ~40,000 geocode requests)
- Pay-as-you-go after credit
- No credit card for first $200
Pricing (after free credit):
- 0-100K requests: $5/1,000
- 100K-500K: $4/1,000
Key Features:
- Industry-leading accuracy
- 200+ countries
- Place autocomplete
- Place details
- Component filtering
- Address validation
JavaScript Example:
const axios = require('axios');
const GOOGLE_API_KEY = process.env.GOOGLE_MAPS_API_KEY;
async function geocode(address) {
const response = await axios.get(
'https://maps.googleapis.com/maps/api/geocode/json',
{
params: {
address,
key: GOOGLE_API_KEY
}
}
);
if (response.data.status !== 'OK') {
throw new Error(`Geocoding failed: ${response.data.status}`);
}
const result = response.data.results[0];
return {
formattedAddress: result.formatted_address,
lat: result.geometry.location.lat,
lng: result.geometry.location.lng,
placeId: result.place_id,
components: result.address_components
};
}
// Usage
const location = await geocode('1600 Amphitheatre Parkway, Mountain View, CA');
console.log(location);
// { lat: 37.4224764, lng: -122.0842499, ... }
Reverse Geocoding:
async function reverseGeocode(lat, lng) {
const response = await axios.get(
'https://maps.googleapis.com/maps/api/geocode/json',
{
params: {
latlng: `${lat},${lng}`,
key: GOOGLE_API_KEY
}
}
);
if (response.data.status !== 'OK') {
throw new Error(`Reverse geocoding failed: ${response.data.status}`);
}
return response.data.results[0].formatted_address;
}
const address = await reverseGeocode(37.4224764, -122.0842499);
// "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA"
With Component Filtering:
// Restrict to specific country
const response = await axios.get(
'https://maps.googleapis.com/maps/api/geocode/json',
{
params: {
address: 'Paris',
components: 'country:FR',
key: GOOGLE_API_KEY
}
}
);
Best For: Apps requiring the highest accuracy and global coverage.
2. Mapbox Geocoding API
Mapbox provides beautiful maps with powerful geocoding and a generous free tier.
Free Tier:
- 100,000 requests/month
- No credit card required
- Permanent places search
- Batch geocoding (50K/mo)
Key Features:
- Forward and reverse geocoding
- Autocomplete/typeahead
- Batch geocoding
- Custom data integration
- Bias by proximity
- Language support
JavaScript Example:
const mbxGeocoding = require('@mapbox/mapbox-sdk/services/geocoding');
const geocodingClient = mbxGeocoding({
accessToken: process.env.MAPBOX_ACCESS_TOKEN
});
async function geocode(query) {
const response = await geocodingClient.forwardGeocode({
query,
limit: 1,
types: ['address', 'place']
}).send();
const feature = response.body.features[0];
return {
placeName: feature.place_name,
coordinates: feature.center, // [lng, lat]
context: feature.context
};
}
// Usage
const result = await geocode('Empire State Building, New York');
console.log(result.coordinates);
// [-73.9857, 40.7484]
Autocomplete Search:
async function searchPlaces(query, proximity) {
const response = await geocodingClient.forwardGeocode({
query,
autocomplete: true,
limit: 5,
proximity: proximity, // [lng, lat] to bias results
types: ['poi', 'address', 'place']
}).send();
return response.body.features.map(f => ({
name: f.place_name,
coordinates: f.center,
category: f.properties.category
}));
}
// Search near user's location
const suggestions = await searchPlaces('coffee', [-73.99, 40.73]);
Batch Geocoding:
async function batchGeocode(addresses) {
// Mapbox batch geocoding via their API
const requests = addresses.map(addr =>
geocodingClient.forwardGeocode({ query: addr, limit: 1 }).send()
);
const results = await Promise.all(requests);
return results.map((r, i) => ({
input: addresses[i],
result: r.body.features[0]?.center || null
}));
}
Best For: Modern web apps with maps integration.
3. OpenCage Geocoding API
OpenCage aggregates multiple data sources with a focus on privacy and GDPR compliance.
Free Tier:
- 2,500 requests/day
- No credit card required
- HTTPS included
- All features available
Key Features:
- Multiple data sources (OSM, government data)
- GDPR compliant
- No tracking
- Annotations (timezone, currency, etc.)
- Bounds filtering
- 100+ languages
JavaScript Example:
const opencage = require('opencage-api-client');
async function geocode(address) {
const response = await opencage.geocode({
q: address,
key: process.env.OPENCAGE_API_KEY
});
if (response.results.length === 0) {
throw new Error('No results found');
}
const result = response.results[0];
return {
formatted: result.formatted,
lat: result.geometry.lat,
lng: result.geometry.lng,
confidence: result.confidence,
annotations: result.annotations
};
}
const location = await geocode('Brandenburg Gate, Berlin');
console.log(location.annotations.timezone);
// { name: "Europe/Berlin", offset_string: "+0100", ... }
With Bounds Filtering:
const response = await opencage.geocode({
q: 'Main Street',
key: process.env.OPENCAGE_API_KEY,
bounds: '-122.5,37.5,-122.0,38.0', // SW lng,lat to NE lng,lat
countrycode: 'us',
limit: 5
});
Annotations Example:
// OpenCage provides rich annotations
const result = await geocode('Tokyo, Japan');
console.log(result.annotations);
// {
// currency: { iso_code: "JPY", symbol: "¥" },
// timezone: { name: "Asia/Tokyo", offset_sec: 32400 },
// sun: { rise: { apparent: 1706, ... }, set: { ... } },
// what3words: { words: "skirt.presented.ranger" },
// flag: "🇯🇵"
// }
Best For: Privacy-focused apps and GDPR compliance.
4. Nominatim (OpenStreetMap)
Nominatim is the free geocoding service powered by OpenStreetMap data.
Free Tier:
- Unlimited (with rate limits)
- 1 request/second
- No API key required
- Self-hosting available
Key Features:
- Completely free
- OpenStreetMap data
- Self-hostable
- Good for open source projects
- Structured queries
- Address parsing
JavaScript Example:
const axios = require('axios');
// Using public Nominatim (respect rate limits!)
async function geocode(address) {
const response = await axios.get(
'https://nominatim.openstreetmap.org/search',
{
params: {
q: address,
format: 'json',
limit: 1,
addressdetails: 1
},
headers: {
'User-Agent': 'YourApp/1.0 (your@email.com)' // Required!
}
}
);
if (response.data.length === 0) {
throw new Error('No results found');
}
const result = response.data[0];
return {
displayName: result.display_name,
lat: parseFloat(result.lat),
lon: parseFloat(result.lon),
address: result.address,
type: result.type
};
}
const location = await geocode('Eiffel Tower, Paris');
Reverse Geocoding:
async function reverseGeocode(lat, lon) {
const response = await axios.get(
'https://nominatim.openstreetmap.org/reverse',
{
params: {
lat,
lon,
format: 'json',
addressdetails: 1
},
headers: {
'User-Agent': 'YourApp/1.0 (your@email.com)'
}
}
);
return {
displayName: response.data.display_name,
address: response.data.address
};
}
Structured Query:
// More precise results with structured query
const response = await axios.get(
'https://nominatim.openstreetmap.org/search',
{
params: {
street: '221B Baker Street',
city: 'London',
country: 'UK',
format: 'json'
},
headers: {
'User-Agent': 'YourApp/1.0'
}
}
);
Best For: Open source projects and self-hosted solutions.
5. HERE Geocoding API
HERE offers enterprise-grade geocoding with a generous free tier.
Free Tier:
- 250,000 requests/month
- All geocoding features
- No credit card required
Key Features:
- Autosuggest
- Batch geocoding
- Address parsing
- Quality scores
- Enterprise SLAs
- Traffic integration
JavaScript Example:
const axios = require('axios');
const HERE_API_KEY = process.env.HERE_API_KEY;
async function geocode(address) {
const response = await axios.get(
'https://geocode.search.hereapi.com/v1/geocode',
{
params: {
q: address,
apiKey: HERE_API_KEY
}
}
);
const item = response.data.items[0];
return {
title: item.title,
position: item.position,
address: item.address,
scoring: item.scoring
};
}
const result = await geocode('Statue of Liberty, New York');
console.log(result.position);
// { lat: 40.68927, lng: -74.04445 }
Autosuggest (Typeahead):
async function autosuggest(query, location) {
const response = await axios.get(
'https://autosuggest.search.hereapi.com/v1/autosuggest',
{
params: {
q: query,
at: `${location.lat},${location.lng}`,
limit: 5,
apiKey: HERE_API_KEY
}
}
);
return response.data.items.map(item => ({
title: item.title,
address: item.address?.label,
position: item.position,
distance: item.distance
}));
}
Best For: Enterprise apps needing reliability and SLAs.
6. LocationIQ
LocationIQ provides affordable geocoding using OpenStreetMap data with added features.
Free Tier:
- 5,000 requests/day
- 2 requests/second
- All basic features
Key Features:
- OSM-based data
- Balance API
- Autocomplete
- Nearby POI search
- Affordable paid plans
- Static maps
JavaScript Example:
const axios = require('axios');
const LOCATIONIQ_KEY = process.env.LOCATIONIQ_KEY;
async function geocode(address) {
const response = await axios.get(
'https://us1.locationiq.com/v1/search',
{
params: {
key: LOCATIONIQ_KEY,
q: address,
format: 'json',
limit: 1
}
}
);
const result = response.data[0];
return {
displayName: result.display_name,
lat: parseFloat(result.lat),
lon: parseFloat(result.lon),
importance: result.importance
};
}
Autocomplete:
async function autocomplete(query) {
const response = await axios.get(
'https://api.locationiq.com/v1/autocomplete',
{
params: {
key: LOCATIONIQ_KEY,
q: query,
limit: 5,
dedupe: 1
}
}
);
return response.data;
}
Best For: Budget-conscious developers needing reliable geocoding.
7. Geoapify
Geoapify offers geocoding with a focus on European data and GDPR compliance.
Free Tier:
- 3,000 requests/day
- Batch geocoding included
- All features available
Key Features:
- European focus
- GDPR compliant
- Batch geocoding
- Address autocomplete
- Isochrones
- Routing
JavaScript Example:
const axios = require('axios');
const GEOAPIFY_KEY = process.env.GEOAPIFY_KEY;
async function geocode(address) {
const response = await axios.get(
'https://api.geoapify.com/v1/geocode/search',
{
params: {
text: address,
apiKey: GEOAPIFY_KEY,
format: 'json'
}
}
);
const result = response.data.results[0];
return {
formatted: result.formatted,
lat: result.lat,
lon: result.lon,
country: result.country,
timezone: result.timezone
};
}
Batch Geocoding:
async function batchGeocode(addresses) {
const response = await axios.post(
`https://api.geoapify.com/v1/batch/geocode/search?apiKey=${GEOAPIFY_KEY}`,
addresses, // Array of address strings
{
headers: { 'Content-Type': 'application/json' }
}
);
// Returns a job URL for async processing
return response.data.url;
}
Best For: European apps and batch processing needs.
8. Positionstack
Positionstack offers simple, straightforward geocoding with a generous free tier.
Free Tier:
- 25,000 requests/month
- Forward geocoding
- Reverse geocoding
- Basic features
Key Features:
- Simple API
- No credit card required
- Global coverage
- JSON/XML output
- Batch requests (paid)
JavaScript Example:
const axios = require('axios');
const ACCESS_KEY = process.env.POSITIONSTACK_KEY;
async function geocode(address) {
const response = await axios.get(
'http://api.positionstack.com/v1/forward',
{
params: {
access_key: ACCESS_KEY,
query: address,
limit: 1
}
}
);
const result = response.data.data[0];
return {
label: result.label,
latitude: result.latitude,
longitude: result.longitude,
country: result.country,
region: result.region
};
}
const location = await geocode('1600 Pennsylvania Avenue, Washington DC');
Best For: Simple projects needing basic geocoding.
Geocoding Best Practices
1. Cache Results
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 86400 }); // 24 hour cache
async function geocodeWithCache(address) {
const cacheKey = `geo:${address.toLowerCase().trim()}`;
const cached = cache.get(cacheKey);
if (cached) return cached;
const result = await geocode(address);
cache.set(cacheKey, result);
return result;
}
2. Handle Rate Limits
const Bottleneck = require('bottleneck');
const limiter = new Bottleneck({
minTime: 1000, // 1 request per second
maxConcurrent: 1
});
const rateLimitedGeocode = limiter.wrap(geocode);
// Use rate-limited version
const results = await Promise.all(
addresses.map(addr => rateLimitedGeocode(addr))
);
3. Validate Coordinates
function isValidCoordinate(lat, lng) {
return (
typeof lat === 'number' &&
typeof lng === 'number' &&
lat >= -90 && lat <= 90 &&
lng >= -180 && lng <= 180 &&
!isNaN(lat) && !isNaN(lng)
);
}
Choosing the Right Geocoding API
| Need | Recommended |
|---|---|
| Best accuracy | Google Maps |
| Free + accurate | Mapbox |
| Privacy/GDPR | OpenCage |
| Completely free | Nominatim |
| Enterprise | HERE |
| Budget | LocationIQ |
| Europe focus | Geoapify |
| Simple projects | Positionstack |
Conclusion
For most developers, Mapbox offers the best balance of free tier limits and accuracy. If accuracy is critical, Google Maps remains the gold standard. For privacy-focused applications, OpenCage or self-hosted Nominatim are excellent choices.
Related Resources: