Overview

The USGS National Hydrologic Geospatial Fabric (NHGF) exposes its vector geospatial layers through a pygeoapi server at https://api.water.usgs.gov/fabric/pygeoapi. The service provides the spatial backbone of the NHGF — stream networks, catchments, waterbodies, hydrologic unit boundaries, and reference gage locations — all queryable over standard HTTP.

It implements two complementary OGC API standards:

  • OGC API – Features — query and retrieve vector geospatial features (points, lines, polygons) as GeoJSON. This is the primary interface for data access.
  • OGC API – Tiles — access pre-rendered Mapbox Vector Tiles (MVT) for performant map display at multiple zoom levels.

If you are new to OGC API: it is a family of RESTful standards that replace older OGC services (WMS, WFS, WCS) with modern JSON/HTTP patterns. Every endpoint returns standard JSON by default and supports content negotiation via a ?f= parameter — more on that below .

This service replaces the legacy GeoServer WFS at https://api.water.usgs.gov/geoserver/wmadata/ows, which is being retired. See Migration from Legacy GeoServer for details.


Available Collections

The collections below are fetched directly from the live API at /collections .

Show collection-table code
library(httr2)
library(jsonlite)

resp <- request(paste0(FABRIC_BASE, "/collections?f=json")) |>
  req_perform()

collections_json <- resp_body_json(resp)

# Extract collection metadata into a data frame
collections <- do.call(rbind, lapply(collections_json$collections, function(col) {
  # Get keywords if available
  keywords <- if (!is.null(col$keywords)) paste(col$keywords, collapse = ", ") else ""

  data.frame(
    id = col$id %||% "",
    title = col$title %||% col$id,
    description = col$description %||% "",
    keywords = keywords,
    stringsAsFactors = FALSE
  )
}))

# Assign groups based on collection ID patterns
classify_group <- function(id) {
  if (grepl("^(nhd(flowline|area|waterbody)|catchmentsp)", id)) return("NHDPlusV2 Hydrography")
  if (grepl("^gagesii", id)) return("Gages-II Reference Gages")
  if (grepl("^nhdplusv2-huc", id)) return("NHDPlusV2 Hydrologic Units")
  if (grepl("^nhdplushr-huc", id)) return("NHDPlusHR Hydrologic Units")
  if (grepl("2020", id)) return("WBD 2020 Hydrologic Units")
  if (grepl("2025", id)) return("WBD 2025 Hydrologic Units")
  return("Other")
}

collections$group <- sapply(collections$id, classify_group)

# Define group order
group_order <- c(
  "NHDPlusV2 Hydrography",
  "Gages-II Reference Gages",
  "NHDPlusV2 Hydrologic Units",
  "NHDPlusHR Hydrologic Units",
  "WBD 2020 Hydrologic Units",
  "WBD 2025 Hydrologic Units",
  "Other"
)

collections$group <- factor(collections$group, levels = group_order)
collections <- collections[order(collections$group, collections$id), ]

# Build linked collection IDs
collections$Collection <- paste0(
  "[`", collections$id, "`](",
  FABRIC_BASE, "/collections/", collections$id, "?f=html)"
)

# Build all output as a single string to keep code-fold block intact
out <- character()

for (grp in levels(collections$group)) {
  subset_df <- collections[collections$group == grp, ]
  if (nrow(subset_df) == 0) next
  out <- c(out, paste0("\n### ", grp, "\n"))
  tbl <- knitr::kable(
    subset_df[, c("Collection", "title", "description")],
    col.names = c("Collection", "Title", "Description"),
    row.names = FALSE
  )
  out <- c(out, tbl, "")
}

out <- c(out, paste0("\n*Table generated: ", format(Sys.time(), "%Y-%m-%d"),
  " from `", FABRIC_BASE, "/collections`*\n"))

cat(paste(out, collapse = "\n"))

NHDPlusV2 Hydrography

Collection Title Description
catchmentsp NHDPlusV2 Catchmentsp Features Catchmentsp layer from NHDPlusV2 National Seamless Geodatabase
nhdarea NHDPlusV2 NHD Area Features National Hydrography Dataset (NHD) Area features from the NHDPlusV2
nhdflowline_network NHDPlusV2 NHD Flowline Network National Hydrography Dataset (NHD) Flowline Network from NHDPlusV2
nhdflowline_nonnetwork NHDPlusV2 NHD Flowline Nonnetwork Features National Hydrography Dataset (NHD) Flowline Nonnetwork from NHDPlusV2
nhdwaterbody NHDPlusV2 NHD Waterbody Features National Hydrography Dataset (NHD) Waterbody from NHDPlusV2

Gages-II Reference Gages

Collection Title Description
gagesii Gages-II Gages Geospatial Attributes of Gages for Evaluating Streamflow, Version II - https://doi.org/10.5066/P96CPHOT
gagesii-basins Gages-II Basins Features Basins for Geospatial Attributes of Gages for Evaluating Streamflow, version II - https://doi.org/10.5066/P96CPHOT

NHDPlusV2 Hydrologic Units

Collection Title Description
nhdplusv2-huc02 NHDPlusV2 HUC02 HUC02 created by aggregating NHDPlusV2 HUC12s
nhdplusv2-huc04 NHDPlusV2 HUC04 HUC04 created by aggregating NHDPlusV2 HUC12s
nhdplusv2-huc06 NHDPlusV2 HUC06 HUC06 created by aggregating NHDPlusV2 HUC12s
nhdplusv2-huc08 NHDPlusV2 HUC08 HUC08 created by aggregating NHDPlusV2 HUC12s
nhdplusv2-huc10 NHDPlusV2 HUC10 HUC10 created by aggregating NHDPlusV2 HUC12s
nhdplusv2-huc12 NHDPlusV2 HUC12 HUC12 layer from NHDPlusV2

NHDPlusHR Hydrologic Units

Collection Title Description
nhdplushr-huc02 NHDPlusHR HUC02 HUC02 created by aggregating NHDPlusHR HUC12s
nhdplushr-huc04 NHDPlusHR HUC04 HUC04 created by aggregating NHDPlusHR HUC12s
nhdplushr-huc06 NHDPlusHR HUC06 HUC06 created by aggregating NHDPlusHR HUC12s
nhdplushr-huc08 NHDPlusHR HUC08 HUC08 created by aggregating NHDPlusHR HUC12s
nhdplushr-huc10 NHDPlusHR HUC10 HUC10 created by aggregating NHDPlusHR HUC12s
nhdplushr-huc12 NHDPlusHR HUC12 HUC12 layer from NHDPlusHR

WBD 2020 Hydrologic Units

Collection Title Description
wbd02_20201026 2020 HUC02 2020 WBD Snapshot HUC02 Polygons
wbd04_20201026 2020 HUC04 2020 WBD Snapshot HUC04 Polygons
wbd06_20201026 2020 HUC06 2020 WBD Snapshot HUC06 Polygons
wbd08_20201026 2020 HUC08 2020 WBD Snapshot HUC08 Polygons
wbd10_20201026 2020 HUC10 2020 WBD Snapshot HUC10 Polygons
wbd12_20201026 2020 HUC12 2020 WBD Snapshot HUC12 Polygons

WBD 2025 Hydrologic Units

Collection Title Description
wbd02_20250107 2025 HUC02 2025 WBD Snapshot HUC02 Polygons
wbd04_20250107 2025 HUC04 2025 WBD Snapshot HUC04 Polygons
wbd06_20250107 2025 HUC06 2025 WBD Snapshot HUC06 Polygons
wbd08_20250107 2025 HUC08 2025 WBD Snapshot HUC08 Polygons
wbd10_20250107 2025 HUC10 2025 WBD Snapshot HUC10 Polygons
wbd12_20250107 2025 HUC12 2025 WBD Snapshot HUC12 Polygons

Table generated: 2026-04-03 from https://api.water.usgs.gov/fabric/pygeoapi/collections

Connecting to the NLDI: The comid attribute in the NHDPlusV2 hydrography collections is the same identifier used by the NLDI to index features to the hydrologic network. If the NLDI returns a comid, you can retrieve the corresponding geometry here — for example, /collections/nhdflowline_network/items?comid=13297246 or /collections/catchmentsp/items?comid=13297246. See Connecting Fabric Data to the NLDI for a walkthrough.


Querying Features

Response Headers and Pagination

Every API response includes HTTP headers that help you understand the result set and navigate pages. Here is a request for a single flowline by comid, showing the most useful headers:

Show request and response headers
resp <- request(paste0(
  FABRIC_BASE,
  "/collections/nhdflowline_network/items?comid=13297246&limit=1&f=json"
)) |>
  req_perform()

headers <- resp_headers(resp)

# Build all output as a single string to avoid fragmented code-fold blocks
out <- character()
out <- c(out, "Request URL:")
out <- c(out, paste0("  ", FABRIC_BASE,
    "/collections/nhdflowline_network/items?comid=13297246&limit=1&f=json"), "")

out <- c(out, "Selected response headers:")
useful <- c("content-type", "access-control-allow-origin",
            "content-encoding", "x-powered-by")
for (h in useful) {
  val <- headers[[h]]
  if (!is.null(val)) out <- c(out, sprintf("  %s: %s", h, val))
}

# Show pagination info from the JSON body
body <- resp_body_json(resp)
out <- c(out, "", "Pagination fields in JSON response:")
out <- c(out, sprintf("  numberMatched: %s", body$numberMatched %||% "not provided"))
out <- c(out, sprintf("  numberReturned: %s", body$numberReturned %||% "not provided"))

# Check for next link
links <- body$links
next_link <- Filter(function(l) identical(l$rel, "next"), links)
if (length(next_link) > 0) {
  out <- c(out, sprintf("  next: %s", next_link[[1]]$href))
} else {
  out <- c(out, "  next: (none — all results fit on this page)")
}

cat(paste(out, collapse = "\n"), "\n")
Request URL:
  https://api.water.usgs.gov/fabric/pygeoapi/collections/nhdflowline_network/items?comid=13297246&limit=1&f=json

Selected response headers:
  content-type: application/json
  content-encoding: gzip

Pagination fields in JSON response:
  numberMatched: 1
  numberReturned: 1
  next: https://api.water.usgs.gov:443/fabric/pygeoapi/collections/nhdflowline_network/items?offset=1&comid=13297246&limit=1 

The key pagination fields are in the JSON response body, not HTTP headers:

  • numberMatched — total features matching your query
  • numberReturned — features on this page
  • links — follow the rel: "next" link to get the next page

Use the limit parameter to control page size (default varies by collection).

Listing and Retrieving Items

Request features from any collection as a paginated GeoJSON FeatureCollection:

GET /collections/{collectionId}/items

To retrieve a single feature by its server-assigned ID:

GET /collections/{collectionId}/items/{featureId}

Filtering with Queryables

Each collection exposes filterable properties at its queryables endpoint. For example, see the flowline network queryables for the full list of available filters.

Queryable properties for nhdflowline_network (click to expand)
Property Type Title
geometry
objectid integer objectid
comid integer comid
fdate string fdate
resolution string resolution
gnis_id string gnis_id
gnis_name string gnis_name
lengthkm number lengthkm
reachcode string reachcode
flowdir string flowdir
wbareacomi integer wbareacomi
ftype string ftype
fcode integer fcode
shape_length number shape_length
streamleve number streamleve
streamorde number streamorde
streamcalc number streamcalc
fromnode number fromnode
tonode number tonode
hydroseq number hydroseq
levelpathi number levelpathi
pathlength number pathlength
terminalpa number terminalpa
arbolatesu number arbolatesu
divergence number divergence
startflag number startflag
terminalfl number terminalfl
dnlevel number dnlevel
uplevelpat number uplevelpat
uphydroseq number uphydroseq
dnlevelpat number dnlevelpat
dnminorhyd number dnminorhyd
dndraincou number dndraincou
dnhydroseq number dnhydroseq
frommeas number frommeas
tomeas number tomeas
rtndiv number rtndiv
vpuin number vpuin
vpuout number vpuout
areasqkm number areasqkm
totdasqkm number totdasqkm
divdasqkm number divdasqkm
tidal number tidal
totma number totma
wbareatype string wbareatype
pathtimema number pathtimema
hwnodesqkm number hwnodesqkm
maxelevraw number maxelevraw
minelevraw number minelevraw
maxelevsmo number maxelevsmo
minelevsmo number minelevsmo
slope number slope
elevfixed string elevfixed
hwtype string hwtype
slopelenkm number slopelenkm
qa_ma number qa_ma
va_ma number va_ma
qc_ma number qc_ma
vc_ma number vc_ma
qe_ma number qe_ma
ve_ma number ve_ma
qa_01 number qa_01
va_01 number va_01
qc_01 number qc_01
vc_01 number vc_01
qe_01 number qe_01
ve_01 number ve_01
qa_02 number qa_02
va_02 number va_02
qc_02 number qc_02
vc_02 number vc_02
qe_02 number qe_02
ve_02 number ve_02
qa_03 number qa_03
va_03 number va_03
qc_03 number qc_03
vc_03 number vc_03
qe_03 number qe_03
ve_03 number ve_03
qa_04 number qa_04
va_04 number va_04
qc_04 number qc_04
vc_04 number vc_04
qe_04 number qe_04
ve_04 number ve_04
qa_05 number qa_05
va_05 number va_05
qc_05 number qc_05
vc_05 number vc_05
qe_05 number qe_05
ve_05 number ve_05
qa_06 number qa_06
va_06 number va_06
qc_06 number qc_06
vc_06 number vc_06
qe_06 number qe_06
ve_06 number ve_06
qa_07 number qa_07
va_07 number va_07
qc_07 number qc_07
vc_07 number vc_07
qe_07 number qe_07
ve_07 number ve_07
qa_08 number qa_08
va_08 number va_08
qc_08 number qc_08
vc_08 number vc_08
qe_08 number qe_08
ve_08 number ve_08
qa_09 number qa_09
va_09 number va_09
qc_09 number qc_09
vc_09 number vc_09
qe_09 number qe_09
ve_09 number ve_09
qa_10 number qa_10
va_10 number va_10
qc_10 number qc_10
vc_10 number vc_10
qe_10 number qe_10
ve_10 number ve_10
qa_11 number qa_11
va_11 number va_11
qc_11 number qc_11
vc_11 number vc_11
qe_11 number qe_11
ve_11 number ve_11
qa_12 number qa_12
va_12 number va_12
qc_12 number qc_12
vc_12 number vc_12
qe_12 number qe_12
ve_12 number ve_12
lakefract number lakefract
surfarea number surfarea
rareahload number rareahload
rpuid string rpuid
vpuid string vpuid
enabled integer enabled

Filter by appending query parameters:

/collections/nhdflowline_network/items?comid=13297246
/collections/nhdflowline_network/items?gnis_name=Connecticut%20River
/collections/nhdplusv2-huc08/items?huc8=01080205

Bounding Box Queries

Use the bbox parameter to retrieve features within a geographic extent (min longitude, min latitude, max longitude, max latitude):

# Retrieve flowlines in a bounding box around Hartford, CT
resp <- request(paste0(
  FABRIC_BASE,
  "/collections/nhdflowline_network/items",
  "?bbox=-72.75,41.7,-72.6,41.8&limit=5&f=json"
)) |>
  req_perform()

body <- resp_body_json(resp)
out <- character()
out <- c(out, sprintf("numberMatched: %s", body$numberMatched))
out <- c(out, sprintf("numberReturned: %s (limit=5)", body$numberReturned))

# Show the first few feature IDs and names
for (feat in body$features[1:min(3, length(body$features))]) {
  out <- c(out, sprintf("  comid: %s  gnis_name: %s",
    feat$properties$comid %||% "—",
    feat$properties$gnis_name %||% "(unnamed)"))
}
cat(paste(out, collapse = "\n"), "\n")
numberMatched: 56
numberReturned: 5 (limit=5)
  comid: 7700130  gnis_name: Burnham Brook
  comid: 7700132  gnis_name:  
  comid: 7700136  gnis_name: Burnham Brook 

Coordinate Reference Systems

The service supports CRS negotiation per OGC API – Features Part 2 . The default storage CRS is NAD83. Use the crs parameter to request output in a different coordinate reference system. Supported CRS options are listed in each collection’s metadata.


Vector Tiles

Collections also expose Mapbox Vector Tile (MVT) tilesets for use in web mapping libraries such as MapLibre GL JS, Mapbox GL JS, or OpenLayers.

Tile URL pattern:

/collections/{collectionId}/tiles/{tileMatrixSetId}/{z}/{y}/{x}

Tileset metadata (available matrix sets and zoom levels) is at:

/collections/{collectionId}/tiles

Use vector tiles when you need to display features on an interactive map without downloading full GeoJSON datasets. Note that tiles may not include all attributes available through the Features interface — use Features queries when you need the complete attribute set.


Client Libraries

Python — requests

For Python, query the Fabric OGC API directly with requests. This teaches the standard OGC API – Features pattern that works with any OGC-compliant server.

Query features as GeoJSON

import requests
import geopandas as gpd

base = "https://api.water.usgs.gov/fabric/pygeoapi"

# Get a flowline by comid
resp = requests.get(
    f"{base}/collections/nhdflowline_network/items",
    params={"comid": 13297246, "f": "json", "limit": 1}
)
data = resp.json()

# Convert to GeoDataFrame
gdf = gpd.GeoDataFrame.from_features(data["features"], crs="EPSG:4269")
print(f"Columns: {list(gdf.columns[:6])} ...")
Columns: ['geometry', 'objectid', 'comid', 'fdate', 'resolution', 'gnis_id'] ...
gdf[["comid", "gnis_name", "lengthkm"]].head()
      comid gnis_name  lengthkm
0  13297246               0.108

Bounding box query

# Get flowlines in a bounding box around Hartford, CT
resp = requests.get(
    f"{base}/collections/nhdflowline_network/items",
    params={
        "bbox": "-72.75,41.7,-72.6,41.8",
        "limit": 5,
        "f": "json",
    }
)
data = resp.json()
print(f"numberMatched: {data['numberMatched']}")
numberMatched: 56
print(f"numberReturned: {data['numberReturned']}")
numberReturned: 5
gdf = gpd.GeoDataFrame.from_features(data["features"], crs="EPSG:4269")
gdf[["comid", "gnis_name", "lengthkm"]].head()
     comid      gnis_name  lengthkm
0  7700130  Burnham Brook     2.688
1  7700132                    1.291
2  7700136  Burnham Brook     2.671
3  7700140                    2.575
4  7700144                    0.138

Paginating through results

# Follow the "next" link to paginate
resp = requests.get(
    f"{base}/collections/nhdflowline_network/items",
    params={"bbox": "-72.75,41.7,-72.6,41.8", "limit": 2, "f": "json"}
)
data = resp.json()

print(f"Page 1: {data['numberReturned']} of {data['numberMatched']} features")
Page 1: 2 of 56 features
# Find the "next" link
next_links = [l for l in data.get("links", []) if l.get("rel") == "next"]
if next_links:
    print(f"Next page URL: {next_links[0]['href'][:80]}...")
    # Follow it:
    resp2 = requests.get(next_links[0]["href"])
    data2 = resp2.json()
    print(f"Page 2: {data2['numberReturned']} features")
else:
    print("No next page — all results fit on one page")
Next page URL: https://api.water.usgs.gov:443/fabric/pygeoapi/collections/nhdflowline_network/i...
Page 2: 2 features

Discovering collections

# List all collections and their types
resp = requests.get(f"{base}/collections", params={"f": "json"})
collections = resp.json()["collections"]

print(f"Total collections: {len(collections)}")
Total collections: 31
for c in collections[:5]:
    print(f"  {c['id']}: {c.get('title', c['id'])}")
  catchmentsp: NHDPlusV2 Catchmentsp Features
  nhdarea: NHDPlusV2 NHD Area Features
  nhdflowline_network: NHDPlusV2 NHD Flowline Network
  nhdflowline_nonnetwork: NHDPlusV2 NHD Flowline Nonnetwork Features
  nhdwaterbody: NHDPlusV2 NHD Waterbody Features
print("  ...")
  ...

NLDI → Fabric (Python)

Use PyNHD for NLDI navigation, then query Fabric directly with requests:

from pynhd import NLDI

nldi = NLDI()

# Step 1: Navigate the NLDI — find upstream flowlines
flowlines = nldi.navigate_byid(
    fsource="nwissite",
    fid="USGS-05428500",
    navigation="upstreamTributaries",
    source="flowlines",
    distance=10,
)
comids = flowlines["nhdplus_comid"].tolist()
print(f"Found {len(comids)} upstream flowlines")
Found 10 upstream flowlines
print(f"First few comids: {comids[:5]}")
First few comids: ['13293750', '13294312', '13294308', '13294310', '13293634']
# Step 2: Query Fabric for a catchment by comid
comid = comids[0]
resp = requests.get(
    f"{base}/collections/catchmentsp/items",
    params={"comid": comid, "f": "json", "limit": 1}
)
data = resp.json()
print(f"\nCatchment for comid {comid}:")
Catchment for comid 13293750:
print(f"  numberMatched: {data.get('numberMatched')}")
  numberMatched: 2647455
if data.get("features"):
    props = data["features"][0]["properties"]
    print(f"  areasqkm: {props.get('areasqkm')}")
  areasqkm: 2.310929

R — nhdplusTools

nhdplusTools provides functions that query the Fabric pygeoapi service directly. Output is always an sf data frame.

nhdplusTools function Fabric collection(s)
get_nhdplus(realization="flowline") nhdflowline_network
get_nhdplus(realization="catchment") catchmentsp
get_nhdplus(realization="outlet") nhdflowline_network (outlet points)
get_waterbodies() nhdwaterbody
get_nhdarea() nhdarea
get_huc() nhdplusv2-huc*, nhdplushr-huc*
get_gagesII() gagesii, gagesii-basins

Query by comid

library(nhdplusTools)

# Get a specific flowline by comid
flowline <- get_nhdplus(comid = 13297246)
cat("Columns:", paste(names(flowline)[1:8], collapse = ", "), "...\n\n")
Columns: objectid, comid, fdate, resolution, gnis_id, gnis_name, lengthkm, reachcode ...
print(sf::st_drop_geometry(flowline)[, 1:6])
# A tibble: 1 × 6
  objectid    comid fdate               resolution gnis_id gnis_name
     <int>    <int> <dttm>              <chr>      <chr>   <chr>    
1   968679 13297246 2009-04-30 23:00:00 Medium     " "     " "      

Query by bounding box

library(sf)

# Create a bounding box around Hartford, CT
bbox <- st_bbox(c(xmin = -72.75, ymin = 41.7,
                   xmax = -72.6,  ymax = 41.8),
                crs = 4326)
aoi <- st_as_sfc(bbox)

# Get flowlines in the AOI
flowlines <- get_nhdplus(AOI = aoi)
cat(sprintf("Retrieved %d flowlines in AOI\n\n", nrow(flowlines)))
Retrieved 56 flowlines in AOI
print(head(sf::st_drop_geometry(flowlines)[, c("comid", "gnis_name", "lengthkm")]))
# A tibble: 6 × 3
    comid gnis_name        lengthkm
    <int> <chr>               <dbl>
1 7700130 "Burnham Brook"     2.69 
2 7700132 " "                 1.29 
3 7700136 "Burnham Brook"     2.67 
4 7700140 " "                 2.58 
5 7700144 " "                 0.138
6 7700146 "Hockanum River"    0.222

Hydrologic units

# Get a HUC8 boundary by ID
huc8 <- get_huc(id = "01080205", type = "huc08")
cat(sprintf("HUC8 %s: %s\n  Area: %s sq km\n",
    huc8$huc8, huc8$name,
    round(as.numeric(sf::st_area(huc8)) / 1e6)))
HUC8 01080205: Outlet Connecticut River
  Area: 2805 sq km

Gages-II

# Get GAGES-II gages by ID
gages <- get_gagesII(id = "01011000")
sf::st_drop_geometry(gages)[, c("staid", "staname", "drain_sqkm", "huc02")]
# A tibble: 1 × 4
  staid    staname                             drain_sqkm huc02
  <chr>    <chr>                                    <dbl> <chr>
1 01011000 Allagash River near Allagash, Maine      3187. 01   

Connecting Fabric Data to the NLDI

The NLDI uses NHDPlusV2 comid values as its spatial backbone. Every feature in the NLDI is indexed to a catchment and its associated flowline via comid. This means you can move between the two services:

  1. NLDI → Fabric: Use the NLDI to navigate the network (e.g., find all flowlines upstream of a gage), then query Fabric for the corresponding catchment or waterbody geometries using the comid values from the NLDI response. See the Python and R examples in the Client Libraries section above.

  2. Fabric → NLDI: Start with a spatial query in Fabric (e.g., flowlines in a bounding box), then use the returned comid values to look up linked data sources in the NLDI (gages, water quality sites, etc.) via /linked-data/comid/{comid}.

# Get a flowline from Fabric by comid
flowline <- get_nhdplus(comid = 13297246)
cat("Flowline from Fabric:\n")
Flowline from Fabric:
print(sf::st_drop_geometry(flowline)[, c("comid", "gnis_name", "lengthkm", "totdasqkm")])
# A tibble: 1 × 4
     comid gnis_name lengthkm totdasqkm
     <int> <chr>        <dbl>     <dbl>
1 13297246 " "          0.108     1305.
# Use this comid to look up the NLDI feature
nldi_comid <- list(featureSource = "comid", featureID = "13297246")
feature <- get_nldi_feature(nldi_comid)
cat("\nNLDI feature for same comid:\n")
NLDI feature for same comid:
print(sf::st_drop_geometry(feature))
# A tibble: 1 × 3
  sourceName    identifier comid   
* <chr>         <chr>      <chr>   
1 NHDPlus comid 13297246   13297246

Using the Built-In Developer Tools

The HTML views that pygeoapi generates serve as browser-based API introspection tools for developers during integration and testing, not as a general-purpose user interface. They render the same data the JSON API returns, formatted for human reading.

Every endpoint supports a ?f= parameter for content negotiation:

  • ?f=json — GeoJSON (default for programmatic access)
  • ?f=jsonld — JSON-LD (linked data format)
  • ?f=html — human-readable HTML view (auto-generated by pygeoapi)

Useful developer entry points:


Key Endpoints

Path Purpose
/ Landing page (service metadata)
/collections All available feature collections
/collections/{id} Metadata for a single collection
/collections/{id}/items Query features (GeoJSON)
/collections/{id}/items/{featureId} Single feature by ID
/collections/{id}/queryables Filterable properties for a collection
/collections/{id}/tiles Available vector tile sets
/conformance Supported OGC standards
/openapi OpenAPI specification (Swagger / ReDoc)

All paths are relative to https://api.water.usgs.gov/fabric/pygeoapi.


Migration from Legacy GeoServer

The legacy GeoServer WFS at https://api.water.usgs.gov/geoserver/wmadata/ows served the same core data as roughly 15 WFS layers (NHDPlusV2 hydrography, gagesii, and WBD layers with date-stamped names like wbd02_20201006). That service is being retired.

Key differences in the Fabric pygeoapi replacement:

  • RESTful JSON instead of XML-based WFS GetFeature requests
  • Stable collection IDs without date stamps (e.g., nhdplusv2-huc08 instead of wbd08_20201006)
  • Vector tile support for web mapping use cases
  • Queryables-based filtering instead of CQL/OGC filter encoding
  • NHDPlusHR hydrologic units added (not available in the legacy service)