US River Water Level API - Official USGS Streamflow Gauges avatar

US River Water Level API - Official USGS Streamflow Gauges

Pricing

from $7.40 / 1,000 gauge reading returneds

Go to Apify Store
US River Water Level API - Official USGS Streamflow Gauges

US River Water Level API - Official USGS Streamflow Gauges

For flood risk models, water utilities, insurance and paddling apps: river level, streamflow and water temperature from official USGS gauges, with how old each reading is and whether the sensor worked. Over 31,752 time series on 2026-08-30, 2.64% read -999999 and 26.6% were over a year old.

Pricing

from $7.40 / 1,000 gauge reading returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

For flood and drought monitoring, hydropower and water utilities, agriculture, paddling and fishing apps, and insurance and engineering models: live river level, streamflow and water temperature from the government's own gauges — with the three facts you need to know whether a number is usable: how old it is, whether the sensor was working, and whether it will be revised.

Four traps, each of which turns into a wrong number in your system without anything looking broken. All four measured on live data across 55 US states and territories, 31,752 time series, on 2026-08-30.

1. -999999 is the missing marker and it appeared in 2.64% of readings — a naive client reports a river at minus 999,999 feet. Filtering for that one value is not enough either: real responses also contain -100000 and a water temperature of -120 °C. Every measurement is checked against a physical range. But large negative streamflow is real — it is tidal backflow, and the Savannah River at Fort Pulaski runs to -218,000 ft³/s — so a client that simply discards big negative numbers destroys real data. The range is set to keep it.

2. 26.6% of live readings across the country are more than a year old, returned with no warning. The oldest gauge in the Arizona sample was last read 13,847 days ago and still comes back in a normal request. Every row says how old it is.

3. USGS quality code A means "approved for publication", and it is tempting to treat that as "trustworthy". In the instantaneous-value service, approval only happens after review — so the flag is returned as what it is, not translated into confidence.

4. USGS returns a separate block per measurement method (Primary, Secondary, Bubbler, Radar, Upper Stage Sensor). Measured nationwide, 720 series carry more than one block and 612 of them disagree on the value — so which block a row came from is part of the row.

And a bad input fails loudly. If none of the site numbers or state codes you gave are usable, the run fails and says so. It does not quietly fall back to the default gauges and charge you for rivers you did not ask about.

This reads USGS Water Services (waterservices.usgs.gov), the official public API of the US Geological Survey. It is a work of the US government: public domain, no API key, no rate-limit contract, no terms that forbid redistribution. Nothing here parses a website. No proxies required. Export as JSON, CSV or Excel.

Why not just call the API yourself

Four traps. Each one turns into a wrong number in your system without anything looking broken. All four were measured on live data across 55 US states and territories, 31,752 time series on 2026-08-30.

1. -999999 is the missing marker - and it is not the only bad number

-999999 appeared in 2.64% of readings. A naive client reports a river at minus 999,999 feet.

But filtering only for that is not enough: real responses also contain values like -100000 and a water temperature of -120 °C. This Actor checks each measurement against a physical range as well, so waterTemperature outside roughly -3 to 70 °C is reported as missing rather than as a reading.

Careful: large negative streamflow is real - it is tidal backflow (Savannah River at Fort Pulaski runs to -218,000 ft³/s). A client that simply discards big negative numbers destroys real data. The range is set per measurement, not per sign.

2. Freshness is a separate question from quality - and it bites hard here

26.6% of live readings across the country are more than a year old. The service returns them with no warning. The oldest gauge in the Arizona sample was last read 13,847 days ago and still comes back in a request for current conditions.

Every measurement therefore carries ...AgeHours, and every row carries freshestAgeHours. If you are monitoring for flooding, filter on those.

A warning worth spelling out. USGS quality code A means "approved for publication". It is tempting to treat A as "trustworthy". Do not. In the instantaneous-value service, approval only happens after review, so A is attached to historical records: of 2,207 A readings measured, 100% were more than 24 hours old and the oldest was 45 years old. Almost every current reading is P (provisional). Filtering for "approved" data leaves you with no current data at all. This Actor therefore does not publish a single "trusted" flag - it gives you age, suspect and provisional separately, and lets you decide.

3. Quality codes decide whether the number means anything

A gauge can be iced over, dry, under maintenance, or broken. ...IsSuspect is true when any code says the measurement itself was affected, and ...QualifierMeanings spells out why in English.

CodeMeaningSuspect
A Approved for publication(see the warning above - approved usually means old)no
P Provisional - subject to revisionthe normal state of current datano
R Revised recordno
Dry The channel is dry at this siteno
ZFL Zero flowno
e Estimatedyes
Ice Value affected by ice at the siteyes
Eqp Value affected by equipment malfunctionyes
Mnt Site under maintenanceyes
Fld Value affected by flood damageyes
Bkw Value affected by backwateryes
Rat Rating being developed or revisedyes
Ssn Monitored seasonally - not measured nowyes
Dis Record discontinued at this siteyes
*** Temporarily unavailableyes
< Actual value is less than the value shownyes

Any code not in this list is reported as Unknown USGS qualifier '<code>' and treated as suspect, so a new code can never quietly pass as a clean reading.

4. One gauge can have several sensors, and the API does not put the good one first

USGS returns a separate block per measurement method - Primary, Secondary, Bubbler, Radar, Upper Stage Sensor. Measured nationwide: 720 series carry more than one block, 612 of them disagree on the value, and in 11 the first block is missing while another sensor has a real reading. One gauge reported no water level at all while its radar sensor was reading 11.11 ft.

This Actor picks the freshest block that actually has a reading, and tells you which one it used in ...Sensor.

What you get

One row per gauge site, with the same columns every time - a site that does not measure something gets null, never a zero.

FieldExampleNotes
siteCode / siteName09379025 / CHINLE CREEK AT CHINLE, AZAs USGS names it
latitude / longitude36.155 / -109.5375
stateFips / countyFips04 / 04001FIPS numbers, not AZ - named for what they actually are
timeZoneMST
streamflow / gageHeight / waterTemperature + ...Unit0 / 2.2 / nullft³/s, ft, °C
...AgeHours1.6How old this measurement is, in hours
...ObservedAt2026-08-30T03:00:00.000-07:00With offset
...IsMissingfalse-999999 or physically impossible
...IsSuspectfalseThe measurement itself was affected
...IsProvisionaltrueWill be revised later
...Qualifiers / ...QualifierMeaningsP / Provisional - subject to revisionRaw codes and plain English
...SensorRadarWhich sensor block was used, when the gauge has several
freshestAgeHours1.6Age of the newest measurement on this row
parametersObserved / parametersTotal2 / 3How much this gauge actually reported
sourceUSGS Water Services NWIS (official, public domain)

A real row

{
"siteCode": "09379025",
"siteName": "CHINLE CREEK AT CHINLE, AZ",
"latitude": 36.155,
"longitude": -109.5375,
"stateFips": "04",
"timeZone": "MST",
"streamflow": 0,
"streamflowUnit": "ft3/s",
"streamflowObservedAt": "2026-08-30T03:00:00.000-07:00",
"streamflowAgeHours": 1.6,
"streamflowIsMissing": false,
"streamflowQualifiers": "P",
"streamflowQualifierMeanings": "Provisional - subject to revision",
"streamflowIsProvisional": true,
"streamflowIsSuspect": false,
"gageHeight": 2.2,
"gageHeightUnit": "ft",
"gageHeightAgeHours": 1.6,
"freshestAgeHours": 1.6,
"parametersObserved": 2,
"parametersTotal": 3,
"source": "USGS Water Services NWIS (official, public domain)"
}

Input

{
"sites": ["01646500", "01463500", "07010000", "05331000", "06934500",
"03294500", "02358000", "08279500", "14105700", "12510500"],
"states": [],
"parameterCodes": ["00060", "00065", "00010"],
"maxRetries": 4
}
  • sites - USGS gauge site numbers, 8 to 15 digits including the leading zero. Find them at https://waterdata.usgs.gov/nwis/rt. Defaults to ten major US river gauges.
  • states - two letter state codes such as vt, tx. Returns every active gauge in those states, which can be several hundred rows per state. Takes priority over sites.
  • parameterCodes - 00060 streamflow, 00065 gage height, 00010 water temperature. Anything else is ignored so the columns stay identical on every row.
  • maxRetries - attempts when USGS returns a server error.

What it does when something is wrong

It tells you, instead of returning a clean-looking empty result.

  • If none of the site numbers or state codes you gave are usable, the run fails and says so. It does not quietly fall back to the default gauges and charge you for rivers you did not ask about. (1646500 with the leading zero dropped is a realistic typo, and it is rejected rather than substituted.)
  • A 4xx from USGS is reported as a rejected request, not as an outage, and is not retried - retrying a bad site number just wastes your time.
  • USGS Water Services returns HTTP 503 often (2 of the first 3 calls on the morning this was built). That is retried, and if it still fails the run fails with the reason in RUN_ISSUES rather than delivering an empty dataset.
  • A response whose shape is not what USGS documents throws instead of returning zero rows.
  • If you set a maximum total charge and the run hits it, the run stops and says the result is incomplete.

Pricing

Pay per result: one charge per gauge site row delivered. Failed runs deliver nothing and charge nothing.

Source and licence

All data comes from the US Geological Survey Water Services (waterservices.usgs.gov), a work of the US federal government and therefore in the public domain. This Actor adds the flattening, the missing-value and range handling, the sensor selection, the freshness figures and the quality-code translation described above.