API reference

Nominatim — Module
Nominatim

A readable Julia client for Nominatim, the open-source geocoder built on OpenStreetMap data.

It works against the public server (https://nominatim.openstreetmap.org, rate-limited to one request per second) and, more usefully for large jobs, against your own Nominatim server, where there is no limit.

Every request asks Nominatim for everything it can return: the address broken into parts, extra OSM tags (website, opening hours, …), all name variants, entrances, and the full geometry.

source

Server and settings

Nominatim.NominatimClient — Type
NominatimClient(; base_url, user_agent, email, accept_language,
                  minimum_seconds_between_requests, readtimeout_seconds,
                  maximum_retries, cache)

Settings shared by every request to one Nominatim server.

Keywords

  • base_url - the server, e.g. "http://127.0.0.1:8088" for your own server. Default: the environment variable NOMINATIM_URL, otherwise the public server https://nominatim.openstreetmap.org.
  • user_agent - identifies your application, e.g. "MyStudy/1.0 (me@university.edu)". Required for the public server (its usage policy blocks generic User-Agents). Default: ENV["NOMINATIM_USER_AGENT"], or "Nominatim.jl" for your own server.
  • email - optional contact address sent with each request, which the public server's operators use to reach you instead of blocking you. Default: ENV["NOMINATIM_EMAIL"].
  • accept_language - preferred language of names and addresses ("en").
  • minimum_seconds_between_requests - 1.0 for the public server (and it may not be lower), 0.0 for any other server.
  • readtimeout_seconds - give up if the server sends nothing for this long (60).
  • maximum_retries - retries after network errors, HTTP 429 and HTTP 5xx (3).
  • cache - where to store responses so repeated queries don't hit the server:
    • :auto (default): on for the public server (the usage policy requires caching), off for your own server;
    • true: on, in this package's scratch space;
    • false: off;
    • a folder path: on, in that folder.

Examples

public_client = NominatimClient(user_agent = "HousingStudy/1.0 (me@university.edu)")
local_client  = NominatimClient(base_url = "http://127.0.0.1:8088")
source
Nominatim.default_client — Function
default_client() -> NominatimClient

The client used when you don't pass client = …. It is created on first use from the environment variables NOMINATIM_URL, NOMINATIM_USER_AGENT and NOMINATIM_EMAIL, or set explicitly with set_default_client!.

source
Nominatim.set_default_client! — Function
set_default_client!(client::NominatimClient) -> NominatimClient

Use client for every call that does not pass client = … explicitly.

set_default_client!(NominatimClient(base_url = "http://127.0.0.1:8088"))
geocode("350 5th Ave, New York, NY")   # goes to your own server
source
Nominatim.server_status — Function
server_status(client = default_client()) -> NamedTuple

Whether the server is working, and how fresh its data is: (ok, status, message, data_updated, software_version, database_version).

data_updated is the date of the OpenStreetMap data (a DateTime, UTC); record it with your results so they are reproducible.

source
Nominatim.NominatimError — Type
NominatimError(http_status, message, url)

Thrown when a Nominatim server answers with an error instead of results, for example a malformed request (HTTP 400), a block for exceeding the usage policy (HTTP 403 or 429), or a server problem that persisted through all retries.

Fields

  • http_status::Int - the HTTP status code the server returned.
  • message::String - the server's explanation.
  • url::String - the request that failed.
source
Nominatim.clear_cache! — Function
clear_cache!(client::NominatimClient = default_client()) -> Int

Delete every cached response of client and return how many were deleted.

source

One query at a time

Nominatim.search — Function
search(query::AbstractString; client, limit, countrycodes, viewbox, bounded,
       layer, featuretype, exclude_place_ids, dedupe, polygon_threshold,
       extra_parameters) -> Vector{Place}

search(; street, city, county, state, country, postalcode, amenity,
       client, limit, …) -> Vector{Place}

Find places matching a free-text query, or a structured address. Returns all candidates, best first (empty if nothing matched). Every result carries the full detail Nominatim can return (see Place).

Structured search is usually more precise for addresses: Nominatim does not have to guess which part of the text is the city.

Keywords

  • client = default_client() - the server to ask (see NominatimClient).
  • limit = 10 - maximum number of results (1–40).
  • countrycodes - restrict to countries, e.g. "us" or ["us", "ca"].
  • viewbox = (min_longitude, min_latitude, max_longitude, max_latitude) - prefer results in this box; with bounded = true, only return results inside it.
  • layer - "address", "poi", "railway", "natural", "manmade", or a vector.
  • featuretype - "country", "state", "city" or "settlement".
  • exclude_place_ids - place ids to skip (for paging through results).
  • dedupe = true - merge duplicates (e.g. one street split into several ways).
  • polygon_threshold - simplify returned geometries to this tolerance (degrees).
  • extra_parameters = Dict() - any other Nominatim parameter, passed through.
  • Structured form only: street (house number and street name), city, county, state, country, postalcode, amenity (name or type of POI). Structured search cannot be combined with a free-text query.

Examples

search("Empire State Building")
search(street = "350 5th Ave", city = "New York", state = "NY", country = "us")
search("coffee"; viewbox = (-74.02, 40.70, -73.93, 40.80), bounded = true, limit = 40)
source
Nominatim.geocode — Function
geocode(query::AbstractString; kwargs...) -> Union{Nothing, Place}
geocode(; street, city, state, postalcode, country, …) -> Union{Nothing, Place}

The best match for an address, or nothing if there is none. Takes the same keywords as search.

Check place.match_level before trusting the coordinates: a street-level match (:street) means the house number was not found.

place = geocode("350 5th Ave, New York, NY 10118")
place.name, place.latitude, place.longitude, place.match_level
source
Nominatim.reverse_geocode — Function
reverse_geocode(latitude, longitude; client, zoom = 18, layer, polygon_threshold,
                extra_parameters) -> Union{Nothing, Place}

The address (or object) at a location, or nothing if there is nothing there (e.g. the open ocean).

zoom sets the level of detail: 18 = building, 17 = street, 16 = major street, 14 = neighbourhood, 13 = village/suburb, 10 = city, 8 = county, 5 = state, 3 = country.

layer limits what may be returned: "address", "poi", "railway", "natural", "manmade" (default: address and POI).

reverse_geocode(40.74844, -73.98566)          # Empire State Building
reverse_geocode(40.74844, -73.98566; zoom = 10)  # New York
source
Nominatim.lookup — Function
lookup(osm_ids; client, polygon_threshold, extra_parameters) -> Vector{Place}

Fetch known OpenStreetMap objects with full detail. osm_ids is a vector of "N123" / "W123" / "R123" codes, (type, id) pairs, or Places. Longer lists are split into requests of 50 automatically. Objects the server does not know are silently left out.

lookup(["W34633854", "R19761182"])   # Empire State Building, White House
source
Nominatim.place_details — Function
place_details(osm_id; client, category) -> Dict{String, Any}
place_details(place::Place; client) -> Dict{String, Any}

Everything Nominatim stores about one object, from its /details endpoint: all names and address tags, the computed postcode, the full address hierarchy ("address"), linked places, keywords, dependent addresses ("hierarchy"), entrances and geometry.

The output format differs from Place and is returned as plain Dicts. Meant for inspecting individual results, not for bulk use.

osm_id is "W34633854" or ("way", 34633854). category picks the entry when one OSM object has several main tags (e.g. "tourism").

source

Many queries at once

Nominatim.geocode_batch — Function
geocode_batch(addresses; client, concurrent_requests, checkpoint_file,
              countrycodes, viewbox, bounded, layer, featuretype,
              polygon_threshold, extra_parameters, expand,
              progress_every_seconds) -> DataFrame

Geocode many addresses and return one row per input, in input order.

Input

  • a vector of address strings, or
  • a DataFrame / vector of NamedTuples with a free-text column (query, address or q), or structured columns street, city, county, state, country, postalcode (zip works too), amenity.

Structured columns usually match more precisely.

Output columns

  • input_index, input_query - which input the row belongs to.
  • status - "matched", "no_match", "error" or "empty_input".
  • error_message - why a query failed (missing otherwise).
  • requested_house_number, house_number_matches - the house number found in the input, and whether the result has it (see house_number_matches).
  • then every column of places_dataframe: name, coordinates, match level, likely_interpolated, address parts, bounding box, extra tags, …

Keywords

  • client = default_client() - use your own server for large jobs.
  • concurrent_requests = 1 - simultaneous requests. On your own server, up to about the number of API worker processes. Always 1 on the public server.
  • checkpoint_file = nothing - a file path (e.g. "run.checkpoint.jsonl"). Every answer is appended to it as it arrives; run the same call again after an interruption and answered queries are not sent again. Queries that failed are retried on the next run.
  • countrycodes, viewbox, bounded, layer, featuretype, polygon_threshold, extra_parameters - as in search, applied to every query. For US addresses, countrycodes = "us" avoids matches abroad.
  • expand = false - add one column per tag, as in places_dataframe.
  • progress_every_seconds = 30 - how often to log progress.

Example

using Nominatim, DataFrames

client = NominatimClient(base_url = "http://127.0.0.1:8088")
addresses = DataFrame(street = ["350 5th Ave", "1600 Pennsylvania Ave NW"],
                      city = ["New York", "Washington"], state = ["NY", "DC"],
                      zip = [10118, 20500])

results = geocode_batch(addresses; client, countrycodes = "us",
                        concurrent_requests = 12,
                        checkpoint_file = "addresses.checkpoint.jsonl")

exact = filter(row -> row.match_level == "house_or_poi" && row.house_number_matches === true &&
                      !row.likely_interpolated, results)
source
Nominatim.reverse_geocode_batch — Function
reverse_geocode_batch(latitudes, longitudes; client, zoom = 18, layer,
                      concurrent_requests, checkpoint_file, polygon_threshold,
                      extra_parameters, expand, progress_every_seconds) -> DataFrame

Find the address at many locations. Returns one row per coordinate pair, in input order, with input_index, input_latitude, input_longitude, status ("matched", "no_match", "error", "empty_input" for missing/NaN coordinates), error_message, then every column of places_dataframe.

Keywords as in reverse_geocode and geocode_batch.

source

Results

Nominatim.Place — Type
Place

One result from Nominatim.

What is there

  • name::String - name of the object, e.g. "Empire State Building" ("" if unnamed).
  • display_name::String - the full, human-readable address.
  • category::String, place_type::String - the main OpenStreetMap tag, e.g. "office" / "government", "building" / "house", "highway" / "residential".
  • addresstype::String - what the object counts as in an address ("road", "city", …).

Where it is

  • latitude::Float64, longitude::Float64 - the point Nominatim returns (the centroid for areas and lines).
  • boundingbox::Union{Missing, BoundingBox}
  • geometry_geojson::Union{Missing, String} - the full geometry (point, line or polygon) as GeoJSON text.

Address and extra information

  • address::Dict{String, String} - the address split into parts: house_number, road, neighbourhood, suburb, city/town/village, county, state, ISO3166-2-lvl4, postcode, country, country_code, …
  • extratags::Dict{String, String} - further OpenStreetMap tags: website, phone, opening_hours, wikidata, building:levels, …
  • namedetails::Dict{String, String} - every name variant: name:en, short_name, official_name, ref, …
  • entrances::Vector{Dict{String, Any}} - tagged entrances of a building.

Match quality

  • place_rank::Int - Nominatim's address rank, 30 = house/POI, 26–27 = street.
  • match_level::Symbol - place_rank in words: :house_or_poi, :street, :locality, :neighbourhood, :suburb, :city, :county, :state, :country or :other.
  • likely_interpolated::Bool - true when the house number is probably estimated from an address range (OSM interpolation line or US TIGER data) rather than a mapped address point. See is_likely_interpolated.
  • importance::Union{Missing, Float64} - Nominatim's relevance score (0–1).

Identifiers

  • osm_type::String ("node", "way", "relation"), osm_id::Int - the OpenStreetMap object; view it at https://www.openstreetmap.org/<osm_type>/<osm_id>.
  • place_id::Int - Nominatim's internal id. Not stable between servers or imports.
  • licence::String - the data licence notice.
  • raw - the original JSON object, for anything not covered above.
source
Nominatim.BoundingBox — Type
BoundingBox(south, north, west, east)

The rectangle around a place, in degrees (WGS84). For a house it is tiny; for a street, city or state it covers the whole area.

source
Nominatim.places_dataframe — Function
places_dataframe(places; expand = false) -> DataFrame

A table with one row per result. nothing entries (no match) become rows of missing, so the output lines up with the input.

Columns:

  • what is there: name, display_name, category, place_type, addresstype
  • where: latitude, longitude, bbox_south, bbox_north, bbox_west, bbox_east, geometry_geojson
  • match quality: match_level, place_rank, likely_interpolated, importance
  • address: address_house_number, address_road, address_neighbourhood, address_suburb, address_hamlet, address_village, address_town, address_city, address_county, address_state, address_state_code (e.g. "US-NY"), address_postcode, address_country, address_country_code
  • identifiers: osm_type, osm_id, place_id
  • everything else, as JSON text: address_json (all address parts), extratags_json, namedetails_json, entrances_json

With expand = true, every address part, extra tag and name variant that occurs in any result also gets its own column, prefixed address_, tag_ and name_ (e.g. tag_website, tag_opening_hours, name_short_name).

source

Match quality

Nominatim.match_level_for_rank — Function
match_level_for_rank(place_rank::Integer) -> Symbol

Translate Nominatim's address rank into a readable match level, following https://nominatim.org/release-docs/latest/customize/Ranking/:

ranklevel
28–30:house_or_poi
26–27:street
25:locality
22–24:neighbourhood
17–21:suburb
13–16:city
10–12:county
5–9:state
4:country
other:other

A search for "123 Main St, Springfield, IL" that only finds the street returns rank 26, i.e. :street: the coordinates are somewhere on Main Street, not at number 123.

source
Nominatim.is_likely_interpolated — Function
is_likely_interpolated(category, place_type, osm_type) -> Bool

true when the result is probably an estimated position on an address range rather than a mapped address point.

Nominatim returns such results as category = "place", type = "house", with osm_type = "way": the way is either an OpenStreetMap interpolation line or, for US TIGER data, the street (https://nominatim.org/release-docs/latest/api/Output/).

This is a heuristic: Nominatim has no field that states the source directly, and a rare untagged area carrying only an address would also match. Mapped address points come back as nodes (place=house on a node) or as buildings (category = "building").

source
Nominatim.house_number_matches — Function
house_number_matches(place::Place, requested_house_number) -> Union{Missing, Bool}

Whether the result carries the house number you asked for.

  • missing if you did not ask for a house number.
  • false if the result has no house number (e.g. a street-level match) or a different one.
  • true if it is the same number, one of several listed ("10;12"), or inside a listed range ("10-20").
source
Nominatim.extract_house_number — Function
extract_house_number(address_text) -> String

The house number at the start of a street address, or "" if there is none.

extract_house_number("350 5th Ave")          # "350"
extract_house_number("1600A Pennsylvania")   # "1600A"
extract_house_number("12-14 Main St")        # "12-14"
extract_house_number("Main St")              # ""
source