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.

2,500 free requests a day from any address, with no key and no account. Need more? Sign up with your name and email, add prepaid credit at €0.0001 per request, or take an Unlimited key for €50 a month (€500 a year, two months free). Cards and crypto accepted.

$ curl -H "X-API-Key: YOUR_KEY" "https://api.mygeocode.com/v1/reverse?lat=48.8584&lon=2.2945"
{
  "status": "ok",
  "lat": 48.8584,
  "lon": 2.2945,
  "result": {
    "formatted": "5 Avenue Anatole France, 75007 Paris, France",
    "lat": 48.858821,
    "lon": 2.294596,
    "distance_m": 47,
    "type": "address",
    "precision": "house",
    "confidence": 0.85,
    "place_id": "uaOpXczzaHCkNCaNUcKLUz6vyUB3_IjkyQ",
    "components": {
      "house_number": "5",
      "road": "Avenue Anatole France",
      "suburb": "7e arrondissement",
      "city": "Paris",
      "postcode": "75007",
      "country": "France",
      "country_code": "fr"
    },
    "bounds": { "north": 48.859321, "south": 48.858318, "east": 2.295098, "west": 2.294096 },
    "codes": {
      "plus_code": "8FW4V75V+GR",
      "geohash": "u09tunqz7bqg",
      "mgrs": "31UDQ4825912001",
      "maidenhead": "JN18du56",
      "dms": {
        "lat": "48° 51' 31.8\" N",
        "lon": "2° 17' 40.5\" E"
      },
      "mapcode": "FRA 4H.QX",
      "mapcode_international": "VHPM8.QYF6"
    }
  }
}
2,500free requests a day, no key needed
€0.0001per request in prepaid credit
€50a month for an Unlimited key
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, 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 252 countries and territories.

See the level for every country

LevelWhat the point represents
houseThe house asked for: on the building or parcel where the address data has it, or placed along its street from the street's number range.
streetThe street, when the house itself could not be answered.
postcodeThe centre of the postal code area.
city, region, countryThe centre of the town, 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.

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 the map drawn on free OpenStreetMap tiles and nothing charged for loading the library. 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.

$ 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

Keys are optional

An email address is the whole signup

Any address gets 2,500 free requests a day with no key at all, across all endpoints and drop-in hosts, measured from 00:00 UTC. A key takes a minute when you want one: sign up with your name, an email address and a password, confirm the address from the email we send, and your first key is waiting in the dashboard. No company, no card. An account gets 2,500 free requests a day, shared by all of its keys. Requests made without a key from the same network share that allowance too, so an account adds credit, packages and a usage history, not a second free 2,500.

Keys are tied to the machines that use them. A pay-as-you-go key serves two IP addresses in any rolling 24 hours, an Unlimited key three. Each address holds its slot for 24 hours from its first request and then frees it. A request from a further address is refused and not counted, which is what stops a leaked key from being useful to anyone else. Need more addresses? Create more keys or add packages.

  1. Sign up, get a key

    Email and password. The key stays in the dashboard, so you can copy it again at any time. 2,500 requests a day, free, from up to two IP addresses.

  2. Add credit when you need more

    Top up €10, €25, €50 or €100 by card or crypto. Requests above your account's free allowance take €0.0001 each from the balance. Credit never expires and nothing is charged automatically.

  3. Or take an Unlimited key

    €50 a month, or €500 a year with two months free, buys a key with no per-request charges, usable from three IP addresses per rolling 24 hours. Order as many packages as you have applications.

Pricing

Free to start, simple to pay for

Every endpoint costs the same. Every drop-in host counts the same. No tiers, no per-seat charges, no contract. Prices in euros, paid by card or crypto.

Free key

2,500 requests a day per account, shared by all your keys. Sign up with your name and email; no card. Same data and the same endpoints as paid usage.

Credit

€0.0001 per request above your account's 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 €0.75 of credit.

Unlimited key

€50 a month, or €500 a year (two months free). A key with no per-request charges across every endpoint and every drop-in host, from up to three IP addresses per rolling 24 hours.

Full pricing and worked examples

SDKs

Client libraries

Client libraries for JavaScript and TypeScript, Python, PHP, Go, Java, C#, Ruby and Rust will stay small: typed responses, sensible timeouts and retries on 429 and 503. Each one goes on the SDK page with its install command when it is released.

Follow SDK progress

Do I need a key to try it?

No. Any address gets 2,500 requests a day with no key and no account. The demo page sends requests straight from the browser without one. A free key takes a minute when you want credit, an Unlimited package or a usage history.

What happens at request 2,501?

If your account has credit, the request goes through and uses €0.0001 of it. If it does not, you get HTTP 402 until 00:00 UTC or until you top up. On an Unlimited key nothing changes.

Why is a key limited to two or three IP addresses?

Keys are meant for servers, and the limit means a key that leaks into a public repository cannot be used from a hundred machines. Each address holds its slot for 24 hours from its first request, then the slot frees. A pay-as-you-go key has two slots, an Unlimited key three. For more machines, create more keys or add packages.

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 with your key and opens the JSON response. A free key takes your name, an email address and a minute; when you outgrow 2,500 a day, top up credit or add an Unlimited key.