Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4
Under maintenancePricing
from $5.50 / 1,000 results
Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4
Under maintenanceBuilds the full USGS historical topographic map chronology for any coordinate and runs an ASTM E1527-21 Sec. 8.3.4 historical records review: five-year interval coverage back to 1940, with data gaps explicitly identified. Every map year, scale, quadrangle and download URL. Keyless USGS data.
Pricing
from $5.50 / 1,000 results
Rating
0.0
(0)
Developer
Kyle Maloney
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
Share
Historical Topographic Map Chronology — ASTM Phase I ESA §8.3.4
Give it a coordinate. Get back every USGS topographic map ever published over that point, year by year — plus an ASTM E1527-21 §8.3.4 historical records review that shows which five-year intervals back to 1940 are covered and which are gaps.
Keyless USGS data (The National Map Access API). One billable row per property, no matter how many maps cover it.
Who this is for
- Phase I ESA consultants / environmental professionals. §8.3.4 requires historical use information reviewed at approximately five-year intervals back to 1940 (or the property's obvious first developed use, whichever is earlier), with data gaps identified. This actor does the topographic-map leg of that review and hands you the interval table, the gap list, and a direct download URL for every sheet.
- EDR-report reviewers and anyone pricing one. The same chronology a commercial historical package charges per-site for, as a structured row you can diff, join and archive.
- Due-diligence and land teams screening a portfolio: run 250 parcels in one call and
sort by
astm_max_years_between_mapsto see which sites will need extra historical research before anyone drives out. - Title, mining, water-rights and litigation researchers who need to know exactly which map editions exist for a location and where to download them.
- AI agents. Every field is described in the output schema, so an agent can chain this into a wider due-diligence workflow without guessing.
What it actually does
- Queries USGS Historical Topographic Maps (186,062 products nationally, ~1884 to the 1990s) for the maps whose own footprint covers your point.
- Queries the modern US Topo series (2009–present) so the chronology reaches the present instead of stopping in the 1990s. Optional, on by default, reported separately.
- Rolls the products into a year-by-year chronology, de-duplicated into real map editions, with the largest-scale (most detailed) sheet identified per year.
- Runs the ASTM §8.3.4 interval review: buckets the window into five-year intervals, marks each covered or uncovered, and reports the longest gap, the largest span between consecutive maps, and whether coverage reaches the review start year.
Worked example — Denver, CO (39.7392, −104.9903)
32 map products covering the point, which de-duplicate to 18 distinct editions across 17 years: 1890, 1935, 1940, 1944, 1950, 1953, 1957, 1958, 1960, 1965, 1981, 1997 from the historical collection, then 2010, 2013, 2016, 2019, 2022 from US Topo.
Reviewed 1940–2026 at five-year intervals: 10 of 18 intervals covered (55.6%), longest uncovered stretch 1970–1979, largest span between consecutive maps 16 years (1965→1981). Pre-1940 coverage exists back to 1890. The most detailed sheet available is 1:24,000.
That 1970s gap is the actionable output: it is where the consultant knows to pull aerials or Sanborns rather than assume nothing happened.
What this actor does NOT do — read this before you rely on it
- It does not review aerial photography. USDA NAIP returns
total: 0for every point tested through the TNM Access API, so there is no keyless aerial leg here and this actor does not pretend otherwise. Every row carriesaerial_photography_status: "not_covered_by_this_actor"— a status string, deliberately not a boolean, becausefalsewould be a claim about something never checked. - It is a screening tool, not a determination. ASTM §8.3.4 expects the standard historical sources as a set — aerials, fire insurance maps, city directories, land title, zoning. An interval reported uncovered here is a candidate data gap for the topographic-map source only and may well be filled by another source. An environmental professional makes the determination; this gives them the map leg of the evidence.
nullnever means "no". On this actornullmeans not checked andfalsemeans checked and negative. If a source did not answer, every ASTM verdict field isnull, theobserved_*fields still report what the run did see, andastm_analysis_statusreadsincomplete_source_failure. A "no data gap" answer computed while a source was down is the one wrong answer in this product that carries professional liability, so it is never emitted.- If the USGS source fails for every property, the run FAILS and bills nothing. It does not emit a row per site saying "no maps found".
Example input
{"assets": [{ "lat": 39.7392, "lon": -104.9903, "label": "Denver CO - downtown redevelopment parcel" },{ "lat": 29.7604, "lon": -95.3698, "label": "Houston TX - Ship Channel industrial site" },{ "lat": 38.9296, "lon": -116.9312, "label": "Nye County NV - rural parcel" }],"bufferMiles": 0,"includeUsTopo": true,"reviewStartYear": 1940,"intervalYears": 5,"maxMapsListed": 200}
bufferMiles: 0 asks USGS for the maps whose footprint covers the property — a true
point-in-quadrangle test, and the defensible answer for §8.3.4. A value above 0 widens the
search to any sheet intersecting a box around the point, which pulls in adjoining
quadrangles and changes what the coverage counts mean; the value used is reported on every
row in buffer_miles and query_geometry.
Set reviewStartYear earlier than 1940 when the property has an obvious first developed
use before then — §8.3.4 asks for 1940 or first developed use, whichever is earlier. Map
years found before the window are always reported anyway, in
pre_review_window_map_years.
Input reference
| Input | Default | What it does |
|---|---|---|
assets | (required) | Array of {lat, lon, label}. One billable row each. |
bufferMiles | 0 | 0 = maps covering the point. Above 0 widens to an intersecting box. |
includeUsTopo | true | Adds the modern 2009+ US Topo series. Does not change billing. |
reviewStartYear | 1940 | First year of the ASTM review window. |
reviewEndYear | current year | Last year of the review window. |
intervalYears | 5 | Interval length. §8.3.4 calls for approximately five years. |
maxMapsListed | 200 | Caps the per-row maps inventory. Counts and chronology are always complete. |
maxAssets | 250 | Safety cap on sites per run. |
verifyUpstream | true | Runs the live drift check before touching your sites. |
simulateOutage | none | Diagnostic: forces a source lookup, or one upstream-verification probe, to fail so you can prove the failure paths yourself. |
How it protects you from a silently wrong answer
USGS answers HTTP 200 with total: 0, items: [] and errors: [] when you send a
collection tag it does not recognise — byte-identical in shape to a genuine "no maps cover
this property". If USGS ever renamed the historical collection, a naive actor would
confidently report no historical coverage for every property in the United States, and
every run would be green.
So before a single billable row exists, each run:
- confirms USGS still publishes both collection tags in its own dataset registry;
- probes a positive canary in Denver that must return at least 10 products, at least 6 distinct years, coverage back past 1910 and forward past 1980, with the map scale and quadrangle name still parseable from at least 90% of titles;
- probes a US Topo canary that must return a map published 2015 or later;
- probes a negative control in the mid-Pacific that must return exactly zero — the check the positive canary cannot do, because an unfiltered response would still clear a floor test;
- post-validates the query USGS echoes back (collection tag and point coordinates) and the rows it returned (every product's own bounding box must contain your point).
Every measured value is logged on every run, pass or fail. If any check measures a wrong answer, the run fails with a message naming the cause, and nothing is emitted or billed.
A probe that could not be reached is not the same as a probe that failed. Each probe
has its own error boundary and its own recorded outcome - pass, fail (it completed
and a band did not hold) or unavailable (it never answered: a gateway timeout, a
transport error). A fail on any probe stops the run. An unavailable stops the run
only when it hits a load-bearing check - the collection-tag registry, or every
positive canary - because without those nothing about the collection can be confirmed.
If only the corroborating negative control cannot be reached, the run proceeds and says
so on every row (drift_gate_status: verified_degraded), rather than reporting a USGS
outage as a finding about your property. The catastrophic case that control guards
against - a spatial filter dropped entirely - is caught independently by the positive
canary's 200-product ceiling, since an unfiltered response is the whole 186,062-product
national collection.
It also reads USGS's own total first and pages against it. The API silently clamps a
page request at 1000 results with a message that reads like success, so "I asked for 2000
and got 1000" looks complete unless you compare. A read that falls short is reported as
partial, never published as a whole answer.
Output fields
One row per property. Every field below is emitted on every row; fields that could not be
determined are null, which means not checked — never no.
| Field | Type | Description |
|---|---|---|
label | string | Your label for the property, echoed back so rows can be joined to your portfolio. |
latitude | number | Latitude of the property as supplied, WGS84 decimal degrees. |
longitude | number | Longitude of the property as supplied, WGS84 decimal degrees. |
checked_at | string | UTC timestamp when this run queried USGS. |
buffer_miles | number | Search buffer applied. 0 means a true point-in-quadrangle test. |
query_geometry | string | point_intersects when buffer_miles is 0 (maps whose footprint covers the property), bbox_intersects otherwise. |
query_bbox | string | The exact bbox sent to the USGS TNM Access API, as minLon,minLat,maxLon,maxLat. |
aerial_photography_status | string | Always not_covered_by_this_actor. This is a STATUS, deliberately not a boolean: reporting false would be a checked-and-negative claim about a source this run never looked at. |
aerial_photography_note | string | Why aerial photography is out of scope and what that means for your ASTM 8.3.4 review. |
scope_note | string | Plain statement that this is a screening tool covering the USGS topographic-map leg only. |
data_source | string | Name of the upstream service. |
data_source_url | string | Endpoint queried. |
drift_gate_status | string | verified when every USGS verification probe completed and passed before your sites were touched. verified_degraded when the load-bearing probes passed but a corroborating probe could not be reached and was not run. skipped when verifyUpstream was off. A run whose load-bearing probes fail emits no rows at all. |
drift_negative_control_status | string | pass when the mid-Pacific control returned exactly zero, proving USGS applied the spatial filter. unavailable means the probe was attempted and USGS never answered - it does NOT mean the control failed. skipped means it was not run. Deliberately not a boolean: not-checked and checked-and-negative are different facts. |
drift_probes_verified | array | Names of the verification probes that completed and passed on this run. null when the check was skipped. |
drift_probes_unavailable | array | Names of probes that were attempted but never answered. Empty array means every probe completed. null when the check was skipped. |
drift_gate_note | string | Plain-language statement of exactly what was and was not confirmed about the USGS collection before your sites were screened. |
error | string | Populated only when the property could not be reviewed at all. null on a successful row. |
historical_topo_status | string | ok, partial, unavailable or not_requested for the Historical Topographic Maps collection. unavailable means NOT CHECKED - it never means no maps exist. |
historical_topo_error | string | Upstream error text when the historical collection did not answer. |
historical_topo_maps_total_reported | integer | The total USGS itself reported for this query. Read first and paged against, because the API silently clamps a page request at 1000. |
historical_topo_maps_retrieved | integer | How many historical products this run actually pulled down. |
historical_topo_complete | boolean | true only when retrieved equals the total USGS reported. false means the chronology below is built on a partial read. |
historical_topo_incomplete_reason | string | Why the historical read fell short of the reported total. |
historical_topo_echo_verified | boolean | true when USGS echoed back the exact collection tag and point this run asked for. Guards against a filter that is accepted, echoed and never applied. |
historical_topo_rows_verified | boolean | true when the returned products own bounding boxes actually contain the property. |
us_topo_status | string | ok, partial, unavailable or not_requested for the modern US Topo series (2009-present). |
us_topo_error | string | Upstream error text when US Topo did not answer. |
us_topo_maps_total_reported | integer | The total USGS reported for the US Topo query at this point. |
us_topo_maps_retrieved | integer | How many US Topo products this run actually pulled down. |
us_topo_complete | boolean | true only when retrieved equals the total USGS reported. |
us_topo_incomplete_reason | string | Why the US Topo read fell short of the reported total. |
us_topo_echo_verified | boolean | true when USGS echoed back the exact collection tag and point that was asked for. |
us_topo_rows_verified | boolean | true when the returned US Topo products own bounding boxes contain the property. |
sources_requested | array | Which USGS collections this run was asked to query. |
sources_ok | array | Which collections actually answered for this property. |
sources_failed | array | Which requested collections did not answer. Non-empty means every ASTM verdict field on this row is null. |
maps_total_products | integer | Total USGS map PRODUCTS covering the property across all queried collections. USGS scans multiple printings of the same sheet, so this is larger than the number of distinct maps - nine separate 1965 Englewood CO products cover the Denver test point. |
maps_distinct_editions | integer | Distinct collection + quadrangle + year + scale combinations. The de-duplicated count of actual map sheets. |
maps_distinct_years | integer | Number of distinct years for which at least one map covers the property. This is the number an ASTM 8.3.4 interval review turns on. |
map_years | array | Every distinct year with coverage, ascending. |
earliest_map_year | integer | Oldest year with coverage, across all queried collections. |
latest_map_year | integer | Most recent year with coverage, across all queried collections. |
coverage_span_years | integer | Latest map year minus earliest map year. |
largest_scale_denominator_any | integer | Smallest scale denominator found, i.e. the most detailed map covering the property. 24000 means a 1:24,000 quadrangle. |
quad_names | array | Every USGS quadrangle name covering the property. More than one is normal - names change between editions and scales. |
state_codes | array | State abbreviations parsed from the covering map titles. |
chronology | array | One entry per map year: map_year, product_count, edition_count, source_datasets, quad_names, scale_denominators, map_extents, and the largest-scale sheet for that year with its title, download URL and preview image URL. |
maps | array | Full per-product inventory: source_dataset, source_id, map_year, publication_date, publication_date_raw, publication_date_is_year_only, title_year, year_cross_check, title, quad_name, state_code, scale_denominator, map_extent, format, size_bytes, download_url, geotiff_url, preview_url, metadata_url, vendor_metadata_url, last_updated and the product bounding box. |
maps_listed | integer | How many products the maps array actually contains, after the maxMapsListed cap. |
maps_truncated_in_row | boolean | true when maps_listed is fewer than maps_total_products. Counts and the chronology are always computed over the complete result regardless. |
year_cross_check_disagreements | integer | How many products had a year in their title that disagreed with their publicationDate. Measured 0 across 6,079 live products; anything above 0 is a drift signal worth inspecting. |
astm_analysis_status | string | complete when every requested source answered in full, otherwise incomplete_source_failure - in which case every astm_* verdict below is null. |
astm_analysis_note | string | Why the analysis is incomplete, when it is. null on a complete run. |
astm_interval_years | integer | Length of each coverage interval. ASTM E1527-21 Sec. 8.3.4 calls for approximately five years. |
astm_review_start_year | integer | First year of the review window. 1940 is the standard baseline. |
astm_review_end_year | integer | Last year of the review window. |
astm_intervals_total | integer | How many intervals the review window contains. |
astm_intervals_covered | integer | Intervals with at least one covering map. null when a source did not answer. |
astm_intervals_uncovered | integer | Intervals with no covering map - candidate data gaps for this source. null when a source did not answer. |
astm_coverage_pct | number | Covered intervals as a percentage of the window. null when a source did not answer. |
astm_uncovered_intervals | array | Labels of the intervals with no covering topographic map. null when a source did not answer. |
astm_longest_uncovered_run_intervals | integer | Longest stretch of consecutive uncovered intervals. null when a source did not answer. |
astm_longest_uncovered_span | string | That stretch expressed as a year range. null when there is none, or when a source did not answer. |
astm_max_years_between_maps | integer | Largest number of years between consecutive covering maps inside the window, including the run-up from the review start and the run-out to the review end. This is the number a reviewer quotes when justifying a data gap. null when a source did not answer. |
astm_data_gap_present | boolean | true when at least one interval in the window has no covering topographic map. NULL means not determined - a requested source did not answer, and null is never the same as false. |
astm_back_to_review_start_satisfied | boolean | true when the earliest covering map falls within one interval of the review start year. null when a source did not answer. |
astm_interval_detail | array | One entry per interval: interval_start_year, interval_end_year, label, covered (null when undetermined), observed_covered, map_years, product_count and source_datasets. |
observed_intervals_covered | integer | Intervals covered by what this run actually saw. Populated even when the analysis is incomplete, so evidence is never withheld - but it is not a verdict. |
observed_intervals_uncovered | integer | Intervals not covered by what this run actually saw. Not a verdict when the analysis is incomplete. |
observed_uncovered_intervals | array | Labels of intervals not covered by what this run saw. |
observed_map_years_in_window | array | Map years found inside the review window. |
pre_review_window_map_years | array | Map years found EARLIER than the review start year. Relevant because ASTM 8.3.4 asks for coverage back to first developed use when that predates 1940. |
pre_review_window_coverage | boolean | true when at least one map predates the review start year. null when a source did not answer. |
earliest_map_year_any | integer | Earliest covering map year including those before the review window. |
latest_map_year_any | integer | Latest covering map year including those after the review window. |
Nested array shapes
chronology[] — one entry per map year:
map_year, product_count, edition_count, source_datasets[], quad_names[],
scale_denominators[], map_extents[], largest_scale_denominator,
largest_scale_title, largest_scale_download_url, largest_scale_preview_url.
astm_interval_detail[] — one entry per interval:
interval_start_year, interval_end_year, label, covered (null when undetermined),
observed_covered, map_years[], product_count, source_datasets[].
maps[] — one entry per map product:
source_dataset, source_id, map_year, publication_date, publication_date_raw,
publication_date_is_year_only, title_year, year_cross_check, title, quad_name,
state_code, scale_denominator, map_extent, format, size_bytes, download_url,
geotiff_url, preview_url, metadata_url, vendor_metadata_url, last_updated,
bbox_min_lon, bbox_min_lat, bbox_max_lon, bbox_max_lat.
Two notes on the data that will otherwise confuse you
publication_date is null on historical maps and that is correct. USGS stamps every
product in the historical collection YYYY-01-01. The year is real; the month and day are
placeholders. Publishing "January 1, 1965" would invent a printing date that does not
exist, so the year goes in map_year, the raw value stays in publication_date_raw, and
publication_date is only populated for US Topo, which carries a genuine full date.
maps_total_products is roughly double maps_distinct_editions, by design. USGS
scans multiple printings of the same sheet and publishes each as its own product — nine
separate 1965 Englewood, CO products cover the Denver test point. Counting products as
"maps covering this site" overstates the chronology about 2x. maps_distinct_years is the
number an ASTM interval review actually turns on.
Use as an MCP tool
This actor is callable by AI agents through mcp.apify.com. Every
input and output field carries a description, so an agent can pass a coordinate and read
back astm_data_gap_present, astm_uncovered_intervals and astm_max_years_between_maps
without guessing at semantics — and can tell "not determined" from "no gap", because the
first is null and the second is false.
Pricing
$10 per 1,000 results — one result per property, regardless of how many maps cover it or how many collections are queried. A failed run emits nothing and bills nothing.
Related actors (same Phase I buyer)
- EPA Contaminated Site Screener — Superfund/SEMS, RCRA CORRACTS/TSD, USTs, ECHO enforcement and institutional controls at ASTM E1527-21 search distances. The recognized-environmental-conditions leg to this actor's historical-records leg.
- Site Due Diligence Bundle — 20 federal and state layers for one coordinate in one call, with a composite site score and a go/caution/no-go verdict gated so it can never read "proceed" while a layer is unavailable.
- State Tank & Spill Registry Screener — the UST/LUST and spill-registry component of an EDR-equivalent bundle.
FAQ
How do I get historical topographic maps for an address?
Geocode it to latitude/longitude, pass it in assets, and every USGS quadrangle covering
that point comes back with its year, scale and a direct download URL for the GeoPDF and
GeoTIFF.
Does this satisfy ASTM E1527-21 §8.3.4? It does the topographic-map portion and identifies the interval gaps. §8.3.4 expects the standard historical sources as a set, so aerials, fire insurance maps, city directories and land title still need reviewing separately. An environmental professional makes the determination.
Why is a recent interval showing as uncovered at a well-mapped site?
US Topo revises a quadrangle roughly every three years and the current cycle may not have
reached yours yet. That is a genuine absence of a published map, not a failure — check
us_topo_status, which will read ok.
Why does one point return 27 maps but only 12 years?
USGS scans several printings of the same sheet. See maps_distinct_editions and
maps_distinct_years.
What happens if USGS is down? The run fails with a message naming the cause, emits no rows, and bills nothing. It never returns a row saying no maps were found.
Does it cover Alaska, Hawaii and the territories? Yes — the historical collection spans 45+ states plus territories (Puerto Rico quadrangles go back to 1947). Coverage depth varies by location, which is exactly what the interval review measures.
Is there an aerial photography option? No. NAIP returns zero results through this API, so there is no keyless aerial leg and this actor does not claim one.
Data source
USGS The National Map Access API —
Historical Topographic Maps and US Topo collections. Public domain, no key required.
Source characteristics were measured live 2026-08-04; the capture scripts and the drift
baselines ship with the actor.