GET /v1/geocode
Overview
Forward geocoding converts a street address, place name, or search query into geographic coordinates. The API returns up to 50 results ranked by relevance, powered by OpenStreetMap data.
Request
GET https://api.geocodeme.net/v1/geocode
Required header: X-Api-Key: gm_YOUR_API_KEY
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Yes | n/a | Address or place name to geocode |
limit | integer | No | 5 | Maximum number of results to return (1 to 50). Higher values increase response size. There is no pagination: all results are returned in a single response. |
countrycodes | string | No | n/a | Comma-separated ISO 3166-1 alpha-2 codes restricting results within the covered area (e.g. de, es,pt). Region aliases (gp, mq, gf, yt, re, eu) choose which regional index is searched; every other code is applied on top as a country filter. The two compose, and mixing them only ever narrows (eu,de returns the same results as de while querying one instance instead of six), whereas a second code of the same kind widens, as a list should (de,es, gp,mq). fr is a country code, not an alias: it means all French data, mainland and overseas. Codes outside the covered area return no results. See Region aliases and country filters. |
format | string | No | json | Response format: json or geojson |
Region aliases and country filters
countrycodes carries two independent decisions, and they combine:
- where to search. The region aliases
gp(Guadeloupe),mq(Martinique),gf(French Guiana),yt(Mayotte),re(Réunion) andeu(continental Europe) each select one regional index. They are resolved by our router and never forwarded to the search engine. With no alias in the list, all six regional instances are queried. - what to keep. Every other code (
de,es,pt,fr…) is forwarded as a country filter, read as a logical OR, and applied inside the instances selected above.
Mixing the two kinds always narrows. Add a country code to an alias and you keep the same area, filtered; add an alias to a country code and you keep the same filter over a smaller area. Neither can widen the answer.
Adding a code of the same kind widens, exactly as a list should: several aliases search several regions (gp,mq covers both islands), and several country codes are read as a logical OR (de,es returns German and Spanish results).
countrycodes | Instances queried | Country filter | What you get |
|---|---|---|---|
| (absent) | all six | none | the whole covered area |
de | all six | de | German results; only the continental index holds any |
eu | continental only | none | anything in continental Europe |
eu,de | continental only | de | the same results as de, from one instance instead of six |
fr | all six | fr | all French data: mainland and the five overseas regions |
fr,eu | continental only | fr | mainland France only, a strict subset of fr |
gp | Guadeloupe only | none | anything in Guadeloupe |
gp,mq | Guadeloupe + Martinique | none | anything in those two islands |
gp,de | Guadeloupe only | de | empty: you asked for German addresses in Guadeloupe |
eu,zz | continental only | zz | empty: zz is not a covered country |
Codes are case-insensitive, surrounding spaces are ignored, duplicates are removed and the forwarded filter is sorted, so eu,de, de,eu and EU, DE are one and the same request.
An unrecognised or uncovered code is never silently discarded: it stays a filter and produces an honest empty list rather than a broader answer.
Latency tip. If you already know the country is in continental Europe, prefixing the alias (eu,de instead of de) narrows the fan-out from six instances to one for an identical result.
/v1/autocomplete selects, but cannot filter/v1/autocomplete reads the same aliases and follows the same selection rule: an alias chooses the index that is searched, and a code can only ever bring in the index it designates; mixing kinds never widens there either, while a second alias does (gp,mq). gp,fr narrows to Guadeloupe there exactly as it does here, and fr,eu searches the continental index on both.
What it has not got is the filter half of the composition: its suggestion engine has no country filter to forward, so a code that is not an alias selects nothing rather than restricting anything. Two consequences if you share countrycodes values between the endpoints:
eu,dereturns all of continental Europe there; Germany only here.- a value that contains no alias returns no suggestion at all there:
deandfr,deboth come back empty, where heredereturns German results andfr,dereturns French or German ones.
Filter suggestions client-side on address.country_code.
Code Examples
- cURL
- Python
- JavaScript
- PHP
curl -H "X-Api-Key: gm_YOUR_API_KEY" \
"https://api.geocodeme.net/v1/geocode?q=10%20Rue%20de%20Rivoli%2C%20Paris&limit=3"
import os
import requests
api_key = os.environ["GEOCODEME_API_KEY"]
response = requests.get(
"https://api.geocodeme.net/v1/geocode",
params={"q": "10 Rue de Rivoli, Paris", "limit": 3},
headers={"X-Api-Key": api_key},
)
response.raise_for_status()
data = response.json()
for result in data["results"]:
print(f"{result['display_name']} ({result['lat']}, {result['lon']})")
const apiKey = process.env.GEOCODEME_API_KEY;
const response = await fetch(
"https://api.geocodeme.net/v1/geocode?q=10%20Rue%20de%20Rivoli%2C%20Paris&limit=3",
{ headers: { "X-Api-Key": apiKey } }
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
for (const result of data.results) {
console.log(`${result.display_name} (${result.lat}, ${result.lon})`);
}
<?php
$apiKey = getenv('GEOCODEME_API_KEY');
$url = 'https://api.geocodeme.net/v1/geocode?' . http_build_query([
'q' => '10 Rue de Rivoli, Paris',
'limit' => 3,
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-Api-Key: $apiKey"]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("HTTP $httpCode: $response");
}
$data = json_decode($response, true);
foreach ($data['results'] as $result) {
echo $result['display_name'] . " ({$result['lat']}, {$result['lon']})\n";
}
Response
All responses include rate limiting headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Monthly-Remaining, etc.).
JSON Response
{
"results": [
{
"lat": 48.8566,
"lon": 2.3522,
"name": null,
"display_name": "10, Rue de Rivoli, 4e Arrondissement, Paris, Île-de-France, 75004, France",
"type": "house",
"importance": 0.62,
"address": {
"house_number": "10",
"road": "Rue de Rivoli",
"city": "Paris",
"state": "Île-de-France",
"postcode": "75004",
"country": "France",
"country_code": "fr"
}
}
],
"attribution": "© OpenStreetMap contributors",
"meta": {
"took_ms": 45,
"cache_hit": false
}
}
GeoJSON Response
When format=geojson, the response is a standard GeoJSON FeatureCollection:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3522, 48.8566]
},
"properties": {
"name": null,
"display_name": "10, Rue de Rivoli, 4e Arrondissement, Paris, Île-de-France, 75004, France",
"type": "house",
"importance": 0.62,
"address": {
"house_number": "10",
"road": "Rue de Rivoli",
"city": "Paris",
"state": "Île-de-France",
"postcode": "75004",
"country": "France",
"country_code": "fr"
}
}
}
],
"attribution": "© OpenStreetMap contributors",
"meta": {
"took_ms": 45,
"cache_hit": false
}
}
Schema
Top-level response
| Field | Type | Description |
|---|---|---|
results | array | Array of GeocodingResult objects |
attribution | string | Always "© OpenStreetMap contributors" |
meta | object | Request metadata |
meta.took_ms | integer | Server processing time in milliseconds |
meta.cache_hit | boolean | Whether the response was served from cache |
GeocodingResult
| Field | Type | Description |
|---|---|---|
lat | float | Latitude of the result |
lon | float | Longitude of the result |
name | string | null | Proper name of the place, from the OpenStreetMap name tag; null when the object has no name. See The name field |
display_name | string | Full human-readable address |
type | string | OSM place type (e.g. house, road, city, building); may be null |
importance | float | Relevance score between 0 and 1; may be null |
address | object | Structured address components; may be null |
The name field
name is a top-level field carrying the OpenStreetMap name tag of the object: "Musée du Louvre", "École élémentaire Jules Ferry", "Boulangerie Chez Momo". It is not an address component and never appears inside address.
{
"lat": 48.8606,
"lon": 2.3376,
"name": "Musée du Louvre",
"display_name": "Musée du Louvre, Rue de Rivoli, 1er Arrondissement, Paris, Île-de-France, 75001, France",
"type": "museum",
"importance": 0.83
}
nullwhen the object has nonametag: the usual case for a plain street or a numbered address. The field is always present in the payload, with the JSON valuenull, never an empty string.- Different from
type, which carries the OSM category (museum,school,bakery,house): the two are complementary, not redundant. - Different from the head of
display_name. Usenameas the title of a result anddisplay_nameas the address line underneath; never splitdisplay_nameon its first comma to obtain a title; on10, Rue de Rivoli, …that yields10.
The same field, with the same contract, is returned by /v1/reverse and /v1/autocomplete. With format=geojson it sits in properties, just before display_name.
Address
All fields are optional and depend on the location:
| Field | Type | Description |
|---|---|---|
house_number | string | House or building number |
road | string | Street name |
city | string | City name |
town | string | Town name (alternative to city for smaller settlements) |
village | string | Village name (alternative to city for rural areas) |
county | string | County or district |
state | string | State or region |
postcode | string | Postal or ZIP code |
country | string | Country name |
country_code | string | ISO 3166-1 alpha-2 country code (e.g. fr) |
Error Responses
The most common errors for this endpoint:
Missing q parameter
{
"error": {
"code": "MISSING_PARAMETER",
"message": "Required parameter 'q' is missing",
"field": "q"
}
}
Invalid API key
{
"error": {
"code": "INVALID_API_KEY",
"message": "API key missing or invalid"
}
}
For the full error reference, see Error Codes.