Client Libraries
Client Libraries
The NLDI can be accessed directly via HTTP (see Getting Started ), but client libraries handle request construction, pagination, and geospatial output formatting so you can focus on analysis rather than URL assembly.
Three libraries cover the most common workflows:
- Python — PyNHD , part of the HyRiver suite
- R — dataRetrieval , the most widely used USGS data access package, with a convenience NLDI interface
- R — nhdplusTools , granular NLDI functions for spatial and network analysis
The examples below parallel the topics covered in the sibling documentation pages — Feature Sources , Navigation , and Basin and Hydrolocation — and show how to accomplish each operation using the library rather than raw HTTP.
Python — PyNHD (HyRiver)
PyNHD is the NLDI component of the HyRiver suite, a collection of Python packages for retrieving hydrological and meteorological data from web services. Companion packages (PyGeoHydro, PyDaymet, Py3DEP, etc.) complement NLDI navigation with streamflow, climate, and elevation data.
All NLDI functions are accessed through the NLDI() class. Output is always a
GeoPandas GeoDataFrame in EPSG:4326.
Install via conda (recommended for geospatial work) or pip:
conda install -c conda-forge pynhd
pip install pynhd
Feature Sources
See Registered Feature Sources
for full API
semantics. Feature sources in PyNHD are referenced by string — "nwissite",
"huc12pp", "comid", etc.
from pynhd import NLDI
nldi = NLDI()
# Retrieve the NLDI record for a NWIS surface-water site
site = nldi.getfeature_byid("nwissite", "USGS-05428500")
site
geometry ... mainstem
0 POINT (-89.36083 43.08944) ... https://geoconnex.us/ref/mainstems/377002
[1 rows x 12 columns]
The comid feature source’s position endpoint is available through
comid_byloc():
# Find the NHDPlusV2 catchment containing a point
# Coordinates are (longitude, latitude)
comid = nldi.comid_byloc((-89.35, 43.0864))
comid
geometry identifier ... type uri
0 POINT (-89.35306 43.08451) ... hydrolocation
[1 rows x 11 columns]
Navigation
See Navigation Modes
for endpoint structure and mode
descriptions. The navigate_byid() method wraps the
/navigation/{mode}/{dataSource}?distance= endpoint.
PyNHD uses descriptive strings for navigation modes:
| PyNHD string | API mode | Description |
|---|---|---|
"upstreamMain" |
UM | Upstream mainstem |
"upstreamTributaries" |
UT | Upstream with tributaries |
"downstreamMain" |
DM | Downstream mainstem |
"downstreamDiversions" |
DD | Downstream with diversions |
# Navigate upstream with tributaries from a NWIS gage, returning flowlines
flowlines = nldi.navigate_byid(
fsource="nwissite",
fid="USGS-05428500",
navigation="upstreamTributaries",
source="flowlines",
distance=100,
)
print(f"{len(flowlines)} flowlines returned")
168 flowlines returned
flowlines.head()
geometry nhdplus_comid
0 LINESTRING (-89.37037 43.09491, -89.36997 43.0... 13293750
1 LINESTRING (-89.38441 43.09903, -89.38351 43.0... 13294312
2 LINESTRING (-89.37836 43.12705, -89.37849 43.1... 13294308
3 LINESTRING (-89.41003 43.10678, -89.40898 43.1... 13294310
4 LINESTRING (-89.37711 43.1276, -89.37836 43.12... 13293634
# Collect all NWIS sites within 100 km upstream
nwis_sites = nldi.navigate_byid(
fsource="nwissite",
fid="USGS-05428500",
navigation="upstreamTributaries",
source="nwissite",
distance=100,
)
print(f"{len(nwis_sites)} NWIS sites found upstream")
53 NWIS sites found upstream
nwis_sites.head()
geometry ... mainstem
0 POINT (-89.43683 43.14683) ... https://geoconnex.us/ref/mainstems/467897
1 POINT (-89.43683 43.14683) ... https://geoconnex.us/ref/mainstems/467897
2 POINT (-89.37012 43.095) ... https://geoconnex.us/ref/mainstems/377002
3 POINT (-89.44231 43.14028) ... NaN
4 POINT (-89.47186 43.14506) ... NaN
[5 rows x 12 columns]
The distance parameter is always in kilometers and must be provided
explicitly.
Basin and Hydrolocation
See Basin and Hydrolocation for algorithm details including the split-catchment and raindrop-trace workflows.
# Retrieve the full upstream basin polygon (simplified by default)
basin = nldi.get_basins(
feature_ids="USGS-05428500",
fsource="nwissite",
)
basin
geometry
identifier
USGS-05428500 POLYGON ((-89.35738 43.11701, -89.35423 43.115...
feature_ids accepts a single string or a list of IDs from the same
fsource. simplified=True (the default) returns a reduced-vertex polygon
suitable for display; set simplified=False for full-resolution geometry.
Location-based hydrolocation snaps a coordinate to the nearest flowline:
# Snap a coordinate to the nearest flowline (within 200 m)
# or trace via the raindrop algorithm
feature = nldi.feature_byloc((-89.35, 43.0864))
feature
geometry ... comid
0 LINESTRING (-89.35393 43.08521, -89.35385 43.0... ... 13294318
[1 rows x 6 columns]
R — dataRetrieval
dataRetrieval
is the most widely
used USGS R package for retrieving water data from NWIS, WQP, and related
services. Its findNLDI() function provides a single-call interface that
combines feature lookup, navigation, and basin retrieval — it is the fastest
path from “I have a gage ID” to “I have upstream features and data.”
Install from CRAN:
install.packages("dataRetrieval")
Feature Sources
See Registered Feature Sources
for full API
semantics. findNLDI() accepts a starting point through named arguments —
nwis, comid, wqp, huc12, or location for coordinates — so you do not
need to construct a feature-source string manually.
library(dataRetrieval)
# Look up the NLDI record for a NWIS site
result <- findNLDI(nwis = "05428500")
# result$origin is an sf point with the gage's NLDI attributes
result$origin
Simple feature collection with 1 feature and 8 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -89.36083 ymin: 43.08944 xmax: -89.36083 ymax: 43.08944
Geodetic CRS: WGS 84
# A tibble: 1 × 9
sourceName identifier comid name reachcode measure X Y
<chr> <chr> <int> <chr> <chr> <dbl> <dbl> <dbl>
1 NWIS Surface Water Sites USGS-0542… 1.33e7 YAHA… 07090002… 42.0 -89.4 43.1
# ℹ 1 more variable: geometry <POINT [°]>
To list all available feature sources:
get_nldi_sources()
source sourceName
1 ca_gages Streamgage catalog for CA SB19
2 census2020-nhdpv2 2020 Census Block - NHDPlusV2 Catchment Intersections
3 epa_nrsa EPA National Rivers and Streams Assessment
4 geoconnex-demo geoconnex contribution demo sites
5 gfv11_pois USGS Geospatial Fabric V1.1 Points of Interest
6 GRAND Selected GRAND Reservoirs
7 HILARRI HILARRI Hydropower Infrastructure
8 huc12pp HUC12 Pour Points NHDPlusV2
9 huc12pp_102020 HUC12 Pour Points circa 10-2020
10 nmwdi-st New Mexico Water Data Initative Sites
11 npdes NPDES Facilities that Discharge to Water
12 nwisgw NWIS Groundwater Sites
13 nwissite NWIS Surface Water Sites
14 ref_dams geoconnex.us reference dams
15 ref_gage geoconnex.us reference gages
16 vigil Vigil Network Data
17 wade Water Data Exchange 2.0 Sites
18 wade_rights Water Data Exchange Water Rights
19 wade_timeseries Water Data Exchange Time Series
20 WQP Water Quality Portal
21 comid NHDPlus comid
features
1 https://api.water.usgs.gov/nldi/linked-data/ca_gages
2 https://api.water.usgs.gov/nldi/linked-data/census2020-nhdpv2
3 https://api.water.usgs.gov/nldi/linked-data/epa_nrsa
4 https://api.water.usgs.gov/nldi/linked-data/geoconnex-demo
5 https://api.water.usgs.gov/nldi/linked-data/gfv11_pois
6 https://api.water.usgs.gov/nldi/linked-data/grand
7 https://api.water.usgs.gov/nldi/linked-data/hilarri
8 https://api.water.usgs.gov/nldi/linked-data/huc12pp
9 https://api.water.usgs.gov/nldi/linked-data/huc12pp_102020
10 https://api.water.usgs.gov/nldi/linked-data/nmwdi-st
11 https://api.water.usgs.gov/nldi/linked-data/npdes
12 https://api.water.usgs.gov/nldi/linked-data/nwisgw
13 https://api.water.usgs.gov/nldi/linked-data/nwissite
14 https://api.water.usgs.gov/nldi/linked-data/ref_dams
15 https://api.water.usgs.gov/nldi/linked-data/ref_gage
16 https://api.water.usgs.gov/nldi/linked-data/vigil
17 https://api.water.usgs.gov/nldi/linked-data/wade
18 https://api.water.usgs.gov/nldi/linked-data/wade_rights
19 https://api.water.usgs.gov/nldi/linked-data/wade_timeseries
20 https://api.water.usgs.gov/nldi/linked-data/wqp
21 https://api.water.usgs.gov/nldi/linked-data/comid
Navigation
See Navigation Modes
for mode descriptions and the
distance parameter. The nav argument accepts the two-letter mode codes
("UM", "UT", "DM", "DD") and the find argument specifies which data
sources to return.
# Navigate upstream with tributaries from a NWIS site
# Collect flowlines within 100 km
ut_flowlines <- findNLDI(
nwis = "05428500",
nav = "UT",
find = c("flowlines"),
distance_km = 100
)
head(ut_flowlines$UT_flowlines)
Simple feature collection with 6 features and 1 field
Geometry type: LINESTRING
Dimension: XY
Bounding box: xmin: -89.42124 ymin: 43.08521 xmax: -89.35393 ymax: 43.1326
Geodetic CRS: WGS 84
# A tibble: 6 × 2
nhdplus_comid geometry
<chr> <LINESTRING [°]>
1 13293750 (-89.37037 43.09491, -89.36997 43.09475, -89.36916 43.09425, -8…
2 13294312 (-89.38441 43.09903, -89.38351 43.09872, -89.3824 43.09866, -89…
3 13294308 (-89.37836 43.12705, -89.37849 43.12689, -89.38291 43.12426, -8…
4 13294310 (-89.41003 43.10678, -89.40898 43.10619, -89.40492 43.10585, -8…
5 13293634 (-89.37711 43.1276, -89.37836 43.12705)
6 13294304 (-89.42001 43.1326, -89.42044 43.13194, -89.42124 43.12364, -89…
# Collect upstream NWIS sites within 100 km
ut_sites <- findNLDI(
nwis = "05428500",
nav = "UT",
find = c("nwissite"),
distance_km = 100
)
head(ut_sites$UT_nwissite)
Simple feature collection with 6 features and 8 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -89.52151 ymin: 43.09861 xmax: -89.26123 ymax: 43.2011
Geodetic CRS: WGS 84
# A tibble: 6 × 9
sourceName identifier comid name reachcode measure X Y
<chr> <chr> <int> <chr> <chr> <dbl> <dbl> <dbl>
1 NWIS Surface Water Sites USGS-0542… 1.33e7 TOKE… 07090002… 12.1 -89.3 43.2
2 NWIS Surface Water Sites USGS-0542… 1.33e7 DORN… 07090002… 15.9 -89.4 43.1
3 NWIS Surface Water Sites USGS-0542… 1.33e7 PHEA… 07090002… 40.7 -89.5 43.1
4 NWIS Surface Water Sites USGS-0542… 1.33e7 SIXM… 07090002… 1.83 -89.5 43.2
5 NWIS Surface Water Sites USGS-0542… 1.33e7 SIXM… 07090002… 82.6 -89.5 43.2
6 NWIS Surface Water Sites USGS-0542… 1.33e7 S FO… 07090002… 53.8 -89.5 43.1
# ℹ 1 more variable: geometry <POINT [°]>
Start from a coordinate instead of a known feature:
result_loc <- findNLDI(
location = c(-89.35, 43.0864),
nav = "UT",
find = c("flowlines"),
distance_km = 50
)
nrow(result_loc$UT_flowlines)
[1] 169
Basin
See Basin and Hydrolocation
for algorithm details.
"basin" is a special value in the find argument that retrieves the full
upstream drainage polygon.
result <- findNLDI(
nwis = "05428500",
find = c("basin")
)
result$basin
Simple feature collection with 1 feature and 0 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -89.60465 ymin: 43.03507 xmax: -89.20378 ymax: 43.36607
Geodetic CRS: WGS 84
# A tibble: 1 × 1
geometry
<POLYGON [°]>
1 ((-89.35738 43.11701, -89.35423 43.11546, -89.35437 43.11067, -89.34997 43.10…
R — nhdplusTools
nhdplusTools
provides separate
functions that map directly to individual NLDI endpoints, giving fine-grained
control over each step. It returns sf data frames in WGS 84 and is best
suited for spatial and network analysis workflows that go beyond simple feature
discovery.
Install from CRAN:
install.packages("nhdplusTools")
All nhdplusTools NLDI functions take an nldi_feature argument — a named list
that maps directly to the {featureSource}/{featureID} URL structure documented
in Getting Started
:
library(nhdplusTools)
nldi_feature <- list(featureSource = "nwissite", featureID = "USGS-05428500")
Feature Sources
See Registered Feature Sources for full API semantics.
# List all available feature sources
sources <- get_nldi_sources()
head(sources)
source sourceName
1 ca_gages Streamgage catalog for CA SB19
2 census2020-nhdpv2 2020 Census Block - NHDPlusV2 Catchment Intersections
3 epa_nrsa EPA National Rivers and Streams Assessment
4 geoconnex-demo geoconnex contribution demo sites
5 gfv11_pois USGS Geospatial Fabric V1.1 Points of Interest
6 GRAND Selected GRAND Reservoirs
features
1 https://api.water.usgs.gov/nldi/linked-data/ca_gages
2 https://api.water.usgs.gov/nldi/linked-data/census2020-nhdpv2
3 https://api.water.usgs.gov/nldi/linked-data/epa_nrsa
4 https://api.water.usgs.gov/nldi/linked-data/geoconnex-demo
5 https://api.water.usgs.gov/nldi/linked-data/gfv11_pois
6 https://api.water.usgs.gov/nldi/linked-data/grand
# Retrieve the NLDI record for a specific site
feature <- get_nldi_feature(nldi_feature)
feature
Simple feature collection with 1 feature and 8 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -89.36083 ymin: 43.08944 xmax: -89.36083 ymax: 43.08944
Geodetic CRS: WGS 84
# A tibble: 1 × 9
sourceName identifier comid name reachcode measure X Y
<chr> <chr> <int> <chr> <chr> <dbl> <dbl> <dbl>
1 NWIS Surface Water Sites USGS-0542… 1.33e7 YAHA… 07090002… 42.0 -89.4 43.1
# ℹ 1 more variable: geometry <POINT [°]>
Navigation
See Navigation Modes for endpoint structure and mode descriptions.
nhdplusTools mode |
API mode | Description |
|---|---|---|
"UM" |
UM | Upstream mainstem |
"UT" |
UT | Upstream with tributaries |
"DM" |
DM | Downstream mainstem |
"DD" |
DD | Downstream with diversions |
# Navigate upstream with tributaries, collecting flowlines
flowlines <- navigate_nldi(
nldi_feature,
mode = "UT",
data_source = "flowlines",
distance_km = 100
)
nrow(flowlines)
NULL
head(flowlines)
$origin
Simple feature collection with 1 feature and 8 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -89.36083 ymin: 43.08944 xmax: -89.36083 ymax: 43.08944
Geodetic CRS: WGS 84
# A tibble: 1 × 9
sourceName identifier comid name reachcode measure X Y
<chr> <chr> <int> <chr> <chr> <dbl> <dbl> <dbl>
1 NWIS Surface Water Sites USGS-0542… 1.33e7 YAHA… 07090002… 42.0 -89.4 43.1
# ℹ 1 more variable: geometry <POINT [°]>
$UT_flowlines
Simple feature collection with 168 features and 1 field
Geometry type: LINESTRING
Dimension: XY
Bounding box: xmin: -89.58537 ymin: 43.08521 xmax: -89.21254 ymax: 43.30179
Geodetic CRS: WGS 84
# A tibble: 168 × 2
nhdplus_comid geometry
<chr> <LINESTRING [°]>
1 13293750 (-89.37037 43.09491, -89.36997 43.09475, -89.36916 43.09425, -…
2 13294312 (-89.38441 43.09903, -89.38351 43.09872, -89.3824 43.09866, -8…
3 13294308 (-89.37836 43.12705, -89.37849 43.12689, -89.38291 43.12426, -…
4 13294310 (-89.41003 43.10678, -89.40898 43.10619, -89.40492 43.10585, -…
5 13293634 (-89.37711 43.1276, -89.37836 43.12705)
6 13294304 (-89.42001 43.1326, -89.42044 43.13194, -89.42124 43.12364, -8…
7 13294314 (-89.48229 43.10496, -89.48217 43.10476, -89.48196 43.10419, -…
8 13294368 (-89.37131 43.12712, -89.37711 43.1276)
9 13294298 (-89.4151 43.145, -89.41507 43.14339, -89.41639 43.1413, -89.4…
10 13294300 (-89.43469 43.14222, -89.43362 43.14176, -89.43142 43.14151, -…
# ℹ 158 more rows
# Collect NWIS sites upstream
nwis_upstream <- navigate_nldi(
nldi_feature,
mode = "UT",
data_source = "nwissite",
distance_km = 100
)
nrow(nwis_upstream)
NULL
Basin
See Basin and Hydrolocation for algorithm details including the split-catchment workflow.
# Retrieve the upstream basin polygon (simplified by default)
basin <- get_nldi_basin(nldi_feature, simplify = TRUE)
basin
Simple feature collection with 1 feature and 0 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -89.60465 ymin: 43.03507 xmax: -89.20378 ymax: 43.36607
Geodetic CRS: WGS 84
# A tibble: 1 × 1
geometry
<POLYGON [°]>
1 ((-89.54456 43.06041, -89.5549 43.06299, -89.55518 43.06519, -89.5594 43.0695…
Choosing a Library
| Task | Recommended library |
|---|---|
| NLDI navigation + spatial analysis in Python | PyNHD (HyRiver) |
| Quick feature discovery + NWIS data retrieval in R | dataRetrieval |
| Granular NLDI control + network analysis in R | nhdplusTools |
For workflows combining spatial analysis with observational time series in R, dataRetrieval and nhdplusTools are often used together — dataRetrieval for discovering features and pulling discharge or water quality records, and nhdplusTools for network operations and catchment characteristics.
Notes & TODOs
- TODO: Add Python-only code examples for
navigate_byloc()— navigation starting from a coordinate rather than a known feature ID. - TODO: Add version pins or minimum version requirements once PyNHD API stability is confirmed for the Python NLDI endpoint.
- TODO: Confirm
feature_byloc()method name and signature in the current PyNHD release. - TODO: Cross-link from sibling pages (feature-sources.md, navigation.md, basin.md) back to this page once internal links are confirmed working.