While standard lookupLandscape calls omit the capture date to provide features
synthesized from multiple recent satellite images, some applications require
landscape data at a certain historical time point. For example, you might want
to observe year-over-year changes to field boundaries, farm ponds, or
tree cover.
To fetch landscape features from a historical date, use a "discover then retrieve" workflow: first identifying when imagery was captured for a region, and then requesting landscape features for that specific date.
Prerequisites
To follow this guide, you need:
- A basic understanding of Python.
- Familiarity with S2 geometry concepts. See Understanding the data for more information.
- An API key for the Agricultural Understanding API. See Setup for instructions on how to get an API key.
Discover and retrieve workflow
To fetch historical estimates, you interact with two endpoints in sequence:
- Discover: Issue a request to
lookupLandscapeCaptureDate, specifying the area of interest using a level 13 S2 cell ID. - Select: Extract an available
captureDatestructured asyear,month, anddayfrom the response. Dates are returned in ascending order in the response, so the earliest available date appears as the first entry. - Retrieve: Issue a request to
lookupLandscape, passing both thes2CellIdand the explicitcaptureDate.
Handle single-capture data limitations
When you omit captureDate in standard lookupLandscape calls, the API
synthesizes features from satellite imagery.
However, when supplying a specific captureDate, the API returns boundaries
extracted from satellite images only from that specific capture date. Single
satellite captures may have missing features due to cloud cover or atmospheric
haze.
Imagery availabilities vary based on location, and there might not be
satellite images in a selected date range. In such situations, we recommend
using the synthesized landscape features (without specifying a captureDate)
as a fallback. For details covering standard retrievals, refer to
Basic retrieval.
Historical retrieval example
The following Python example demonstrates the "discover then retrieve" workflow, first finding available dates and then retrieving the landscape for the first discovered date:
import json
import os
import requests
API_KEY = os.environ.get("AG_UNDERSTANDING_API_KEY")
if not API_KEY:
raise ValueError("Please set the 'AG_UNDERSTANDING_API_KEY' environment variable.")
date_url = "https://agriculturalunderstanding.googleapis.com/v1:lookupLandscapeCaptureDate"
lookup_url = "https://agriculturalunderstanding.googleapis.com/v1:lookupLandscape"
s2_cell_id = "4306523180387794944"
request_payload = {
"locationSpecifier": {
"s2CellId": s2_cell_id
}
}
# 1. Discover available dates
date_response = requests.post(date_url, json=request_payload, params={"key": API_KEY})
date_response.raise_for_status()
date_data = date_response.json()
available_dates = date_data.get("captureDates", [])
if available_dates:
# 2. Select the first available date
chosen_date = available_dates[0]
print(f"Discovered available data for: {chosen_date}")
# 3. Retrieve landscape for the explicit date
lookup_payload = {
"locationSpecifier": {
"s2CellId": s2_cell_id
},
"captureDate": chosen_date
}
lookup_response = requests.post(lookup_url, json=lookup_payload, params={"key": API_KEY})
lookup_response.raise_for_status()
lookup_data = lookup_response.json()
geojson_str = lookup_data.get("landscape", {}).get("geojson", "{}")
geojson_data = json.loads(geojson_str)
features = geojson_data.get("features", [])
print(f"Successfully retrieved {len(features)} landscape features for {chosen_date}.")
for feature in features:
alu_type = feature.get("properties", {}).get("alu_type")
area = feature.get("properties", {}).get("area_sq_m")
print(f"Feature type: {alu_type}, area: {area} sq m")
else:
print("No landscape data available for this location.")
Parsed capture dates
The endpoint returns an array of available dates for the requested S2 cell:
{
"captureDates": [
{
"year": 2011,
"month": 11,
"day": 10
},
{
"year": 2012,
"month": 4,
"day": 1
}
]
}
Parsed GeoJSON
When the stringified GeoJSON in landscape.geojson is parsed from the
historical lookupLandscape response, it expands to standard GeoJSON features:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "7M2JHHF6+MFWC",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[92.5612194, 10.5741646],
[92.5612194, 10.5742008],
[92.5612559, 10.5742551],
[92.5612467, 10.5742912],
[92.5612192, 10.5743094],
[92.5611644, 10.5743001],
[92.5611462, 10.5742731],
[92.5611462, 10.5742006],
[92.5611646, 10.5741555],
[92.5612194, 10.5741646]
]
]
]
},
"properties": {
"alu_type": "trees",
"area_sq_m": 149.7001,
"class_confidence": 1.0,
"capture_timestamp_sec": 1697353200
}
}
]
}
Payload breakdown:
- Capture timestamp: The
capture_timestamp_sec(for example,1697353200) reflects the Unix timestamp of the specific historical satellite capture. - Cross-references: For details on schema characteristics, see Response format.