USGS dataretrieval Python Package Groundwater-Level get_field_measurements() Examples

This notebook provides examples of using the Python dataretrieval package to retrieve groundwater level field measurements for a United States Geological Survey (USGS) monitoring location. The dataretrieval package provides a collection of functions to get data from the USGS Water Data API and other online sources of hydrology and water quality data.

Install the Package

Use the following code to install the package if it doesn’t exist already within your Jupyter Python environment.

[1]:
!pip install dataretrieval
Requirement already satisfied: dataretrieval in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (0.1.dev1+g2846fff54)
Requirement already satisfied: httpx in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from dataretrieval) (0.28.1)
Requirement already satisfied: pandas<4.0.0,>=2.0.0 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from dataretrieval) (3.1.0)
Requirement already satisfied: anyio>=4.0 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from dataretrieval) (4.15.1)
Requirement already satisfied: numpy>=2.0.2 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from pandas<4.0.0,>=2.0.0->dataretrieval) (2.5.4)
Requirement already satisfied: python-dateutil>=2.9.0 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from pandas<4.0.0,>=2.0.0->dataretrieval) (3.0.0)
Requirement already satisfied: idna>=2.8 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from anyio>=4.0->dataretrieval) (3.20)
Requirement already satisfied: typing_extensions>=4.16.0 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from anyio>=4.0->dataretrieval) (4.16.0)
Requirement already satisfied: six>=1.6 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from python-dateutil>=2.9.0->pandas<4.0.0,>=2.0.0->dataretrieval) (1.17.0)
Requirement already satisfied: tzdata in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from python-dateutil>=2.9.0->pandas<4.0.0,>=2.0.0->dataretrieval) (2026.6)
Requirement already satisfied: certifi in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from httpx->dataretrieval) (2026.10.23)
Requirement already satisfied: httpcore==1.* in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from httpx->dataretrieval) (1.0.9)
Requirement already satisfied: h11>=0.16 in /opt/hostedtoolcache/Python/3.13.17/x64/lib/python3.13/site-packages (from httpcore==1.*->httpx->dataretrieval) (0.16.0)

Load the package so you can use it along with other packages used in this notebook.

[2]:
from IPython.display import display

import dataretrieval.waterdata as waterdata

Basic Usage

The dataretrieval package has several functions that allow you to retrieve data from different services of the USGS Water Data API. This example uses the get_field_measurements() function to retrieve groundwater level field measurements. Field measurements are physically measured values collected during a visit to a monitoring location and are commonly used to record groundwater levels. The following arguments are commonly used:

  • monitoring_location_id (string or list of strings): A unique identifier representing one or more monitoring locations. IDs combine the responsible agency code with the location number, separated by a hyphen (e.g. USGS-434400121275801).

  • parameter_code (string or list of strings): One or more 5-digit codes identifying the constituent measured and its units of measure.

  • time (string): The date an observation represents. Accepts a single RFC 3339 date-time, a bounded or half-bounded interval (e.g. "1980-01-01/2000-12-31", "1980-01-01/.."), or an ISO 8601 duration (e.g. "P20Y"). Only observations whose time intersects this value are returned.

  • skip_geometry (boolean): If True, response geometries are omitted and the returned data frame contains no spatial information.

Example 1: Get groundwater level field measurements for a single monitoring location.

[3]:
# Set the parameters needed to retrieve data
site_id = "USGS-434400121275801"

# Retrieve the data
data = waterdata.get_field_measurements(monitoring_location_id=site_id)
print("Retrieved " + str(len(data[0])) + " data values.")
Retrieving: field-measurements · 1 page · 744 rows
Retrieved 744 data values.

Interpreting the Result

The get_field_measurements() function returns a tuple of two objects: a pandas data frame containing the requested data and an associated metadata object. The data frame is flat, using a default integer index, and the observation dates are held in its time column.

Once you’ve got the data frame, there are several useful things you can do to explore the data.

Display the data frame as a table

[4]:
display(data[0])
geometry field_measurements_series_id reading_type field_visit_id parameter_code monitoring_location_id observing_procedure_code observing_procedure value unit_of_measure ... measuring_agency last_modified control_condition measurement_rated year month day time_of_day sublocation_identifier field_measurement_id
0 POINT (-121.46711 43.73345) e9bcd145-2041-4124-b749-110c5bc2ada9 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62610 USGS-434400121275801 O GW level, estim, report, observ 4192.65 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 2e594ecb-9f37-46a3-b206-cafc0d7fa89b
1 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62611 USGS-434400121275801 O GW level, estim, report, observ 4196.67 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 38f74401-1767-4709-947b-c06cdd1c4473
2 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 72019 USGS-434400121275801 O GW level, estim, report, observ 27.35 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 73f803fc-c422-403e-97fd-97cb3a03127e
3 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 62611 USGS-434400121275801 O GW level, estim, report, observ 4194.34 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None 6a914e2b-5970-494f-a2f9-d2bb7a3837ff
4 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 72019 USGS-434400121275801 O GW level, estim, report, observ 29.68 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None a8900c6a-6fe2-4d8f-b51c-e0505e7da5a7
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
739 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary 065dc2e2-2e2d-4f40-8d50-3cb3afd914fe 72019 USGS-434400121275801 S GW level, steel tape 28.13 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 2015 10 22 17:52:00+00:00 None 89e01b0f-c42e-4ba4-a2d3-8b50fd7a7d5e
740 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary 065dc2e2-2e2d-4f40-8d50-3cb3afd914fe 62611 USGS-434400121275801 S GW level, steel tape 4195.89 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 2015 10 22 17:52:00+00:00 None 8ea3c629-15b6-4dd3-948b-db494f47c30e
741 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary 7b45dc93-704a-4b0d-9772-692a09abc95a 72019 USGS-434400121275801 S GW level, steel tape 28.33 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 2016 10 26 16:22:00+00:00 None 012a3b21-a77f-436a-8ef4-b87ec65dd9ba
742 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary 7b45dc93-704a-4b0d-9772-692a09abc95a 62611 USGS-434400121275801 S GW level, steel tape 4195.69 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 2016 10 26 16:22:00+00:00 None 111ea634-0ff4-485c-9c94-44c59dad6d2b
743 POINT (-121.46711 43.73345) e9bcd145-2041-4124-b749-110c5bc2ada9 ReferencePrimary 7b45dc93-704a-4b0d-9772-692a09abc95a 62610 USGS-434400121275801 S GW level, steel tape 4191.67 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 2016 10 26 16:22:00+00:00 None 4642be37-db24-42ec-85fa-d1c746cd776c

744 rows × 24 columns

Show the data types of the columns in the resulting data frame.

[5]:
print(data[0].dtypes)
geometry                                   geometry
field_measurements_series_id                    str
reading_type                                    str
field_visit_id                                  str
parameter_code                                  str
monitoring_location_id                          str
observing_procedure_code                        str
observing_procedure                             str
value                                       float64
unit_of_measure                                 str
time                                 datetime64[us]
qualifier                                    object
vertical_datum                                  str
approval_status                                 str
measuring_agency                                str
last_modified                   datetime64[us, UTC]
control_condition                            object
measurement_rated                            object
year                                          int64
month                                         int64
day                                           int64
time_of_day                                     str
sublocation_identifier                       object
field_measurement_id                            str
dtype: object

Get summary statistics for the measured groundwater level values.

[6]:
data[0]["value"].describe()
[6]:
count     744.000000
mean     2806.776465
std      1969.270464
min        10.900000
25%        27.385000
50%      4194.190000
75%      4199.645000
max      4213.120000
Name: value, dtype: float64

Make a quick time series plot.

[7]:
# This site reports several quantities (depth below land surface as well as
# water-surface elevations above NGVD29/NAVD88), so use a datum-neutral label.
ax = data[0][["time", "value"]].plot(x="time", y="value", style=".")
ax.set_xlabel("Date")
ax.set_ylabel("Water level (ft)")
[7]:
Text(0, 0.5, 'Water level (ft)')
../_images/examples_USGS_WaterData_GroundwaterLevels_Examples_16_1.png

The other part of the result returned from the get_field_measurements() function is a metadata object that contains information about the query that was executed to return the data. For example, you can access the URL that was assembled to retrieve the requested data from the USGS Water Data API.

[8]:
print("The query URL used to retrieve the data from the Water Data API was: " + data[1].url)
The query URL used to retrieve the data from the Water Data API was: https://api.waterdata.usgs.gov/ogcapi/v1/collections/field-measurements/items?monitoring_location_id=USGS-434400121275801&limit=50000

Additional Examples

You can also request data for multiple monitoring locations at the same time.

Example 2: Get data for multiple monitoring locations. The monitoring location ids are passed as a list of strings.

[9]:
site_ids = ["USGS-434400121275801", "USGS-375907091432201"]
data2 = waterdata.get_field_measurements(monitoring_location_id=site_ids)
print("Retrieved " + str(len(data2[0])) + " data values.")
display(data2[0])
Retrieving: field-measurements · 1 page · 933 rows
No API key detected — register for higher rate limits at https://api.waterdata.usgs.gov/signup/
Retrieved 933 data values.
geometry field_measurements_series_id reading_type field_visit_id parameter_code monitoring_location_id observing_procedure_code observing_procedure value unit_of_measure ... measuring_agency last_modified control_condition measurement_rated year month day time_of_day sublocation_identifier field_measurement_id
0 POINT (-121.46711 43.73345) e9bcd145-2041-4124-b749-110c5bc2ada9 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62610 USGS-434400121275801 O GW level, estim, report, observ 4192.65 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 2e594ecb-9f37-46a3-b206-cafc0d7fa89b
1 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62611 USGS-434400121275801 O GW level, estim, report, observ 4196.67 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 38f74401-1767-4709-947b-c06cdd1c4473
2 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 72019 USGS-434400121275801 O GW level, estim, report, observ 27.35 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 73f803fc-c422-403e-97fd-97cb3a03127e
3 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 62611 USGS-434400121275801 O GW level, estim, report, observ 4194.34 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None 6a914e2b-5970-494f-a2f9-d2bb7a3837ff
4 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 72019 USGS-434400121275801 O GW level, estim, report, observ 29.68 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None a8900c6a-6fe2-4d8f-b51c-e0505e7da5a7
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
928 POINT (-91.72294 37.98615) f2ee268b-e080-45db-be0b-926150fb0fae ReferencePrimary 48bfbbaa-5db8-4ba2-9e90-742166552bec 72019 USGS-375907091432201 V GW level, calib electric tape 310.46 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 6 19 16:04:00+00:00 None 6fd6f05b-4370-4133-a3ba-e9b6d92bd721
929 POINT (-91.72294 37.98615) 4d3667e7-6eb2-4cde-8458-b4a24096cfd1 ReferencePrimary 48bfbbaa-5db8-4ba2-9e90-742166552bec 62610 USGS-375907091432201 V GW level, calib electric tape 878.54 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 6 19 16:04:00+00:00 None 9ec235c6-ca2b-48b6-b825-bfd0981ead31
930 POINT (-91.72294 37.98615) 3c26120c-0be9-4e52-8435-370bd37ed6c0 ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 62611 USGS-375907091432201 V GW level, calib electric tape 875.66 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None 82159f75-87da-4ae0-9264-5b35e9647d50
931 POINT (-91.72294 37.98615) 4d3667e7-6eb2-4cde-8458-b4a24096cfd1 ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 62610 USGS-375907091432201 V GW level, calib electric tape 875.52 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None b6fc2e2c-b158-4400-b172-130ac1f93a7c
932 POINT (-91.72294 37.98615) f2ee268b-e080-45db-be0b-926150fb0fae ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 72019 USGS-375907091432201 V GW level, calib electric tape 313.48 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None f29ec961-5ba1-441c-9b2e-9448ef8721fc

933 rows × 24 columns

The following example requests the same data as the previous example, again passing the monitoring location ids as a list of strings.

[10]:
site_ids = ["USGS-434400121275801", "USGS-375907091432201"]
data2 = waterdata.get_field_measurements(monitoring_location_id=site_ids, )
print("Retrieved " + str(len(data2[0])) + " data values.")
display(data2[0])
Retrieving: field-measurements · 1 page · 933 rows
Retrieved 933 data values.
geometry field_measurements_series_id reading_type field_visit_id parameter_code monitoring_location_id observing_procedure_code observing_procedure value unit_of_measure ... measuring_agency last_modified control_condition measurement_rated year month day time_of_day sublocation_identifier field_measurement_id
0 POINT (-121.46711 43.73345) e9bcd145-2041-4124-b749-110c5bc2ada9 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62610 USGS-434400121275801 O GW level, estim, report, observ 4192.65 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 2e594ecb-9f37-46a3-b206-cafc0d7fa89b
1 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 62611 USGS-434400121275801 O GW level, estim, report, observ 4196.67 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 38f74401-1767-4709-947b-c06cdd1c4473
2 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary c722cb49-bca8-446f-9b4d-3b152729bb39 72019 USGS-434400121275801 O GW level, estim, report, observ 27.35 ft ... USGS 2026-10-10 04:03:50.147693+00:00 None None 1945 10 12 22:35:00+00:00 None 73f803fc-c422-403e-97fd-97cb3a03127e
3 POINT (-121.46711 43.73345) ac601371-e12d-4b22-85db-0c511cea7790 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 62611 USGS-434400121275801 O GW level, estim, report, observ 4194.34 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None 6a914e2b-5970-494f-a2f9-d2bb7a3837ff
4 POINT (-121.46711 43.73345) 03469d22-7a5f-4bbe-ba60-b808afaf7e36 ReferencePrimary 0217fd12-a22a-4f4f-a43c-3b9907e2fcc3 72019 USGS-434400121275801 O GW level, estim, report, observ 29.68 ft ... OR004 2026-10-10 04:03:50.147693+00:00 None None 1946 7 12 NaN None a8900c6a-6fe2-4d8f-b51c-e0505e7da5a7
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
928 POINT (-91.72294 37.98615) f2ee268b-e080-45db-be0b-926150fb0fae ReferencePrimary 48bfbbaa-5db8-4ba2-9e90-742166552bec 72019 USGS-375907091432201 V GW level, calib electric tape 310.46 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 6 19 16:04:00+00:00 None 6fd6f05b-4370-4133-a3ba-e9b6d92bd721
929 POINT (-91.72294 37.98615) 4d3667e7-6eb2-4cde-8458-b4a24096cfd1 ReferencePrimary 48bfbbaa-5db8-4ba2-9e90-742166552bec 62610 USGS-375907091432201 V GW level, calib electric tape 878.54 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 6 19 16:04:00+00:00 None 9ec235c6-ca2b-48b6-b825-bfd0981ead31
930 POINT (-91.72294 37.98615) 3c26120c-0be9-4e52-8435-370bd37ed6c0 ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 62611 USGS-375907091432201 V GW level, calib electric tape 875.66 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None 82159f75-87da-4ae0-9264-5b35e9647d50
931 POINT (-91.72294 37.98615) 4d3667e7-6eb2-4cde-8458-b4a24096cfd1 ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 62610 USGS-375907091432201 V GW level, calib electric tape 875.52 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None b6fc2e2c-b158-4400-b172-130ac1f93a7c
932 POINT (-91.72294 37.98615) f2ee268b-e080-45db-be0b-926150fb0fae ReferencePrimary 68eeb933-ea4d-4e8c-be48-605c06cb36fc 72019 USGS-375907091432201 V GW level, calib electric tape 313.48 ft ... MO005 2026-10-25 04:14:27.241239+00:00 None None 2020 8 31 13:00:00+00:00 None f29ec961-5ba1-441c-9b2e-9448ef8721fc

933 rows × 24 columns

Some groundwater level data have dates that include only a year or a month and year, but no day.

Example 3: Retrieve groundwater level data that have dates without a day.

[11]:
data3 = waterdata.get_field_measurements(monitoring_location_id="USGS-425957088141001")
print("Retrieved " + str(len(data3[0])) + " data values.")

# Observation dates live in the 'time' column (the data frame uses a plain
# integer index). Where the original record gave only a year or a year and
# month, the Water Data API normalizes the value to a UTC timestamp with the
# missing day/time defaulted, so these appear as ordinary timestamps.
print(data3[0]["time"].head(10))
Retrieving: field-measurements · 1 page · 102 rows
Retrieved 102 data values.
0   1945-12-01
1   1945-12-01
2   1945-12-01
3   1946-12-01
4   1946-12-01
5   1946-12-01
6   1947-01-01
7   1947-01-01
8   1947-01-01
9   1948-01-01
Name: time, dtype: datetime64[us]

If you want to inspect the request that was sent, you can get the URL for the query that was issued to the USGS Water Data API.

[12]:
# Print the URL used to retrieve the data
print("You can examine the data retrieved from the Water Data API at: " + data3[1].url)
You can examine the data retrieved from the Water Data API at: https://api.waterdata.usgs.gov/ogcapi/v1/collections/field-measurements/items?monitoring_location_id=USGS-425957088141001&limit=50000

You can also retrieve data for a monitoring location within a specified time window by giving a start and end date.

Example 4: Get groundwater level data for a monitoring location between a start and end date.

[13]:
data4 = waterdata.get_field_measurements(monitoring_location_id=site_id, time="1980-01-01/2000-12-31")
print("Retrieved " + str(len(data4[0])) + " data values.")
Retrieving: field-measurements · 1 page · 213 rows
Retrieved 213 data values.