API reference
Nominatim — Module
NominatimA 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.
- Search by free text or by address fields →
search,geocode - Coordinates to address →
reverse_geocode - Known OSM objects →
lookup,place_details - Many addresses at once, resumable →
geocode_batch,reverse_geocode_batch - Results as a table →
places_dataframe - Server health →
server_status
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 variableNOMINATIM_URL, otherwise the public serverhttps://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.0for the public server (and it may not be lower),0.0for 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")Nominatim.default_client — Function
default_client() -> NominatimClientThe 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!.
Nominatim.set_default_client! — Function
set_default_client!(client::NominatimClient) -> NominatimClientUse 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 serverNominatim.server_status — Function
server_status(client = default_client()) -> NamedTupleWhether 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.
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.
Nominatim.clear_cache! — Function
clear_cache!(client::NominatimClient = default_client()) -> IntDelete every cached response of client and return how many were deleted.
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 (seeNominatimClient).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; withbounded = 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)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_levelNominatim.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 YorkNominatim.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 HouseNominatim.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").
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) -> DataFrameGeocode 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,addressorq), or structured columnsstreet,city,county,state,country,postalcode(zipworks 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 (missingotherwise).requested_house_number,house_number_matches- the house number found in the input, and whether the result has it (seehouse_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 insearch, applied to every query. For US addresses,countrycodes = "us"avoids matches abroad.expand = false- add one column per tag, as inplaces_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)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) -> DataFrameFind 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.
Results
Nominatim.Place — Type
PlaceOne 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_rankin words::house_or_poi,:street,:locality,:neighbourhood,:suburb,:city,:county,:state,:countryor:other.likely_interpolated::Bool-truewhen the house number is probably estimated from an address range (OSM interpolation line or US TIGER data) rather than a mapped address point. Seeis_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 athttps://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.
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.
Nominatim.places_dataframe — Function
places_dataframe(places; expand = false) -> DataFrameA 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).
Match quality
Nominatim.match_level_for_rank — Function
match_level_for_rank(place_rank::Integer) -> SymbolTranslate Nominatim's address rank into a readable match level, following https://nominatim.org/release-docs/latest/customize/Ranking/:
| rank | level |
|---|---|
| 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.
Nominatim.is_likely_interpolated — Function
is_likely_interpolated(category, place_type, osm_type) -> Booltrue 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").
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.
missingif you did not ask for a house number.falseif the result has no house number (e.g. a street-level match) or a different one.trueif it is the same number, one of several listed ("10;12"), or inside a listed range ("10-20").
Nominatim.extract_house_number — Function
extract_house_number(address_text) -> StringThe 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") # ""