Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4 avatar

Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4

Under maintenance

Pricing

from $5.50 / 1,000 results

Go to Apify Store
Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4

Historical Topographic Map Chronology - ASTM Phase I ESA 8.3.4

Under maintenance

Builds 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

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

19 hours ago

Last modified

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_maps to 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

  1. Queries USGS Historical Topographic Maps (186,062 products nationally, ~1884 to the 1990s) for the maps whose own footprint covers your point.
  2. 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.
  3. 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.
  4. 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: 0 for 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 carries aerial_photography_status: "not_covered_by_this_actor" — a status string, deliberately not a boolean, because false would 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.
  • null never means "no". On this actor null means not checked and false means checked and negative. If a source did not answer, every ASTM verdict field is null, the observed_* fields still report what the run did see, and astm_analysis_status reads incomplete_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

InputDefaultWhat it does
assets(required)Array of {lat, lon, label}. One billable row each.
bufferMiles00 = maps covering the point. Above 0 widens to an intersecting box.
includeUsTopotrueAdds the modern 2009+ US Topo series. Does not change billing.
reviewStartYear1940First year of the ASTM review window.
reviewEndYearcurrent yearLast year of the review window.
intervalYears5Interval length. §8.3.4 calls for approximately five years.
maxMapsListed200Caps the per-row maps inventory. Counts and chronology are always complete.
maxAssets250Safety cap on sites per run.
verifyUpstreamtrueRuns the live drift check before touching your sites.
simulateOutagenoneDiagnostic: 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.

FieldTypeDescription
labelstringYour label for the property, echoed back so rows can be joined to your portfolio.
latitudenumberLatitude of the property as supplied, WGS84 decimal degrees.
longitudenumberLongitude of the property as supplied, WGS84 decimal degrees.
checked_atstringUTC timestamp when this run queried USGS.
buffer_milesnumberSearch buffer applied. 0 means a true point-in-quadrangle test.
query_geometrystringpoint_intersects when buffer_miles is 0 (maps whose footprint covers the property), bbox_intersects otherwise.
query_bboxstringThe exact bbox sent to the USGS TNM Access API, as minLon,minLat,maxLon,maxLat.
aerial_photography_statusstringAlways 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_notestringWhy aerial photography is out of scope and what that means for your ASTM 8.3.4 review.
scope_notestringPlain statement that this is a screening tool covering the USGS topographic-map leg only.
data_sourcestringName of the upstream service.
data_source_urlstringEndpoint queried.
drift_gate_statusstringverified 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_statusstringpass 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_verifiedarrayNames of the verification probes that completed and passed on this run. null when the check was skipped.
drift_probes_unavailablearrayNames of probes that were attempted but never answered. Empty array means every probe completed. null when the check was skipped.
drift_gate_notestringPlain-language statement of exactly what was and was not confirmed about the USGS collection before your sites were screened.
errorstringPopulated only when the property could not be reviewed at all. null on a successful row.
historical_topo_statusstringok, partial, unavailable or not_requested for the Historical Topographic Maps collection. unavailable means NOT CHECKED - it never means no maps exist.
historical_topo_errorstringUpstream error text when the historical collection did not answer.
historical_topo_maps_total_reportedintegerThe 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_retrievedintegerHow many historical products this run actually pulled down.
historical_topo_completebooleantrue only when retrieved equals the total USGS reported. false means the chronology below is built on a partial read.
historical_topo_incomplete_reasonstringWhy the historical read fell short of the reported total.
historical_topo_echo_verifiedbooleantrue 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_verifiedbooleantrue when the returned products own bounding boxes actually contain the property.
us_topo_statusstringok, partial, unavailable or not_requested for the modern US Topo series (2009-present).
us_topo_errorstringUpstream error text when US Topo did not answer.
us_topo_maps_total_reportedintegerThe total USGS reported for the US Topo query at this point.
us_topo_maps_retrievedintegerHow many US Topo products this run actually pulled down.
us_topo_completebooleantrue only when retrieved equals the total USGS reported.
us_topo_incomplete_reasonstringWhy the US Topo read fell short of the reported total.
us_topo_echo_verifiedbooleantrue when USGS echoed back the exact collection tag and point that was asked for.
us_topo_rows_verifiedbooleantrue when the returned US Topo products own bounding boxes contain the property.
sources_requestedarrayWhich USGS collections this run was asked to query.
sources_okarrayWhich collections actually answered for this property.
sources_failedarrayWhich requested collections did not answer. Non-empty means every ASTM verdict field on this row is null.
maps_total_productsintegerTotal 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_editionsintegerDistinct collection + quadrangle + year + scale combinations. The de-duplicated count of actual map sheets.
maps_distinct_yearsintegerNumber 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_yearsarrayEvery distinct year with coverage, ascending.
earliest_map_yearintegerOldest year with coverage, across all queried collections.
latest_map_yearintegerMost recent year with coverage, across all queried collections.
coverage_span_yearsintegerLatest map year minus earliest map year.
largest_scale_denominator_anyintegerSmallest scale denominator found, i.e. the most detailed map covering the property. 24000 means a 1:24,000 quadrangle.
quad_namesarrayEvery USGS quadrangle name covering the property. More than one is normal - names change between editions and scales.
state_codesarrayState abbreviations parsed from the covering map titles.
chronologyarrayOne 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.
mapsarrayFull 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_listedintegerHow many products the maps array actually contains, after the maxMapsListed cap.
maps_truncated_in_rowbooleantrue when maps_listed is fewer than maps_total_products. Counts and the chronology are always computed over the complete result regardless.
year_cross_check_disagreementsintegerHow 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_statusstringcomplete when every requested source answered in full, otherwise incomplete_source_failure - in which case every astm_* verdict below is null.
astm_analysis_notestringWhy the analysis is incomplete, when it is. null on a complete run.
astm_interval_yearsintegerLength of each coverage interval. ASTM E1527-21 Sec. 8.3.4 calls for approximately five years.
astm_review_start_yearintegerFirst year of the review window. 1940 is the standard baseline.
astm_review_end_yearintegerLast year of the review window.
astm_intervals_totalintegerHow many intervals the review window contains.
astm_intervals_coveredintegerIntervals with at least one covering map. null when a source did not answer.
astm_intervals_uncoveredintegerIntervals with no covering map - candidate data gaps for this source. null when a source did not answer.
astm_coverage_pctnumberCovered intervals as a percentage of the window. null when a source did not answer.
astm_uncovered_intervalsarrayLabels of the intervals with no covering topographic map. null when a source did not answer.
astm_longest_uncovered_run_intervalsintegerLongest stretch of consecutive uncovered intervals. null when a source did not answer.
astm_longest_uncovered_spanstringThat stretch expressed as a year range. null when there is none, or when a source did not answer.
astm_max_years_between_mapsintegerLargest 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_presentbooleantrue 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_satisfiedbooleantrue when the earliest covering map falls within one interval of the review start year. null when a source did not answer.
astm_interval_detailarrayOne 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_coveredintegerIntervals 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_uncoveredintegerIntervals not covered by what this run actually saw. Not a verdict when the analysis is incomplete.
observed_uncovered_intervalsarrayLabels of intervals not covered by what this run saw.
observed_map_years_in_windowarrayMap years found inside the review window.
pre_review_window_map_yearsarrayMap 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_coveragebooleantrue when at least one map predates the review start year. null when a source did not answer.
earliest_map_year_anyintegerEarliest covering map year including those before the review window.
latest_map_year_anyintegerLatest 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.

  • 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 APIHistorical 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.