US River Water Level API - Official USGS Streamflow Gauges avatar

US River Water Level API - Official USGS Streamflow Gauges

Pricing

$10.00 / 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

Live river water level, streamflow and water temperature from official USGS gauges - no API key. Every reading carries its USGS quality codes in plain English, so you can tell an approved measurement from a provisional one, a frozen gauge or a dry channel. -999999 is never returned as a level.

Pricing

$10.00 / 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

8 hours ago

Last modified

Share

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.

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.

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.