TL;DR
The USGS Water Services API delivers real-time and historical water data from over 1.5 million monitoring sites across the United States. Access streamflow/discharge rates, groundwater levels, surface water stage (height), water temperature, specific conductance, dissolved oxygen, pH, turbidity, and precipitation. Query by site number, state, county, or geographic bounding box. Data goes back decades for many sites. The authoritative source for US water information — used for flood forecasting, drought monitoring, water resource management, and environmental research.
Quick start: https://waterservices.usgs.gov/nwis/iv/?site=03339000&format=json
No API key needed — just make a request!
https://waterservices.usgs.gov/nwis/iv/?site=03339000&format=json
How to Use This API
1. Real-Time Data for a Site
https://waterservices.usgs.gov/nwis/iv/?site=03339000&format=json
2. Sites by State (Recent Data)
https://waterservices.usgs.gov/nwis/iv/?stateCd=ca&format=json
3. Historical Daily Data
https://waterservices.usgs.gov/nwis/dv/?site=03339000&format=json&startDt=2025-01-01&endDt=2025-12-31
4. Site Search by County
https://waterservices.usgs.gov/nwis/site/?stateCd=ny&countyCd=081&format=json
5. JavaScript — River Level Check
async function riverLevel(siteId) {
const resp = await fetch(
`https://waterservices.usgs.gov/nwis/iv/?site=${siteId}&format=json`
);
const data = await resp.json();
const ts = data.value.timeSeries[0];
const name = ts.sourceInfo.siteName;
const value = ts.values[0].value[0].value;
const unit = ts.variable.unit.unitCode;
const time = ts.values[0].value[0].dateTime;
console.log(`Site: ${name}`);
console.log(`Value: ${value} ${unit}`);
console.log(`Time: ${time}`);
}
riverLevel('03339000'); // Vermilion River near Danville, IL
6. Python — Flood Monitoring
import requests
def check_flood_sites(state='tx'):
resp = requests.get(
'https://waterservices.usgs.gov/nwis/iv/',
params={
'stateCd': state,
'format': 'json',
'parameterCd': '00065' # Gage height
}
)
data = resp.json()
print(f'Sites with gage height data in {state.upper()}:')
for ts in data.get('value', {}).get('timeSeries', [])[:10]:
site = ts['sourceInfo']['siteName']
val = ts['values'][0]['value'][0]
height = val['value']
time = val['dateTime'][:16]
print(f' {site}: {height} ft at {time}')
check_flood_sites('la')
Frequently Asked Questions
- What parameters are measured?
- Streamflow (discharge), gage height (stage), groundwater levels, water temperature, specific conductance, dissolved oxygen, pH, turbidity, and precipitation. Each parameter has a 5-digit code.
- Do I need an API key?
- No. USGS data is public domain — no authentication required.
- How do I find site IDs?
- Search by state using
stateCdor use the USGS National Water Information System (NWIS) mapper to find monitoring sites by location. - What's the difference between IV and DV?
- IV (Instantaneous Values) — real-time data typically recorded every 15 minutes. DV (Daily Values) — daily averages calculated from instantaneous readings.
- How far back does historical data go?
- Many sites have data going back to the early 1900s. Use
startDtandendDtparameters in YYYY-MM-DD format. - What area is covered?
- The entire United States including Alaska, Hawaii, and US territories. Over 1.5 million sites monitored by USGS in cooperation with state and local agencies.
API Details
- API URL
https://waterservices.usgs.gov/nwis/- Documentation
- waterservices.usgs.gov
- Category
- Government
- Authentication
- Not Required
- Geographic Coverage
- United States and territories
What You Can Build
- Flood early warning dashboard using real-time gage height data
- Fishing app showing river flow conditions for trip planning
- Drought monitoring tool tracking groundwater levels over time
- Whitewater rafting guide with streamflow by river section
- Water resource management application for agricultural planning