Geocoding, IP and timezone lookups over one plain HTTP API

Turn addresses into coordinates and back, find out where an IPv4 or IPv6 address sits, get the timezone or elevation of any point, and resolve postal codes. Send a GET request, read the JSON. Nothing to install.

Try it before you buy anything: 2,500 requests a day are always free, with no API key and no account. Need more? Sign up with an email address, nothing else, and add credits at $0.001 per request, or go Unlimited for €50 a month. Cards and crypto accepted.

$ curl "https://api.mygeocode.com/v1/reverse?lat=48.8584&lon=2.2945"
{
  "status": "ok",
  "result": {
    "formatted": "5 Avenue Anatole France, 75007 Paris, France",
    "lat": 48.85837,
    "lon": 2.29448,
    "distance_m": 12,
    "precision": "house",
    "components": {
      "house_number": "5",
      "road": "Avenue Anatole France",
      "city": "Paris",
      "postcode": "75007",
      "country": "France",
      "country_code": "fr"
    }
  }
}
2,500free requests a day, always
$0.001per request in prepaid credits
€50a month for unlimited requests
17drop-in hosts for other providers' APIs
Endpoints

Eight lookups, one base URL

Every endpoint lives under https://api.mygeocode.com/v1/, takes query parameters, and returns JSON with the same envelope. Learn one and you know them all.

Accuracy

Every result says how precise it is

A geocoder that returns a city centre when you asked for a house number is worse than one that says it could not find the house. Each result we return carries a precision field with one of four values, so your code can decide what to do with a coarse match instead of guessing.

Coverage is not the same everywhere, and we would rather show you than make a blanket claim. The coverage page lists the best level we reach in each of 249 countries and territories.

See the level for every country

LevelWhat the point represents
houseThe building or parcel itself. The point sits on the property.
streetA position along the street, interpolated from the house number range of that block.
postcodeThe centre of the postal code area.
adminThe centre of the city, district, region or country, whichever is the most specific match we could make.
Migration

Already using someone else's API? Change the hostname.

We run drop-in hosts that accept the same paths and parameters as Google Maps, Bing Maps, HERE, Mapbox, Geocode.Farm, Nominatim and eleven others, and answer in their response format with our data. Your parsing code does not change. Put your My Geocode key where the old key went, or leave it out for the free tier.

Before
$ curl "https://maps.googleapis.com/maps/api/geocode/json?address=10+Downing+St+London&key=GOOGLE_KEY"
After
$ curl "https://gapi.mygeocode.com/maps/api/geocode/json?address=10+Downing+St+London&key=MYGEOCODE_KEY"

The same idea works for JavaScript libraries. Load the Google Maps JavaScript API from gapi.mygeocode.com and google.maps.Map, Geocoder and Places Autocomplete keep working, with map loads that cost nothing. There are loaders for the Bing Maps V8 control, HERE Maps for JavaScript and MapQuest.js, and settings for MapLibre, Mapbox GL and Leaflet geocoder plugins.

  • Google Maps
  • Bing Maps
  • HERE
  • Mapbox
  • Geocode.Farm
  • Nominatim
  • OpenCage
  • LocationIQ
  • Geoapify
  • TomTom
  • MapQuest
  • Geocodio
  • PositionStack
  • ip-api
  • ipinfo
  • ipstack
  • Open-Elevation

REST drop-ins JavaScript drop-ins

Any language

If it can send an HTTP request, it can use this

No SDK is needed. These examples geocode an address and print its coordinates. Official libraries for each language are on the way and will stay thin wrappers around these same calls.

$ curl "https://api.mygeocode.com/v1/forward?q=221B+Baker+Street,+London"

# With a key, once you have one
$ curl -H "X-API-Key: YOUR_KEY" "https://api.mygeocode.com/v1/forward?q=221B+Baker+Street,+London"
const url = new URL("https://api.mygeocode.com/v1/forward");
url.searchParams.set("q", "221B Baker Street, London");

const res = await fetch(url, { headers: { "X-API-Key": process.env.MYGEOCODE_KEY } });
const data = await res.json();

const [first] = data.results;
console.log(first.lat, first.lon, first.precision);
import os
import requests

r = requests.get(
    "https://api.mygeocode.com/v1/forward",
    params={"q": "221B Baker Street, London"},
    headers={"X-API-Key": os.environ["MYGEOCODE_KEY"]},
    timeout=10,
)
r.raise_for_status()
first = r.json()["results"][0]
print(first["lat"], first["lon"], first["precision"])
<?php
$url = "https://api.mygeocode.com/v1/forward?" . http_build_query([
    "q" => "221B Baker Street, London",
]);

$context = stream_context_create(["http" => ["header" => "X-API-Key: " . getenv("MYGEOCODE_KEY")]]);
$data = json_decode(file_get_contents($url, false, $context), true);

$first = $data["results"][0];
echo $first["lat"], ", ", $first["lon"], " (", $first["precision"], ")\n";
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
)

func main() {
	q := url.Values{"q": {"221B Baker Street, London"}}
	req, _ := http.NewRequest("GET", "https://api.mygeocode.com/v1/forward?"+q.Encode(), nil)
	req.Header.Set("X-API-Key", os.Getenv("MYGEOCODE_KEY"))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var data struct {
		Results []struct {
			Lat       float64 `json:"lat"`
			Lon       float64 `json:"lon"`
			Precision string  `json:"precision"`
		} `json:"results"`
	}
	json.NewDecoder(resp.Body).Decode(&data)
	fmt.Println(data.Results[0].Lat, data.Results[0].Lon, data.Results[0].Precision)
}
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class Geocode {
    public static void main(String[] args) throws Exception {
        String q = URLEncoder.encode("221B Baker Street, London", StandardCharsets.UTF_8);
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.mygeocode.com/v1/forward?q=" + q))
            .header("X-API-Key", System.getenv("MYGEOCODE_KEY"))
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}
using System.Net.Http;
using System.Text.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("MYGEOCODE_KEY"));

var q = Uri.EscapeDataString("221B Baker Street, London");
var json = await client.GetStringAsync($"https://api.mygeocode.com/v1/forward?q={q}");

using var doc = JsonDocument.Parse(json);
var first = doc.RootElement.GetProperty("results")[0];
Console.WriteLine($"{first.GetProperty("lat")}, {first.GetProperty("lon")} ({first.GetProperty("precision")})");
require "net/http"
require "json"

uri = URI("https://api.mygeocode.com/v1/forward")
uri.query = URI.encode_www_form(q: "221B Baker Street, London")

req = Net::HTTP::Get.new(uri)
req["X-API-Key"] = ENV["MYGEOCODE_KEY"]
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }

first = JSON.parse(res.body)["results"][0]
puts "#{first["lat"]}, #{first["lon"]} (#{first["precision"]})"

See the SDK plans and full examples for each language

Try before you buy

Start with nothing. Sign up with an email when you need more.

Usage is counted per IP address, so the free tier needs no key, no account and no card. Each IPv4 address gets 2,500 requests a day across all endpoints and drop-in hosts, measured from midnight UTC. IPv6 usage is counted per /40 block rather than per address, because one customer can hold billions of addresses and we would rather not let a single script eat the whole pool.

When you want more than that, an account takes an email address and nothing else. No name, no company, no card until you decide to add credits. Pay by card or in crypto.

  1. Use it. No key, no account.

    2,500 requests a day from each IPv4 address or IPv6 /40, on every endpoint. Enough to build the whole integration and run a small site.

  2. Add credits when you need more

    Sign up with an email, top up whenever you like, and credits are used only for requests above the free 2,500 a day, even when you use an API key. Whitelist your server IPs, or use a key, which works from up to two IP addresses per 24 hours.

  3. Or go Unlimited

    €50 a month, as many requests as you need, from up to two IP addresses per 24 hours per account.

Pricing

Free to try, simple to pay for

Every endpoint costs the same. Every drop-in host counts the same. No tiers, no per-seat charges, no contract. Cards and crypto accepted.

Free, always

2,500 requests a day. No key, no account, no card. Counted per IPv4 address or IPv6 /40. Accounts get the same 2,500 a day before any credits are used.

Credits

$0.001 per request above the free 2,500 each day, taken from a balance you top up whenever you like. No monthly fee, no expiry. 10,000 requests in a day use $7.50 of credit.

Unlimited

€50 a month. As many requests as you need across every endpoint and every drop-in host, from up to two IP addresses per 24 hours per account.

Full pricing and worked examples

SDKs

Official libraries, one per language, all thin

We are writing small client libraries for JavaScript and TypeScript, Python, PHP, Go, Java, C#, Ruby and Rust. Each will give you typed responses, sensible timeouts, retries on 429 and 503, and nothing else. When one is ready it goes on the SDK page with its install command.

Follow SDK progress

Do I need a key to try it?

No. Send a request from any machine and it counts toward that machine's 2,500 a day. The demo page does exactly that from your browser.

What happens at request 2,501?

Without an account you get HTTP 429 until midnight UTC. With an account and credits, the request goes through and uses one credit ($0.001). On the Unlimited plan, nothing changes.

Why is a key limited to two IPs?

Keys are meant for servers. Limiting a key to two addresses in any 24 hour window means a key that leaks into a public repository cannot be used from a hundred machines. On credits, whitelisting server addresses has no limit. On the Unlimited plan the two-address limit applies to the whole account.

Can I store the results?

Yes. Cache them, save them in your database, show them on a map from another provider. The terms only ask that you do not resell the raw data as a geocoding service of your own.

Send your first request now

The demo sends live requests from your browser and opens the JSON response. No account, no key, no card. When you outgrow 2,500 a day, signing up takes an email address and nothing more.