OpenHistoricalMap/Overpass
OpenHistoricalMap's Overpass API instance allows you to query the database for elements matching very specific criteria. For example, you could search for trees that were planted in a certain city during a particular date range near a certain kind of building – all subject to whether these details have been mapped, of course.
For raw queries from desktop applications, OpenHistoricalMap's Overpass API endpoint is located at:
https://overpass-api.openhistoricalmap.org/api/
Overpass turbo
Most people use the Overpass API through Overpass turbo, a Web application that provides syntax highlighting for the OverpassQL language and displays the results on a map. Overpass turbo has a wizard that makes it easier to come up with an OverpassQL query. It can also export the results in various popular formats, such as GeoJSON.
OpenHistoricalMap's Overpass turbo instance has been customized to query the OpenHistoricalMap database and display the results on the Historical basemap.
If you prefer to use a different Overpass turbo instance, append the following code to your query to force it to use the OpenHistoricalMap Overpass API:
Overpass Ultra
Overpass Ultra is an alternative to Overpass turbo. There is an OpenHistoricalMap-optimized instance of Overpass Ultra that requires no upfront configuration. Alternatively, you can configure the main instance to connect to OHM using some YAML front matter.
In the original version of Overpass Ultra, click the Settings button in the toolbar and enter the following settings:
- Server
- https://overpass-api.openhistoricalmap.org/api/
- Style Sheet
- https://www.openhistoricalmap.org/map-styles/main/main.json (or another OHM-based stylesheet URL)
QGIS
For more advanced visualizations that require desktop processing, the QuickOSM plugin for QGIS streamlines the process of importing Overpass API results into a QGIS project. Unfortunately, QGIS does not offer OpenHistoricalMap's Overpass API instance as an option. [1] As a workaround, you can create a custom configuration in your QGIS profile. To use the Quick Query functionality, you also need to configure OHM's Nominatim instance in the profile. [2]
{
"overpass_servers": [
"https://overpass-api.openhistoricalmap.org/api/"
],
"nominatim_servers": [
"https://nominatim-api.openhistoricalmap.org/search?"
]
}
Query examples
- Main article: Overpass API/Overpass API by Example
OpenHistoricalMap's data model allows you to analyze geographical data in a historical context, as well as real-world changes over time, not just the database changes that OSM-based Overpass instances expose.
Theatres in a given year
This query returns all the theatres (amenity=theatre) that existed in the year 1975:
nwr["amenity"="theatre"]["start_date"](if:
t["start_date"] < "1976" &&
(!is_tag("end_date") || t["end_date"] >= "1975"));
out geom;
start_date=* needs to be compared to 1976, not 1975, because for example the string 1975-01-01
sorts after 1975
and is not equivalent to it.
Using sets: 1 type of invalid start_date
and end_date
check
This query searches for invalid dates of any type that looks like a year greater than the present. For example, a start_date
value typed as 1928011023
(a typo replacing "-" with "0") or as 19252
(unclear if this should be "1952" or "1925") is essentially the same query as the one above. What is different is the use of sets (.starts
and .badstarts
). Sets are probably overkill for this query (again, see the query above that gets the job done without them), but this is a simple example that shows how they can be defined, filtered within, and then passed to your results. Clearly, more complex filters can be set up by adding additional logic within each step. You can also create sets using features related to named areas, regions, etc., as shown in the next query.
// assign relations with a "start_date" tag or and "end_date" to a set called ".dates"
(relation["start_date"];
relation["end_date"];)->.dates;
// filter from the set of relations defined in the prior step ("relation.dates")
// based on a tag value and store in a second set called ".baddates"
relation.dates
(if (t["start_date"] >= 2025) || (t["end_date"] >= 2025))->.baddates;
// identify the set you'd like to output; usually the default
.baddates;
// print results
out geom;
Load query in OHM OverpassTurbo.
Oldest building in a region
This query returns the oldest mapped building in Ohio; that is, the building with the minimum start_date=* tag. It relies on the fact that you can sort ISO 8601 dates chronologically by sorting them alphanumerically.
// Get present-day Ohio as an area.
relation(id:2663622);
map_to_area->.ohio;
// Get buildings in Ohio with start dates.
wr["building"]["start_date"](area.ohio)->.buildings;
// Only include buildings whose start dates are as old as the oldest start date of any building in Ohio.
wr.buildings(if: t["start_date"] == lrs_min(buildings.set(t["start_date"])));
// Output the building geometry.
out geom;
Total railway distance in a given year
This query returns the sum total distance of railroad tracks that existed in the year 1975 in meters:
[out:json];
way["railway"]["start_date"](if:
t["start_date"] < "1976" &&
(!is_tag("end_date") || t["end_date"] >= "1975"));
make stats length=sum(length());
out;
Contemporaneous surrounding areas
When recounting a historical event or someone's biography, you typically need to qualify a place with the country, region, etc. that the place was in at the time, not where it's located in the present day. This query returns the areas that contained a specific coordinate pair on a specific date: [3]
// Convert the query point to an area.
is_in(50.92812,11.58791)->.a;
// Get all ways that intersect this area, but only if they existed in the same time period as the city of Jena.
// This relies on the fact that ISO 8601 dates sort lexicographically.
way(pivot.a)(if: t["start_date"] >= "1975")[!"end_date"];
// Output their geometries.
out geom;
out ids geom(50.92785,11.58656,50.92855,11.58949);
// Get all relations that intersect this area, but only if they existed in the same time period as the city of Jena.
relation(pivot.a)(if: t["start_date"] >= "1975")[!"end_date"];
// Output their geometries.
out geom;
This query is also available as a Jupyter notebook.
Changes on this day in history
This query uses a regular expression to find features that began or ended on the current day in years past. The OpenHistoricalMap portal's "On this day in OpenHistoricalMap" feature curates some notable and interesting changes from this query:
(
nwr["start_date"~"-11-21"];
nwr["end_date"~"-11-21"];
);
out geom;
Chronology relations with boundary geometries
type=chronology relations can be tricky to deal with, especially if they don't explicitly contain any geometry-related primitives, such as when they are relations that only have other relations as members. If you want to edit the data this search returns in JOSM, you cannot miss the meta
reference, as the objects will have osmids, but no version information, which will block editing.
[out:xml];
// Get chronology relations with other appropriate criteria.
relation["type"="chronology"]["source:name"="Newberry Library Atlas of Historical County Boundaries"];
// Recurse down and get the members of each chronology.
(._;>;);
// Output the osm object metadata - e.g., non-tag metadata - from the query, even if no geometry is included.
out meta;
This query will generate 2 warning messages in Overpass Turbo: the first is about a large dataset (select "Continue Anyway"), and the the second is about "Incomplete data." This second warning is about the fact that some (all, in this case) of the results have no supporting geometries. This is fine. Select "Show Data" and then click on the "Data" button in the upper right corner of the web page UI.
Load query on OHM Overpass Turbo
Incomplete chronologies
A type=chronology relation represents a single feature as its geometry or tags change over time; each member represents a stage in the feature's evolution. A chronology relation can be used to indicate that the feature's creation or establishment predates the currently mapped stages. For example, a statue may have been created centuries ago in a different place than where it is today, but we haven't mapped its original location or don't even know it. This query returns the earliest stage of a chronology if the chronology's start_date=* tag doesn't match one of its stages' start_date=* tags:
// Get chronology relations with start dates.
relation["type"="chronology"]["start_date"];
// Get the members of each chronology.
nwr(r)(if:
// Filter out all but the earliest stage. This assumes the stages are sorted chronologically within the relation.
lrs_in(id(), set(per_member(pos() == 1 ? ref() : 0))) &&
// Filter out the chronology’s stages if the chronology’s start date matches one of its stages’ start dates.
!lrs_in(t["start_date"], set(per_member(t["start_date"]))));
// Output the earliest stage.
out geom;
Downloading chronology relation IDs for uploading to Wikidata
Adding type=chronology relation IDs to Wikidata will enable Wikidata consumers to find geospatial information related to that Wikidata entry in OHM. Pointing at Wikidata from OHM alone is only one half of a two-way link. Adding this OHM information to Wikidata will close this loop. When you have more than a few Wikidata items to update, Turbo Overpass can help you download necessary fields from OHM and QuickStatements can help upload that data into Wikidata. This query demonstrates how to generate a .csv file with the info you'll need for QuickStatements.
// Define csv output and the tags (wikidata & name) and metadata (::id) you need for Quickstatements
[out:csv('wikidata','name',::id)][timeout:125];
// get the chronology relations you want
relation["type"="chronology"]["natural"="glacier"];
// output csv for editing & use in Quickstatements
out body;
Of note, you do not actually need the name
field for connecting OHM to Wikidata; that is there for you to visually ensure you're working with the correct data.
After you generate this .csv, delete the name
column and rename wikidata
as qid
and rename @id
as P8424
. This assigns the OpenHistoricalMap relation ID property identifier P8424 to the Wikidata Qcode for the Wikidata item it represents. Then, be sure to put each of the OHM relation IDs in triple double quotes, like this: """2790811"""
. And, make sure the first row has no spaces in it, like this: qid,P8424
. The triple double quote wrapping and no spaces in the first row are requirements for QuickStatements to work properly. Then, you can just cut and paste this modified .csv into QuickStatements and run the update.