Forward and Reverse Geocoding API
Overview
The OpenCage Geocoding API provides reverse (lat/long to text) and forward (text to lat/long) geocoding via a RESTful API.Behind the scenes we query multiple geocoders from various open datasources - see the full list - to answer your request.
Quick Start
1. Sign up for your API key 2. Start geocoding by requesting a URL:-
Reverse geocoding
https://api.opencagedata.com/geocode/v1/json?q=LAT+LNG&key=YOUR-API-KEY
-
Forward geocoding
https://api.opencagedata.com/geocode/v1/json?q=PLACENAME&key=YOUR-API-KEY
For all the details of optional parameters, rate limiting, SDKs and tutorials for 30+ programing languages, best practices, migrating from Google Maps geocoding, and much more please see below.
You may also find our demo page helpful.
Authentication
Using the OpenCage geocoder API requires a
valid API key that you must pass with each HTTP request
to the API as the value of the
key
parameter (one of two
required parameters).
Rate/Usage Limits
The OpenCage geocoding API uses a rate limiting mechanism to ensure that the service stays available to all users.
Free trial usage limits:
Free trial accounts are limited to 2,500 requests per day for testing purposes. Our day is based on the UTC timezone. Your daily count resets at midnight (24:00 UTC - see the current UTC time).
For the avoidance of any doubt: if you are regularly depending on our service, you are not testing, and should become a customer.
Paid usage limits:
If you wish to use our geocoding API at high volume or on an ongoing basis, become a customer. We have two different pricing models: subscriptions and one-time purchases. Please see our pricing page for the exact options.
Here we discuss the technical differences of the API response for customers
with hard limits (free trial users and one-time customers) and those
without hard limits (subscription customers).
Responses to subscription customers do
NOT
contain the
rate
element of the response body or
X-Ratelimit
HTTP headers,
as subscription customers do not face 'hard'
limits. For details please see the Q&A section of
Pricing & Billing FAQ.
Quota information / seeing your usage:
A graph of daily usage is shown in your account dashboard.
Real-time quota information for free trial accounts and one-time purchase
customers is returned by the API in both the
rate
element of the response body and HTTP response headers.
If you send a request after you have reached your limit, a response with
status of
402 - Payment Required
will be returned in both the HTTP headers and
status
field.
If you are not a customer and
continually request beyond the free trial usage limit (ie you ignore the
402
status) you will eventually be blocked and see a
403 - Forbidden
response, so don't do that. Thanks.
Please see below for
a full list of all possible response codes
and
various API keys
you can use to generate a
402
or
403
response for testing.
Rate information in the response body
Here is an example (in JSON format) of the information in the API response body
"rate" : {
"limit" : 2500,
"remaining" : 2498,
"reset" : 1605312000
},
limit
is the number of requests you can make per day.
remaining
is the number of requests you have remaining.
reset
is the Unix time at which your count will reset.
Rate Limit HTTP Headers
X-RateLimit-Limit
|
the total number of API requests that your account is limited to over the given time period (24 hours for free trials) |
X-RateLimit-Remaining
|
the number of API requests remaining in the given time period |
X-RateLimit-Reset
|
the time, in UNIX time format, at which your request count will reset |
Requests per second
Free trial users are limited to 1 request per second and if you exceed that rate you may be blocked. Paying customers can use our service at a much faster rate, ranging from 15-40 requests per second depending on pricing tier. Please see the exact levels on our pricing page. If you need more than 40 requests per second (our Large subscription) that is possible, but please get in touch to discuss your exact needs. If you request too quickly you will eventually see a429 - Too many requests
response. Please see below for
a full list of all possible response codes
and
an API key
you can use to generate a
429
response for testing.
Request Format
A geocoder API request is in the following form:
https://api.opencagedata.com/geocode/version/format?parameters
Both the HTTP 1.1 and HTTP/2 protocols are supported.
All requests should use the HTTP
GET
method. Requests that use other methods will recieve a response
with status
405 - Method not allowed
.
Both
http
and
https
schemes are supported. We strongly recommend
https
as requests made using
http
are not encrypted.
https
requests need to use TLS 1.2 or higher. Requests that use an older
(insecure) TLS will receive a response with
status
426 - Upgrade required (unsupported TLS)
.
The
version
component of the URL should be replaced with a version of the format
v + version number
.
The current version is
v1
.
Requests with an incorrect version number will receive a response with
status
400 - not a valid version
.
The
format
component of the URL should be replaced with one of the following:
json
|
the geocoder response will be returned as JSON. |
geojson
|
the geocoder response will be returned as GeoJSON. |
xml
|
the geocoder response will be returned as XML. |
google-v3-json
|
the geocoder request supports a subset of the
Google v3 Geocoding API
and returns a JSON response that it compatible with Google's. Please
note we provide this format as a general convenience and do not
actively maintain it. It is not widely used and may be discontinued.
We encourage you to use the
json
or
xml
format. Please see
details of our Google compatibility
.
|
400 - not a valid format
.
Request Parameters
Required Parameters
key
|
a 30 character long, alphanumeric string.
Example usage:
key=YOUR-API-KEY
You will find your API key in your account dashboard.
Sign up for an API key
By default accounts are limited to one key per account.
Subscription customers can have multiple API keys.
Please see our guide to protecting your API key(s). |
q
|
the query string to be geocoded: a latitude, longitude or
a placename/address.
The query should be
URL encoded.
Instead of, for example, non-ascii strings like
München
you should send us
M%C3%BCnchen .
When
reverse geocoding
the query should be in latitude, longitude
order in decimal format. Use periods as decimals, not commas.
Reverse geocoding example usage:
q=51.952659,7.632473
There is no reason to send more than six or seven digits past
the decimal as that is down to the precision of a centimeter -
see Wikipedia about decimal degree precision.
If impossible coordinates are supplied you will receive a
response with status
400 invalid coordinates .
Forward geocoding example usage:
q=Berlin%2C%20Germany
When
forward geocoding
there are many things you can do to help improve our chance of finding
the correct answer and answering more quickly.
Please note:
|
Optional Parameters
abbrv
|
When set to 1 we attempt to abbreviate and shorten the
formatted
string we return. Learn more about
formatted placenames.
Example usage:
abbrv=1
Are we missing abbreviations in your language? If so please help us
by
contributing improvements.
Thanks!
|
add_request
|
When set to 1 the various request parameters are added to the response
for ease of debugging.
Example usage:
add_request=1
|
bounds
|
Used only for forward geocoding.
This value will restrict the possible results to a defined bounding box.
The value of the
bounds
parameter should be specified as two coordinate points
forming the south-west and north-east corners of a
bounding box (min lon, min lat, max lon, max lat).
Example usage:
bounds=-0.563160,51.280430,0.278970,51.683979
Values that are not valid coordinates are ignored.
We have built
a small, map-based tool
to easily see bounds values.
|
countrycode
|
Used only for forward geocoding. Restricts results to the specified
country/territory or countries.
Example usage:
countrycode=de
The country code is a two letter code as defined by the
ISO 3166-1 Alpha 2
standard. E.g.
gb
for the United Kingdom,
fr
for France,
us
for United States.
Non-two letter country codes are ignored.
You can specify multiple country codes by supplying a comma separated
list. For example
countrycode=ca,us
would limit results to either the United States or Canada.
Please note, many territories have their own ISO 3116-1 codes, despite
being part of another country. An example is Puerto Rico which has ISO
code
PR ,
despite being part of the United States,
US .
In the
components
portion of results we return both -
see details below.
Many parts of the world have complex or even disputed political
structures and/or share postal systems with another country, and thus
may be treated as a single or multiple country by some of the
geocoders we rely upon. It may make sense to specify multiple country
codes.
As an example, when searching for locations on the island of Aruba -
technically a constituent country of the
Kingdom of the Netherlands
-
we will do better if you specify
countrycode=aw,nl
rather than just
countrycode=aw .
As a convenience we have compiled
a list of country codes for dependent territories.
|
jsonp
|
Wraps the
returned JSON with a function name.
Example usage:
jsonp=myfuncname
If you are calling our service via AJAX you may also find
our documentation on CORS headers
and/or
our jQuery tutorial
helpful.
|
language
|
An
IETF format language code
(such as
es
for Spanish or
pt-BR
for Brazilian Portuguese), or
native
in which case we will attempt to return the response in the local
language(s).
Example usage:
language=de
If no language is explicitly specified, we will then look for an HTTP
Accept-Language
header like those sent by a browser and use highest quality language specified (please see
RFC 4647
for details). If the request did not specify a valid header, then
en
(English) will be assumed.
Please note, setting the
language
parameter does NOT mean results will only be returned in the specified
language. Instead it means we will attempt to favour results in that
language.
Please see
our detailed comments on language below,
particularly the caviats around specifying
language=native .
|
limit
|
The maximum number of results we should return. Default is 10.
Maximum allowable value is 100.
Example usage:
limit=1
|
min_confidence
|
An integer from 1-10. Only results with at least this confidence
will be returned. Learn more about our
confidence score.
Example usage:
min_confidence=3
|
no_annotations
|
When set to 1 results will not contain
annotations.
Example usage:
no_annotations=1
The only exception is if the optional
roadinfo
parameter is set (see below).
|
no_dedupe
|
When set to 1 results will not be deduplicated.
Example usage:
no_dedupe=1
|
no_record
|
When set to 1 the query contents are not logged. Please use this
parameter if you have concerns about privacy and want us to have no
record of your query.
Example usage:
no_record=1
|
pretty
|
When set to 1 results are 'pretty' printed for easier reading.
Useful for debugging.
Example usage:
pretty=1
|
proximity
|
Used only for forward geocoding.
Provides the geocoder with a hint to bias results in favour of those
closer to the specified location. Please note though, this is just one
of many factors in the internal scoring we use for ranking results.
The value is a point with latitude, longitude coordinates in decimal
format.
Example usage:
proximity=51.952659,7.632473
Values that are not valid coordinates are ignored.
|
roadinfo
|
When set to 1 the behaviour of the geocoder is changed to attempt to
match the nearest road (as opposed to address). If possible we also
fill additional information in the
roadinfo
annotation. Please see
details below.
Example usage:
roadinfo=1
|
Response Format
The API response is formatted
according to the contents of the
format
component of the request URL.
The response can vary slightly depending on which, if any, of
the optional request parameters
are used, and
whether or not you are a subscription customer.
All returned coordinates use WGS 84 (sometimes also known as EPSG:4326) as reference coordinate system.
Some developers prefer to use API inspection tools to examine the API response. We have tutorials for accessing the API via Postman or via Insomnia.
Here are example responses to reverse and forward geocoding requests with no optional parameters:
Reverse Geocoding Response Format
JSON Output
In the following example, a response in JSON format is requested to get the nearest address for coordinates -22.6792, 14.5272.https://api.opencagedata.com/geocode/v1/json?q=-22.6792%2C+14.5272&key=YOUR-API-KEY&pretty=1
The JSON returned by the reverse geocoder will look like:
{
"documentation" : "https://opencagedata.com/api",
"licenses" : [
{
"name" : "see attribution guide",
"url" : "https://opencagedata.com/credits"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2473,
"reset" : 1613001600
},
"results" : [
{
"annotations" : {
"DMS" : {
"lat" : "22\u00b0 40' 45.05736'' S",
"lng" : "14\u00b0 31' 36.48576'' E"
},
"MGRS" : "33KVQ5139191916",
"Maidenhead" : "JG77gh36fx",
"Mercator" : {
"x" : 1617116.157,
"y" : -2576798.589
},
"OSM" : {
"edit_url" : "https://www.openstreetmap.org/edit?node=4488973891#map=16/-22.67918/14.52680",
"note_url" : "https://www.openstreetmap.org/note/new#map=16/-22.67918/14.52680&layers=N",
"url" : "https://www.openstreetmap.org/?mlat=-22.67918&mlon=14.52680#map=16/-22.67918/14.52680"
},
"UN_M49" : {
"regions" : {
"AFRICA" : "002",
"NA" : "516",
"SOUTHERN_AFRICA" : "018",
"SUB-SAHARAN_AFRICA" : "202",
"WORLD" : "001"
},
"statistical_groupings" : [
"LEDC"
]
},
"callingcode" : 264,
"currency" : {
"alternate_symbols" : [
"N$"
],
"decimal_mark" : ".",
"disambiguate_symbol" : "N$",
"format" : "%n %u",
"html_entity" : "$",
"iso_code" : "NAD",
"iso_numeric" : "516",
"name" : "Namibian Dollar",
"smallest_denomination" : 5,
"subunit" : "Cent",
"subunit_to_unit" : 100,
"symbol" : "$",
"symbol_first" : 0,
"thousands_separator" : ","
},
"flag" : "\ud83c\uddf3\ud83c\udde6",
"geohash" : "k7fqfx6h5jbq5tn8tnpn",
"qibla" : 31.02,
"roadinfo" : {
"drive_on" : "left",
"road" : "Woermann St",
"speed_in" : "km/h"
},
"sun" : {
"rise" : {
"apparent" : 1612932540,
"astronomical" : 1612927800,
"civil" : 1612931160,
"nautical" : 1612929480
},
"set" : {
"apparent" : 1612978980,
"astronomical" : 1612983720,
"civil" : 1612980360,
"nautical" : 1612982040
}
},
"timezone" : {
"name" : "Africa/Windhoek",
"now_in_dst" : 0,
"offset_sec" : 7200,
"offset_string" : "+0200",
"short_name" : "CAT"
},
"what3words" : {
"words" : "integrate.laughter.teller"
}
},
"bounds" : {
"northeast" : {
"lat" : -22.6791326,
"lng" : 14.5268516
},
"southwest" : {
"lat" : -22.6792326,
"lng" : 14.5267516
}
},
"components" : {
"ISO_3166-1_alpha-2" : "NA",
"ISO_3166-1_alpha-3" : "NAM",
"_category" : "commerce",
"_type" : "restaurant",
"city" : "Swakopmund",
"continent" : "Africa",
"country" : "Namibia",
"country_code" : "na",
"postcode" : "13001",
"restaurant" : "Beryl's Restaurant",
"road" : "Woermann St",
"state" : "Erongo Region",
"suburb" : "Central"
},
"confidence" : 9,
"formatted" : "Beryl's Restaurant, Woermann St, Swakopmund 13001, Namibia",
"geometry" : {
"lat" : -22.6791826,
"lng" : 14.5268016
}
}
],
"status" : {
"code" : 200,
"message" : "OK"
},
"stay_informed" : {
"blog" : "https://blog.opencagedata.com",
"twitter" : "https://twitter.com/OpenCage"
},
"thanks" : "For using an OpenCage API",
"timestamp" : {
"created_http" : "Wed, 10 Feb 2021 06:57:06 GMT",
"created_unix" : 1612940226
},
"total_results" : 1
}
GeoJSON Output
In the following example, a response in GeoJSON format is requested for coordinates -22.6792, 14.5272.https://api.opencagedata.com/geocode/v1/geojson?q=-22.6792%2C+14.5272&key=YOUR-API-KEY&pretty=1
The GeoJSON response:
{
"documentation" : "https://opencagedata.com/api",
"features" : [
{
"geometry" : {
"coordinates" : [
14.5268016,
-22.6791826
],
"type" : "Point"
},
"properties" : {
"annotations" : {
"DMS" : {
"lat" : "22\u00b0 40' 45.05736'' S",
"lng" : "14\u00b0 31' 36.48576'' E"
},
"MGRS" : "33KVQ5139191916",
"Maidenhead" : "JG77gh36fx",
"Mercator" : {
"x" : 1617116.157,
"y" : -2576798.589
},
"OSM" : {
"edit_url" : "https://www.openstreetmap.org/edit?node=4488973891#map=16/-22.67918/14.52680",
"note_url" : "https://www.openstreetmap.org/note/new#map=16/-22.67918/14.52680&layers=N",
"url" : "https://www.openstreetmap.org/?mlat=-22.67918&mlon=14.52680#map=16/-22.67918/14.52680"
},
"UN_M49" : {
"regions" : {
"AFRICA" : "002",
"NA" : "516",
"SOUTHERN_AFRICA" : "018",
"SUB-SAHARAN_AFRICA" : "202",
"WORLD" : "001"
},
"statistical_groupings" : [
"LEDC"
]
},
"callingcode" : 264,
"currency" : {
"alternate_symbols" : [
"N$"
],
"decimal_mark" : ".",
"disambiguate_symbol" : "N$",
"format" : "%n %u",
"html_entity" : "$",
"iso_code" : "NAD",
"iso_numeric" : "516",
"name" : "Namibian Dollar",
"smallest_denomination" : 5,
"subunit" : "Cent",
"subunit_to_unit" : 100,
"symbol" : "$",
"symbol_first" : 0,
"thousands_separator" : ","
},
"flag" : "\ud83c\uddf3\ud83c\udde6",
"geohash" : "k7fqfx6h5jbq5tn8tnpn",
"qibla" : 31.02,
"roadinfo" : {
"drive_on" : "left",
"road" : "Woermann St",
"speed_in" : "km/h"
},
"sun" : {
"rise" : {
"apparent" : 1612932540,
"astronomical" : 1612927800,
"civil" : 1612931160,
"nautical" : 1612929480
},
"set" : {
"apparent" : 1612978980,
"astronomical" : 1612983720,
"civil" : 1612980360,
"nautical" : 1612982040
}
},
"timezone" : {
"name" : "Africa/Windhoek",
"now_in_dst" : 0,
"offset_sec" : 7200,
"offset_string" : "+0200",
"short_name" : "CAT"
},
"what3words" : {
"words" : "integrate.laughter.teller"
}
},
"bounds" : {
"northeast" : {
"lat" : -22.6791326,
"lng" : 14.5268516
},
"southwest" : {
"lat" : -22.6792326,
"lng" : 14.5267516
}
},
"components" : {
"ISO_3166-1_alpha-2" : "NA",
"ISO_3166-1_alpha-3" : "NAM",
"_category" : "commerce",
"_type" : "restaurant",
"city" : "Swakopmund",
"continent" : "Africa",
"country" : "Namibia",
"country_code" : "na",
"postcode" : "13001",
"restaurant" : "Beryl's Restaurant",
"road" : "Woermann St",
"state" : "Erongo Region",
"suburb" : "Central"
},
"confidence" : 9,
"formatted" : "Beryl's Restaurant, Woermann St, Swakopmund 13001, Namibia"
},
"type" : "Feature"
}
],
"licenses" : [
{
"name" : "see attribution guide",
"url" : "https://opencagedata.com/credits"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2471,
"reset" : 1613001600
},
"status" : {
"code" : 200,
"message" : "OK"
},
"stay_informed" : {
"blog" : "https://blog.opencagedata.com",
"twitter" : "https://twitter.com/OpenCage"
},
"thanks" : "For using an OpenCage API",
"timestamp" : {
"created_http" : "Wed, 10 Feb 2021 06:57:06 GMT",
"created_unix" : 1612940226
},
"total_results" : 1,
"type" : "FeatureCollection"
}
Learn more about
the GeoJSON format.
XML Output
In the following example, a response in XML format is requested for coordinates -22.6792, 14.5272.https://api.opencagedata.com/geocode/v1/xml?q=-22.6792%2C+14.5272&key=YOUR-API-KEY&pretty=1
The XML returned by the reverse geocoder will look like:
<response>
<documentation>https://opencagedata.com/api</documentation>
<licenses>
<license>
<name>see attribution guide</name>
<url>https://opencagedata.com/credits</url>
</license>
</licenses>
<rate>
<limit>2500</limit>
<remaining>2472</remaining>
<reset>1613001600</reset>
</rate>
<results>
<result>
<annotations>
<DMS>
<lat>22° 40' 45.05736'' S</lat>
<lng>14° 31' 36.48576'' E</lng>
</DMS>
<MGRS>33KVQ5139191916</MGRS>
<Maidenhead>JG77gh36fx</Maidenhead>
<Mercator>
<x>1617116.157</x>
<y>-2576798.589</y>
</Mercator>
<OSM>
<edit_url>https://www.openstreetmap.org/edit?node=4488973891#map=16/-22.67918/14.52680</edit_url>
<note_url>https://www.openstreetmap.org/note/new#map=16/-22.67918/14.52680&layers=N</note_url>
<url>https://www.openstreetmap.org/?mlat=-22.67918&mlon=14.52680#map=16/-22.67918/14.52680</url>
</OSM>
<UN_M49>
<regions>
<AFRICA>002</AFRICA>
<NA>516</NA>
<SOUTHERN_AFRICA>018</SOUTHERN_AFRICA>
<SUB-SAHARAN_AFRICA>202</SUB-SAHARAN_AFRICA>
<WORLD>001</WORLD>
</regions>
<statistical_groupings>LEDC</statistical_groupings>
</UN_M49>
<callingcode>264</callingcode>
<currency>
<alternate_symbols>N$</alternate_symbols>
<decimal_mark>.</decimal_mark>
<disambiguate_symbol>N$</disambiguate_symbol>
<format>%n %u</format>
<html_entity>$</html_entity>
<iso_code>NAD</iso_code>
<iso_numeric>516</iso_numeric>
<name>Namibian Dollar</name>
<smallest_denomination>5</smallest_denomination>
<subunit>Cent</subunit>
<subunit_to_unit>100</subunit_to_unit>
<symbol>$</symbol>
<symbol_first>0</symbol_first>
<thousands_separator>,</thousands_separator>
</currency>
<flag>🇳🇦</flag>
<geohash>k7fqfx6h5jbq5tn8tnpn</geohash>
<qibla>31.02</qibla>
<roadinfo>
<drive_on>left</drive_on>
<road>Woermann St</road>
<speed_in>km/h</speed_in>
</roadinfo>
<sun>
<rise>
<apparent>1612932540</apparent>
<astronomical>1612927800</astronomical>
<civil>1612931160</civil>
<nautical>1612929480</nautical>
</rise>
<set>
<apparent>1612978980</apparent>
<astronomical>1612983720</astronomical>
<civil>1612980360</civil>
<nautical>1612982040</nautical>
</set>
</sun>
<timezone>
<name>Africa/Windhoek</name>
<now_in_dst>0</now_in_dst>
<offset_sec>7200</offset_sec>
<offset_string>+0200</offset_string>
<short_name>CAT</short_name>
</timezone>
<what3words>
<words>integrate.laughter.teller</words>
</what3words>
</annotations>
<bounds>
<northeast>
<lat>-22.6791326</lat>
<lng>14.5268516</lng>
</northeast>
<southwest>
<lat>-22.6792326</lat>
<lng>14.5267516</lng>
</southwest>
</bounds>
<components>
<ISO_3166-1_alpha-2>NA</ISO_3166-1_alpha-2>
<ISO_3166-1_alpha-3>NAM</ISO_3166-1_alpha-3>
<_category>commerce</_category>
<_type>restaurant</_type>
<city>Swakopmund</city>
<continent>Africa</continent>
<country>Namibia</country>
<country_code>na</country_code>
<postcode>13001</postcode>
<restaurant>Beryl's Restaurant</restaurant>
<road>Woermann St</road>
<state>Erongo Region</state>
<suburb>Central</suburb>
</components>
<confidence>9</confidence>
<formatted>Beryl's Restaurant, Woermann St, Swakopmund 13001, Namibia</formatted>
<geometry>
<lat>-22.6791826</lat>
<lng>14.5268016</lng>
</geometry>
</result>
</results>
<status>
<code>200</code>
<message>OK</message>
</status>
<stay_informed>
<blog>https://blog.opencagedata.com</blog>
<twitter>https://twitter.com/OpenCage</twitter>
</stay_informed>
<thanks>For using an OpenCage API</thanks>
<timestamp>
<created_http>Wed, 10 Feb 2021 06:57:06 GMT</created_http>
<created_unix>1612940226</created_unix>
</timestamp>
<total_results>1</total_results>
</response>
Forward Geocoding Response Format
JSON Output
In the following example, a response in JSON format is requested for the query Carapicuíba, Brasil.https://api.opencagedata.com/geocode/v1/json?q=Rua+Cafel%C3%A2ndia%2C+Carapicu%C3%ADba%2C+Brasil&key=YOUR-API-KEY&pretty=1
The JSON returned by the geocoder will look like:
{
"documentation" : "https://opencagedata.com/api",
"licenses" : [
{
"name" : "see attribution guide",
"url" : "https://opencagedata.com/credits"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2477,
"reset" : 1613001600
},
"results" : [
{
"annotations" : {
"DMS" : {
"lat" : "23\u00b0 32' 14.49456'' S",
"lng" : "46\u00b0 50' 14.81748'' W"
},
"MGRS" : "23KLP1242695791",
"Maidenhead" : "GG66nl91ma",
"Mercator" : {
"x" : -5213921.006,
"y" : -2680076.588
},
"OSM" : {
"edit_url" : "https://www.openstreetmap.org/edit?way=185327107#map=17/-23.53736/-46.83745",
"note_url" : "https://www.openstreetmap.org/note/new#map=17/-23.53736/-46.83745&layers=N",
"url" : "https://www.openstreetmap.org/?mlat=-23.53736&mlon=-46.83745#map=17/-23.53736/-46.83745"
},
"UN_M49" : {
"regions" : {
"AMERICAS" : "019",
"BR" : "076",
"LATIN_AMERICA" : "419",
"SOUTH_AMERICA" : "005",
"WORLD" : "001"
},
"statistical_groupings" : [
"LEDC"
]
},
"callingcode" : 55,
"currency" : {
"decimal_mark" : ",",
"html_entity" : "R$",
"iso_code" : "BRL",
"iso_numeric" : "986",
"name" : "Brazilian Real",
"smallest_denomination" : 5,
"subunit" : "Centavo",
"subunit_to_unit" : 100,
"symbol" : "R$",
"symbol_first" : 1,
"thousands_separator" : "."
},
"flag" : "\ud83c\udde7\ud83c\uddf7",
"geohash" : "6gydn5nhbq4kzymuw0zu",
"qibla" : 69.01,
"roadinfo" : {
"drive_on" : "right",
"road" : "Rua Cafel\u00e2ndia",
"road_type" : "residential",
"speed_in" : "km/h"
},
"sun" : {
"rise" : {
"apparent" : 1612947240,
"astronomical" : 1612942440,
"civil" : 1612945800,
"nautical" : 1612944120
},
"set" : {
"apparent" : 1612993740,
"astronomical" : 1612998540,
"civil" : 1612995180,
"nautical" : 1612996800
}
},
"timezone" : {
"name" : "America/Sao_Paulo",
"now_in_dst" : 0,
"offset_sec" : -10800,
"offset_string" : "-0300",
"short_name" : "BRT"
},
"what3words" : {
"words" : "younger.jingles.cheerful"
}
},
"bounds" : {
"northeast" : {
"lat" : -23.5370411,
"lng" : -46.835665
},
"southwest" : {
"lat" : -23.5373596,
"lng" : -46.8374493
}
},
"components" : {
"ISO_3166-1_alpha-2" : "BR",
"ISO_3166-1_alpha-3" : "BRA",
"_category" : "road",
"_type" : "road",
"city" : "Carapicu\u00edba",
"city_district" : "Carapicu\u00edba",
"continent" : "South America",
"country" : "Brazil",
"country_code" : "br",
"county" : "Regi\u00e3o Metropolitana de S\u00e3o Paulo",
"municipality" : "Regi\u00e3o Imediata de S\u00e3o Paulo",
"postcode" : "06321-665",
"region" : "Southeast Region",
"road" : "Rua Cafel\u00e2ndia",
"road_type" : "residential",
"state" : "S\u00e3o Paulo",
"state_code" : "SP",
"state_district" : "Regi\u00e3o Geogr\u00e1fica Intermedi\u00e1ria de S\u00e3o Paulo",
"suburb" : "Parque Jos\u00e9 Alexandre"
},
"confidence" : 9,
"formatted" : "Rua Cafel\u00e2ndia, Parque Jos\u00e9 Alexandre, Carapicu\u00edba - SP, 06321-665, Brazil",
"geometry" : {
"lat" : -23.5373596,
"lng" : -46.8374493
}
}
],
"status" : {
"code" : 200,
"message" : "OK"
},
"stay_informed" : {
"blog" : "https://blog.opencagedata.com",
"twitter" : "https://twitter.com/OpenCage"
},
"thanks" : "For using an OpenCage API",
"timestamp" : {
"created_http" : "Wed, 10 Feb 2021 06:57:05 GMT",
"created_unix" : 1612940225
},
"total_results" : 1
}
GeoJSON Output
In the following example, a response in GeoJSON format is requested for Carapicuíba, Brasil.https://api.opencagedata.com/geocode/v1/geojson?q=Rua+Cafel%C3%A2ndia%2C+Carapicu%C3%ADba%2C+Brasil&key=YOUR-API-KEY&pretty=1
The GeoJSON response:
{
"documentation" : "https://opencagedata.com/api",
"features" : [
{
"geometry" : {
"coordinates" : [
-46.8374493,
-23.5373596
],
"type" : "Point"
},
"properties" : {
"annotations" : {
"DMS" : {
"lat" : "23\u00b0 32' 14.49456'' S",
"lng" : "46\u00b0 50' 14.81748'' W"
},
"MGRS" : "23KLP1242695791",
"Maidenhead" : "GG66nl91ma",
"Mercator" : {
"x" : -5213921.006,
"y" : -2680076.588
},
"OSM" : {
"edit_url" : "https://www.openstreetmap.org/edit?way=185327107#map=17/-23.53736/-46.83745",
"note_url" : "https://www.openstreetmap.org/note/new#map=17/-23.53736/-46.83745&layers=N",
"url" : "https://www.openstreetmap.org/?mlat=-23.53736&mlon=-46.83745#map=17/-23.53736/-46.83745"
},
"UN_M49" : {
"regions" : {
"AMERICAS" : "019",
"BR" : "076",
"LATIN_AMERICA" : "419",
"SOUTH_AMERICA" : "005",
"WORLD" : "001"
},
"statistical_groupings" : [
"LEDC"
]
},
"callingcode" : 55,
"currency" : {
"decimal_mark" : ",",
"html_entity" : "R$",
"iso_code" : "BRL",
"iso_numeric" : "986",
"name" : "Brazilian Real",
"smallest_denomination" : 5,
"subunit" : "Centavo",
"subunit_to_unit" : 100,
"symbol" : "R$",
"symbol_first" : 1,
"thousands_separator" : "."
},
"flag" : "\ud83c\udde7\ud83c\uddf7",
"geohash" : "6gydn5nhbq4kzymuw0zu",
"qibla" : 69.01,
"roadinfo" : {
"drive_on" : "right",
"road" : "Rua Cafel\u00e2ndia",
"road_type" : "residential",
"speed_in" : "km/h"
},
"sun" : {
"rise" : {
"apparent" : 1612947240,
"astronomical" : 1612942440,
"civil" : 1612945800,
"nautical" : 1612944120
},
"set" : {
"apparent" : 1612993740,
"astronomical" : 1612998540,
"civil" : 1612995180,
"nautical" : 1612996800
}
},
"timezone" : {
"name" : "America/Sao_Paulo",
"now_in_dst" : 0,
"offset_sec" : -10800,
"offset_string" : "-0300",
"short_name" : "BRT"
},
"what3words" : {
"words" : "younger.jingles.cheerful"
}
},
"bounds" : {
"northeast" : {
"lat" : -23.5370411,
"lng" : -46.835665
},
"southwest" : {
"lat" : -23.5373596,
"lng" : -46.8374493
}
},
"components" : {
"ISO_3166-1_alpha-2" : "BR",
"ISO_3166-1_alpha-3" : "BRA",
"_category" : "road",
"_type" : "road",
"city" : "Carapicu\u00edba",
"city_district" : "Carapicu\u00edba",
"continent" : "South America",
"country" : "Brazil",
"country_code" : "br",
"county" : "Regi\u00e3o Metropolitana de S\u00e3o Paulo",
"municipality" : "Regi\u00e3o Imediata de S\u00e3o Paulo",
"postcode" : "06321-665",
"region" : "Southeast Region",
"road" : "Rua Cafel\u00e2ndia",
"road_type" : "residential",
"state" : "S\u00e3o Paulo",
"state_code" : "SP",
"state_district" : "Regi\u00e3o Geogr\u00e1fica Intermedi\u00e1ria de S\u00e3o Paulo",
"suburb" : "Parque Jos\u00e9 Alexandre"
},
"confidence" : 9,
"formatted" : "Rua Cafel\u00e2ndia, Parque Jos\u00e9 Alexandre, Carapicu\u00edba - SP, 06321-665, Brazil"
},
"type" : "Feature"
}
],
"licenses" : [
{
"name" : "see attribution guide",
"url" : "https://opencagedata.com/credits"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2474,
"reset" : 1613001600
},
"status" : {
"code" : 200,
"message" : "OK"
},
"stay_informed" : {
"blog" : "https://blog.opencagedata.com",
"twitter" : "https://twitter.com/OpenCage"
},
"thanks" : "For using an OpenCage API",
"timestamp" : {
"created_http" : "Wed, 10 Feb 2021 06:57:06 GMT",
"created_unix" : 1612940226
},
"total_results" : 1,
"type" : "FeatureCollection"
}
Learn more about
the GeoJSON format.
XML Output
In the following example, a response in XML format is requested for Carapicuíba, Brasil.https://api.opencagedata.com/geocode/v1/xml?q=Rua+Cafel%C3%A2ndia%2C+Carapicu%C3%ADba%2C+Brasil&key=YOUR-API-KEY&pretty=1
The XML returned by the geocoder looks like:
<response>
<documentation>https://opencagedata.com/api</documentation>
<licenses>
<license>
<name>see attribution guide</name>
<url>https://opencagedata.com/credits</url>
</license>
</licenses>
<rate>
<limit>2500</limit>
<remaining>2476</remaining>
<reset>1613001600</reset>
</rate>
<results>
<result>
<annotations>
<DMS>
<lat>23° 32' 14.49456'' S</lat>
<lng>46° 50' 14.81748'' W</lng>
</DMS>
<MGRS>23KLP1242695791</MGRS>
<Maidenhead>GG66nl91ma</Maidenhead>
<Mercator>
<x>-5213921.006</x>
<y>-2680076.588</y>
</Mercator>
<OSM>
<edit_url>https://www.openstreetmap.org/edit?way=185327107#map=16/-23.53736/-46.83745</edit_url>
<note_url>https://www.openstreetmap.org/note/new#map=16/-23.53736/-46.83745&layers=N</note_url>
<url>https://www.openstreetmap.org/?mlat=-23.53736&mlon=-46.83745#map=16/-23.53736/-46.83745</url>
</OSM>
<UN_M49>
<regions>
<AMERICAS>019</AMERICAS>
<BR>076</BR>
<LATIN_AMERICA>419</LATIN_AMERICA>
<SOUTH_AMERICA>005</SOUTH_AMERICA>
<WORLD>001</WORLD>
</regions>
<statistical_groupings>LEDC</statistical_groupings>
</UN_M49>
<callingcode>55</callingcode>
<currency>
<decimal_mark>,</decimal_mark>
<html_entity>R$</html_entity>
<iso_code>BRL</iso_code>
<iso_numeric>986</iso_numeric>
<name>Brazilian Real</name>
<smallest_denomination>5</smallest_denomination>
<subunit>Centavo</subunit>
<subunit_to_unit>100</subunit_to_unit>
<symbol>R$</symbol>
<symbol_first>1</symbol_first>
<thousands_separator>.</thousands_separator>
</currency>
<flag>🇧🇷</flag>
<geohash>6gydn5nhbq4kzymuw0zu</geohash>
<qibla>69.01</qibla>
<roadinfo>
<drive_on>right</drive_on>
<road>Rua Cafelândia</road>
<road_type>residential</road_type>
<speed_in>km/h</speed_in>
</roadinfo>
<sun>
<rise>
<apparent>1612947240</apparent>
<astronomical>1612942440</astronomical>
<civil>1612945800</civil>
<nautical>1612944120</nautical>
</rise>
<set>
<apparent>1612993740</apparent>
<astronomical>1612998540</astronomical>
<civil>1612995180</civil>
<nautical>1612996800</nautical>
</set>
</sun>
<timezone>
<name>America/Sao_Paulo</name>
<now_in_dst>0</now_in_dst>
<offset_sec>-10800</offset_sec>
<offset_string>-0300</offset_string>
<short_name>BRT</short_name>
</timezone>
<what3words>
<words>younger.jingles.cheerful</words>
</what3words>
</annotations>
<bounds>
<northeast>
<lat>-23.5370411</lat>
<lng>-46.835665</lng>
</northeast>
<southwest>
<lat>-23.5373596</lat>
<lng>-46.8374493</lng>
</southwest>
</bounds>
<components>
<ISO_3166-1_alpha-2>BR</ISO_3166-1_alpha-2>
<ISO_3166-1_alpha-3>BRA</ISO_3166-1_alpha-3>
<_category>road</_category>
<_type>road</_type>
<city>Carapicuíba</city>
<city_district>Carapicuíba</city_district>
<continent>South America</continent>
<country>Brazil</country>
<country_code>br</country_code>
<county>Região Metropolitana de São Paulo</county>
<municipality>Região Imediata de São Paulo</municipality>
<postcode>06321-665</postcode>
<region>Southeast Region</region>
<road>Rua Cafelândia</road>
<road_type>residential</road_type>
<state>São Paulo</state>
<state_code>SP</state_code>
<state_district>Região Geográfica Intermediária de São Paulo</state_district>
<suburb>Parque José Alexandre</suburb>
</components>
<confidence>9</confidence>
<formatted>Rua Cafelândia, Parque José Alexandre, Carapicuíba - SP, 06321-665, Brazil</formatted>
<geometry>
<lat>-23.5373596</lat>
<lng>-46.8374493</lng>
</geometry>
</result>
</results>
<status>
<code>200</code>
<message>OK</message>
</status>
<stay_informed>
<blog>https://blog.opencagedata.com</blog>
<twitter>https://twitter.com/OpenCage</twitter>
</stay_informed>
<thanks>For using an OpenCage API</thanks>
<timestamp>
<created_http>Wed, 10 Feb 2021 06:57:05 GMT</created_http>
<created_unix>1612940225</created_unix>
</timestamp>
<total_results>1</total_results>
</response>
Best Practices
General advice:-
Save yourself a lot of time by not reinventing the wheel.
Use one of the many libraries that already exist for accessing our API. -
If you do not need the information provided in the annotations
please set
no_annotations=1
.
This enables us to do less work and significantly reduces the response size and thus reply more quickly.
In our guide to geocoding more quickly we outline a few more strategies for speed. -
If you are geocoding non-English locations, please don't forget to set
the optional
language
parameter - see details. - Program defensively. We are aggregating data from many rapidly-changing data sources. While we make every effort to clean things up, your code should be as forgiving as possible.
- If you are geocoding any significant volume, please read our guide to geocoding large datasets.
- Changes to the API are very rare, but if you are depending on our service please "watch" our public Changelog on Github, so you are notified when we announce and changes.
-
It helps us greatly is you can format your query well.
Please see our detailed guide on how to format your forward geocoding query. -
We are much more likely to give you a correct answer if you are able
to use the
bounds
and/orcountrycode
parameters as this lets us route the search better and narrow the results considerably. -
We may return multiple relevant results.
Please see our
guide to understanding geocoding accuracy
to learn strategies for deciding which result is the one you want.
If you plan to
only look at the first result and disregard the others then please set
limit=1
as this enables us to only return a single result. We thus do less work and the response size is smaller. -
If the request comes from a mobile device whose
location you know or a user viewing a map please consider using the
optional
proximity
parameter to bias results to the user's location or the location the user is viewing.
Ranking of Results
We may return multiple results for a forward geocoding query. Results are returned in order of most relevant to least. Results are NOT ordered byconfidence
score (see
definition of confidence score).
Reverse geocoding requests return at most one result.
Fuzzy matching / Autosuggest
Many people confuse forward geocoding with geosearch. Geocoding expects an address or placename as an input. Geosearch takes any string of text as input and tries to extract locations from that string or to expand the string and return a list of possible location matches. Our API is designed for geocoding, we do NOT perform "fuzzy" matching. As an example, a request with querypar
will NOT return
Paris, France
as a result.
We do NOT offer an "autosuggest" or "typeahead" functionality for
search forms. We have experimented with building such a service in the past,
but our experience is that consumer expectation is a full "Google search"
style search box which will match any restaurant, landmark, etc in
any language anywhere in the world. That is a significant
technical challenge requiring an immense dataset and deep experience in
search (as opposed to just geo). All of our testing showed it was not (yet!)
possible for us to provide the level of experience consumers expected.
Rather than provide a poor geosearch experience we focus our efforts on
geocoding. We are a screwdriver. You will be frustrating if you try to use us
as a hammer.
Geocoding Confidence
The OpenCage geocoding API will always attempt to find a match for as many parts of a query as it can, but this isn't always possible. Where a partial match is made, for example a street name can be matched but not the specific house number, the we will still return a result.
The precision of a match is returned in the
confidence
field.
Please note:
confidence is
NOT
used for
ranking of the results.
It does not tell you which result is more "correct", nor what type of
thing the result is - for that please check
the components portion of the result.
The confidence score is an integer value between
0
and
10
, where
0
reflects inability to determine a confidence (due to lack of a
bounding box),
1
indicates low precision, and
10
indicates high precision.
Confidence is calculated by measuring the distance between the southwest
and northeast corners of each result's bounding box. Then an adjustment
may be made to reflect the ambiguity of the underlying geocoder.
Please note, confidence is not the way to determine the type of place
that was matched, for that please use the
_type
field of the
components portion of the response.
The best way to think of our confidence score is as a measure of how confident we are that centre point coordinates returned for the result precisely reflect the result. So for example, if you search for "Berlin, Germany", we know exactly where that is, but it has a confidence of only 4, as Berlin is a large city ( and Bundesland, but that's another story). The coordinates we return are in the centre of the bounding box, but it would be valid to consider anywhere in that box to be "Berlin", hence the relatively low confidence score.
You can supply the optional
min_confidence
parameter (see
optional parameter details).
10
|
< 0.25 km distance |
9
|
< 0.5 km |
8
|
< 1 km |
7
|
< 5 km |
6
|
< 7.5 km |
5
|
< 10 km |
4
|
< 15 km |
3
|
< 20 km |
2
|
< 25 km |
1
|
25 km or greater distance |
0
|
unable to determine a bounding box; thus unable to determine a confidence |
Ambiguous Results
When forward geocoding we may find multiple valid matches for a query. Many places have the same or similar names. In this case we return multiple results ranked by relevance. See our comments on how results are ranked. Please see our detailed guide to understanding geocoding accuracy which outlines some strategies to determine whether a result from an ambiguous query is sufficiently correct to warrant using or not. Note: Reverse geocoding requests return at most one result.No Results
In cases where the geocoder cannot find any match
for a request, we will return a successful
status (a response code of
200
)
but the number of results in the response will
be zero. You can test this situation by sending a request with the query
NOWHERE-INTERESTING
which will return a valid response with 0 results.
Response Codes
The
status
element of the response contains the following:
code
|
a three digit error code |
message
|
a brief, human-readable explanation of the error code |
The following status codes are possible:
code |
meaning
check message
in API response for specific details
|
200
|
OK (zero or more results will be returned) |
400
|
Invalid request (bad request; a required parameter is missing; invalid coordinates; invalid version; invalid format) |
401
|
Unable to authenticate - missing, invalid, or unknown API key |
402
|
Valid request but quota exceeded (payment required) |
403
|
Forbidden (API key disabled or IP address rejected) |
404
|
Invalid API endpoint |
405
|
Method not allowed (non-GET request) |
408
|
Timeout; you can try again |
410
|
Request too long |
426
|
Upgrade required (unsupported TLS) |
429
|
Too many requests (too quickly, rate limiting) |
503
|
Internal server error |
API keys for testing
For testing purposes you can use the following API keys:-
6d0e711d72d74daeb2b0bfd2a5cdfdba
which will always generate a200 - OK
response.
Note the response will be as if theq
parameter of the request had been51.952659,7.632473
regardless of what was actually specified.
Sample request using this API key -
4372eff77b8343cebfc843eb4da4ddc4
which will always generate a402 - quota exceeded
response.
Sample request using this API key -
2e10e5e828262eb243ec0b54681d699a
which will always generate a403 - disabled
response.
Sample request using this API key -
6c79ee8e1ca44ad58ad1fc493ba9542f
which will always generate a403 - IP address rejected
response.
Sample request using this API key -
d6d0f0065f4348a4bdfe4587ba02714b
which will always generate a429 - requesting too quickly
response.
Sample request using this API key
Formatted Placename and Components
For each result we supply a
formatted
field which contains a well formatted version of the place name. We attempt
to display the name of the location in a way that would make sense to
humans. This is difficult in that across the world there are many
different ways to format an address. For more background please
read our blog post on the topic.
We welcome your contributions to the
open-source templates we use to tackle the address formatting problem.
We will attempt to shorten or abbreviate the formatted string
if the optional parameter
abbrv
is supplied, this can be useful if screenspace is limited - for example
on a mobile device. The various abbreviations are all open-sourced in the
code repository linked above.
The
formatted
placename is created from the various terms in the
components
hash. This is the raw data we have to work with.
We are often asked if there is a definitive list of all possible
component keys. Unfortunately not -
read why not.
For convenience we add the key
_type
with the value set to what we believe the matched location to be.
In the case where, for whatever reason, we can't determine a type
we set the value
unknown
.
Common possible values of
_type
include
building, road, village, neighbourhood, city, county, postcode, partial_postcode, terminated_postcode, postal_city, state_district, state, region, island, body_of_water, country, continent, fictitious, unknown
.
Please note: just because a result has a certain
_type
does NOT mean there is a key of that type in the components list.
Various types get mapped together. As an example
town
gets mapped to
_type : city
.
See
the list of mappings.
We also set a
_category
key and value, based on mapping the value of
_type
.
See a
full list of the possible _category values.
If the result is a road - ie
_type
has the value
road
- if possible we also return a
road_type
key with values like those
generally used in OpenStreetMap.
If you are interested in road information, please read details on
getting more road / driving information.
Finally, when possible we set the keys
ISO_3166-1_alpha-2
,
ISO_3166-1_alpha-3
,
and
continent
.
Possible values for
continent
are
Africa, Antarctica, Asia, Europe, Oceania, North America, South America
.
Caching
Feel free to cache, or store, results as long as you like, you know your use case and whether or not it makes sense. That said, the world is a constantly changing place and the underlying datasets, like OpenStreetMap, that we're querying are always evolving, so it may make sense to refresh your cache regularly. For ease of caching every response has atimestamp
section with both a human readable HTTP timestamp - in the
created_http
key, and a unix timestamp - in the
created_unix
key.
Customers often ask us when it makes sense to cache. In the case of
forward geocoding you can look at a normalized version of the request.
In the case of reverse though it is not so clear cut.
If two coordinates are the same to X places past the decimal, should
you not bother with a request? This depends of course on what level
of granularity you need in a response. There is almost no reason to go
beyond six or seven places past the decimal as that then gets down to
the precision of a centimeter.
See Wikipedia about decimal degree precision.
Our experience is that caching makes sense at the device level. For
example if you are doing fleet tracking and the vehicle is parked, there
is no reason to continually request the identical coordinates. So it makes
sense to keep a record of the last 20 or 50 or whatever positions and then
only request if the coordinates have changed. Beyond that caching for
reverse requests is not particularly useful as the number of potential
requests is so massive that direct hits are rare.
Whether or not caching makes sense largely depends on your
use case. You'll have to test and see what works for you.
Caching is only one of several ways to speed things up. Please see our
guide to geocoding more quickly
where we outline a strategies to optimze for speed.
Language
Many places have different names in different languages. To tell us you
favour results in a specific language please use the optional
language
parameter, otherwise we will default to the language of your browser
or, if no browser language is specified, English.
See the section on optional parameters
for a detailed explanation of how we determine which language to favour.
We rely on many different datasets. Some, like OpenStreetMap, tend to
have results in many languages. Others tend to have results only in
English. Specifying
language
does not mean we will return results purely in that language, only
that we will do our best to favour such results if we have them.
If you specify
language=native
we will attempt to return results in the local language. As an example,
instead of
Munich
you will receive
München
.
Please be aware that the geocoders we build upon typically use the
"official" language of the country, which may not actually be the language
spoken locally.
Also, many countries have multiple "official" languages.
As an example, instead of returning
Belgium
as we would for a request with
language=en
we would return
België / Belgique / Belgien
for a request with
language=native
.
Nearest Road / Speed Limit Information
Many of our clients use our service for vehicle or fleet tracking,
and are interested in information about the roads the vehicles are
travelling on.
To simplify this use case we offer the optional parameter
roadinfo
.
Setting this optional parameter (adding
roadinfo=1
to your request) has a few implications:
- The behaviour of the geocoder changes to try to match the nearest road rather than the nearest address. This behaviour is often known as "snap to road". You will likely get different results if this parameter is set.
-
We will add the
roadinfo
annotation to the response, regardless of whether the optional parameterno_annotations
is set or not. Please see the roadinfo annotation documentation for the exact list of fields we attempt to return.
Note: the information we return comes from crowdsourced databases like
OpenStreetMap. It should NOT be taken as official governmental data. It
may be out of date or simply wrong, and especially the speed limit in the
maxspeed
key may have many caveats, for example different
speed limits depending on time of day, time of year, weather conditions,
type of vehicle, etc.
The results are provided for informational purposes only and common sense should always be used. Always drive safely.
Annotations
By defaults each result contains anannotations
section which supplies additional information about the result location.
We believe this is one of the easiest ways to make life
simpler for geo-developers, which is of course the whole point of our
service.
Annotations can be turned off by setting the optional
no_annotations
parameter (with the exception of
roadinfo
,
please see below for details), and we recommend you do so if you don't
need them as it means we can respond to your query a tiny bit faster.
Please note:
-
The annotations reflect information derived based on
the coordinates of the result.
These may differ from the coordinates of the request. -
Some annotations, for example
currency
, depend on the coordinates being in a country.
These annotations will not be supplied for results that do not lie inside the boundaries of any country, for example in the middle of an ocean. - The information in the annotations may come from different sources of variable coverage. We do the best we can, but please don't assume we will always be able to provide the same level of information everywhere.
We provide the following annotations:
callingcode
|
the international telephone calling code for the country of the result. |
currency
|
information about the local currency |
DMS
|
the latitude and longitude of the center point of the result in degree minute decimal second format |
FIPS
|
contains the US Federal Information Processing Standards (FIPS)
code for the
state
(two digit)
and
county
(five digit)
of the center point of the result, if we can determine it.
This annotation is applied
only for locations in the United States and associated territories.
The values are strings - not numbers - and can have leading
zeros.
Learn more about
FIPS county codes.
|
flag
|
emoji flag of the country of the result |
geohash
|
contains a geohash for the center point of the result. |
ITM
|
contains the Irish Transverse Mercator
easting
and
northing
of the center point of the result.
This annotation is applied only for locations in Ireland.
Learn more about
ITM.
|
Maidenhead
|
contains a Maidenhead location reference for the center point of the result. |
Mercator
|
contains the
Mercator projection
(EPSG:41001, sometimes also referred to as "Simple Mercator")
x
and
y
unit meter values of the center point of the result.
Note: use of Mercator projection on latitudes above/below +70/-70
degrees is strongly discouraged, due to the gross distortions of
the projection.
|
MGRS
|
contains a Military Grid Reference System code for the center point of the result. WGS84 datum. |
OSM
|
contains:
Our tutorial on how to add an address to OpenStreetMap may be helpful. |
qibla
|
decimal degrees clockwise from true north to turn to point to the Kaaba (21.4225,39.8262). Calculated using the great circle method. More background on Qibla. |
roadinfo
|
contains information relevant to driving in this region,
potentially also about the specific road of the result
Information relevant to driving in the country/region:
roadinfo
parameter was specified we will also attempt to set the following
values about the road:
|
sun
|
contains two keys:
rise
and
set
, each of which in turn contains four keys:
|
timezone
|
contains the keys
name
,
now_in_dst
,
offset_sec
,
offset_string
,
short_name .
When the coordinates are in a country the name will be of the form
Continent/City ,
the format used by
tz database
on *nix systems, for example
Europe/Lisbon .
When the coordinates are not in a country (for example in an ocean)
the format will be an
offset to/from GMT, for example
GMT+2 .
Learn more about timezones and how they are typically represented on *nix based systems
over on Wikipedia.
|
UN_M49
|
contains relevant
United Nations M49 codes.
The annotation consists of two keys:
regions
and
statistical_groupings .
The
regions
key contains key which are human-readable names of the regions in English and values
which are 3 digit UN M49 codes. Note: The codes are strings and not numbers, they can have
leading zeros.
For example:
"WORLD": "001", "AFRICA": "002", "SUB-SAHARAN AFRICA": "202"
You can see
a full list of all possible regions and the corresponding codes.
The value of the
statistical_groupings
key is a list of abbreviations of names of various country groupings commonly used in statistical analysis.
Possible values are
|
what3words
|
contains a key
words
whose value is a 3 words address (3wa).
By default the words
returned are in English, but if the query contained the
optional
language
parameter specifying one of the following languages:
af,ar,bg,bn,cs,da,de,el,en,es,fi,fr,he,hu,id,it,ja,ko
mn,mr,ms,nl,no,pl,pt,ro,ru,sv,sw,ta,te,th,tr,xh,zh,zu
the 3wa will be in that language.
Learn more about
what3words
and their location naming scheme.
|
wikidata
|
Wikidata item for the location. A Wikidata item is a unique identifier used by the Wikimedia Foundation and others. Learn more. |
Troubleshooting / Common Issues
If things aren't working as you hope, here's some advice:-
If you aren't getting the response you expected from the API
please look at the
status
field of the response. It contains two fields:code
andmessage
. Please take a look at what the various response codes mean. We do our best to tell you what the problem is. Sometimes we see developers assuming the problem is X when really it is Y. - If at all possible please follow the best practices, especially our advice on formatting your query.
- Unless you use case is truly exotic, we recommend you use one of the many SDKs to help avoid basic errors (and save your time).
- Nevertheless, sometimes an SDK can obscure what is actually happening. Our demo page is a good tool for quickly playing with the API and seeing actual requests and responses.
- We have detailed guides to common geocoding questions like how to geocode more quickly or how to show geocoding results on a map. Have a look.
- If in doubt, please don't hesitate to get in touch with any specific questions you may have.
Libraries and SDKs
There is no need to reinvent the wheel, there are open-source SDKs for accessing the OpenCage geocoding API for over 30 different programming languages.Tutorials
We have tutorials showing how to access our geocoding API for over 20 different programming languages.Operational Status
In the event of network or other operational issues we will keep you informed via the @OpenCage twitter account. We also have a third-party dashboard of past operational performance. In the last 30 days our independently monitored uptime has been:Reverse geocoding |
|
Forward geocoding |
|
Batch or Bulk Geocoding
We are sometimes asked if the geocoding API supports sending more than one location per request, sometimes referred to as "batch" or "bulk" geocoding. The answer is no. We intentionally don’t support more than one location per request as our experience is that the conceptually much simpler "one location, one request" model is much less likely to lead to misunderstandings or errors of implementation, thus saving engineering time, which is the most valuable resource for almost all of our customers. Our entire goal is simplicity. If you need to geocode many locations quickly the way to do so is by sending requests in parallel. We have customers geocoding millions of locations per day, it works. Please read our guide to geocoding large datasets where we explain various strategies and points to consider.IP restriction
Subscription customers can define a list of IP addresses that are allowed to use their API key. All requests with that API key that come from non-allowed IP numbers will receive a403 - IP address rejected
response.
Customers can add or delete IP addresses in their account dashboard.
Changes to IP restriction settings
take approximately 10 minutes to take effect
as they are distributed out to all of our servers.
CORS / JSONP
If you are accessing the API from client side javascript please be aware that by default the OpenCage Geocoding API allows all origins for Cross-Origin Resource Sharing (CORS). The default API response includes the HTTP headeraccess-control-allow-origin: *
which thus allows all cross-origin requests.
Subscription customers can change this by defining a domain per API key in
their account dashboard. We will then return:
access-control-allow-origin: https://some-customer-defined-domain.com
which will thus restrict AJAX requests to the specified domain.
It is important to note this does nothing to prevent someone from making
an API request with your key, it just makes AJAX requests from within
a browser stop working. Please see our detailed
advice on protecting your API key(s).
The value you specify must be a domain including
https://
or
http://
.
The value may contain ports, for example
http://localhost:8080
.
Changes to these settings may take approximately 10 minutes
to take effect
as they are distributed out to all of our servers.
Additional resources:
-
You can also use the optional
jsonp
parameter to wrap our APIs JSON response with a function name. - If you are sending requests to our API via AJAX you may find our jQuery tutorial helpful.
- Learn more about CORS on Wikipedia.
- Some of the pros and cons of JSONP and CORS.
Privacy
In using the OpenCage geocoding API you are sending us your location data. While we have no ability or desire to link locations with individuals, any time you are transferring data it makes sense to consider the privacy implications.- We are a European (German) legal entity, and thus fully bound by the EU's General Data Protection Regulation (GDPR). Please find all details of our compliance with GDPR in our privacy policy.
-
As a reassurance for any users of the API with privacy concerns,
we provide the optional
no_record
parameter. See details. When this parameter is set we keep no record of your query. - Our geocoding API attempts to geocode to the most precise level possible. There are use cases where exposing a full address or precise location may pose a privacy risk. This will necessarily depend on how exactly you are using location data in your application. Nevertheless, we provide the following guide to how to create an imprecise location description to preserve privacy. Please be responsible in your use of location data.
- Free trial accounts are deleted after six months of inactivity, afterwhich we have no record of the account. You can also delete your account sooner anytime you like in your account dashboard.
Google Compatibility
As a convenience we provide a Google compatible response format for forward geocoding. Please note this may be discontinued in the future as it is not used much.
We strongly recommend migrating to our response format. Please see our overview of how our service differs from Google's.
Required Parameters
-
address
- the query string to be geocoded; this must be URL encoded -
key
- you API key, a 30 character long, alphanumeric string
Optional Parameters
-
sensor
- required by Google as an indicator of whether the request comes from a device with a location sensor; this parameter is ignored by the OpenCage geocoding API.
Google JSON Output
In the following example, a response in Google's JSON format is requested to get the coordinates of the old OpenCage office in central London at 82 Clerkenwell Road, London EC1M 5RF, United Kingdom.https://api.opencagedata.com/geocode/v1/google-v3-json?address=82+Clerkenwell+Road%2C+London+EC1M+5RF%2C+United+Kingdom&pretty=1&key=YOUR-API-KEY
A JSON geocoding response contains 3 elements:
-
total_results
- the number of elements in theresults
array -
results
- an array of result responses -
status
- the overall status of the request
{
"results" : [
{
"address_components" : [
{
"long_name" : "Europe",
"short_name" : "Europe",
"types" : [
"continent"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "Greater London",
"short_name" : "Greater London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "European Union",
"short_name" : "European Union",
"types" : [
"political_union"
]
},
{
"long_name" : "SW1A 2DX",
"short_name" : "SW1A 2DX",
"types" : [
"postal_code"
]
},
{
"long_name" : "United Kingdom",
"short_name" : "United Kingdom",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London SW1A 2DX, United Kingdom",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "51.6673219",
"lng" : "0.0323526"
},
"southwest" : {
"lat" : "51.3473219",
"lng" : "-0.2876474"
}
},
"location" : {
"lat" : "51.5073219",
"lng" : "-0.1276474"
}
}
},
{
"address_components" : [
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "Europe",
"short_name" : "Europe",
"types" : [
"continent"
]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "Greater London",
"short_name" : "Greater London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "European Union",
"short_name" : "European Union",
"types" : [
"political_union"
]
},
{
"long_name" : "United Kingdom",
"short_name" : "United Kingdom",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, United Kingdom",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "51.6918741",
"lng" : "0.3340155"
},
"southwest" : {
"lat" : "51.2867601",
"lng" : "-0.5103751"
}
},
"location" : {
"lat" : "51.4893335",
"lng" : "-0.144055084527687"
}
}
},
{
"address_components" : [
{
"long_name" : "City of London",
"short_name" : "City of London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "Europe",
"short_name" : "Europe",
"types" : [
"continent"
]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "Greater London",
"short_name" : "Greater London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "European Union",
"short_name" : "European Union",
"types" : [
"political_union"
]
},
{
"long_name" : "United Kingdom",
"short_name" : "United Kingdom",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "City of London, United Kingdom",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "51.5233213",
"lng" : "-0.0727261"
},
"southwest" : {
"lat" : "51.5068696",
"lng" : "-0.1138211"
}
},
"location" : {
"lat" : "51.514947",
"lng" : "-0.0930460965094679"
}
}
},
{
"address_components" : [
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "Ontario",
"short_name" : "Ontario",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "Southwestern Ontario",
"short_name" : "Southwestern Ontario",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "N6B 2P8",
"short_name" : "N6B 2P8",
"types" : [
"postal_code"
]
},
{
"long_name" : "Canada",
"short_name" : "Canada",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, ON N6B 2P8, Canada",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "43.148576",
"lng" : "-81.086643"
},
"southwest" : {
"lat" : "42.828576",
"lng" : "-81.406643"
}
},
"location" : {
"lat" : "42.988576",
"lng" : "-81.246643"
}
}
},
{
"address_components" : [
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "Ontario",
"short_name" : "Ontario",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "Southwestern Ontario",
"short_name" : "Southwestern Ontario",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "Canada",
"short_name" : "Canada",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "Southwestern Ontario, ON, Canada",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "43.0730461",
"lng" : "-81.1070784"
},
"southwest" : {
"lat" : "42.824599",
"lng" : "-81.3906556"
}
},
"location" : {
"lat" : "42.9537654",
"lng" : "-81.2291529"
}
}
},
{
"address_components" : [
{
"long_name" : "Laurel County",
"short_name" : "Laurel County",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "Kentucky",
"short_name" : "Kentucky",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "40741",
"short_name" : "40741",
"types" : [
"postal_code"
]
},
{
"long_name" : "United States of America",
"short_name" : "United States of America",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, KY 40741, United States of America",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "37.15226",
"lng" : "-84.035957"
},
"southwest" : {
"lat" : "37.079759",
"lng" : "-84.126262"
}
},
"location" : {
"lat" : "37.1289771",
"lng" : "-84.0832646"
}
}
},
{
"address_components" : [
{
"long_name" : "Madison County",
"short_name" : "Madison County",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "Ohio",
"short_name" : "Ohio",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "43140",
"short_name" : "43140",
"types" : [
"postal_code"
]
},
{
"long_name" : "United States of America",
"short_name" : "United States of America",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, OH 43140, United States of America",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "39.921786",
"lng" : "-83.389997"
},
"southwest" : {
"lat" : "39.85928",
"lng" : "-83.478923"
}
},
"location" : {
"lat" : "39.8864493",
"lng" : "-83.448253"
}
}
},
{
"address_components" : [
{
"long_name" : "Pope County",
"short_name" : "Pope County",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "Arkansas",
"short_name" : "Arkansas",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "United States of America",
"short_name" : "United States of America",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, AR, United States of America",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "35.3389327",
"lng" : "-93.1874567"
},
"southwest" : {
"lat" : "35.3169503",
"lng" : "-93.2716305"
}
},
"location" : {
"lat" : "35.328973",
"lng" : "-93.2529553"
}
}
},
{
"address_components" : [
{
"long_name" : "Tulare County",
"short_name" : "Tulare County",
"types" : [
"administrative_area_level_2",
"political"
]
},
{
"long_name" : "North America",
"short_name" : "North America",
"types" : [
"continent"
]
},
{
"long_name" : "California",
"short_name" : "California",
"types" : [
"administrative_area_level_1",
"political"
]
},
{
"long_name" : "London",
"short_name" : "London",
"types" : [
"locality",
"political"
]
},
{
"long_name" : "United States of America",
"short_name" : "United States of America",
"types" : [
"country",
"political"
]
}
],
"formatted_address" : "London, CA, United States of America",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : "36.4884367",
"lng" : "-119.4385395"
},
"southwest" : {
"lat" : "36.4734452",
"lng" : "-119.4497699"
}
},
"location" : {
"lat" : "36.4760619",
"lng" : "-119.4431785"
}
}
}
],
"status" : "OK"
}
Open API / Swagger specification
Want an Open API / Swagger specification for the OpenCage Geocoding API? Look no further, here it is. We also have tutorials for accessing our API in Postman and Insomnia REST client.Change Log
We keep a record of all changes to the API on GitHub. We also recommend you follow us on twitter and/or read our blog where all changes are announced.Help Us Improve
If anything in this documentation is unclear, please let us know We welcome your feedback. Much of our code is open source. Geocoding the world is a tough challenge, we would love your help.Bugs
Unfortunately, humanity has not always chosen to name places in a way that is simple for computers to decipher. The task a geocoder faces is a difficult one. A geocoder consists of two things, software and the underlying data. So there are two types of problems that can occur: a software problem, or data problems (erroneous or missing data). In both cases we want to solve it, but what needs to be done depends on the type of problem we're facing. Regardless, we appreciate your feedback and will work with you to get better.Security Issues
We make every effort to keep user data secure. If you find a vulnerability please report it to security @ opencagedata.com, we will follow up with you promptly. Please see the details of our security bounty program. If you wish to encrypt your report you can find our public key on our security.txt. Thank you.Thanks
Many thanks for using the OpenCage geocoding API. Thanks also to everyone who has contributed data and software to OpenStreetMap and the other open geo datasources we rely on. Here is the full list of sources we rely on.It's one of many data sources we use.
Data © OpenStreetMap contributors, Imagery © Martin Raifer, cc-by
Open as larger interactive map