EPA UCMR 5 PFAS and lithium results monitor avatar

EPA UCMR 5 PFAS and lithium results monitor

Pricing

$1.00 / 1,000 results

Go to Apify Store
EPA UCMR 5 PFAS and lithium results monitor

EPA UCMR 5 PFAS and lithium results monitor

Monitor EPA UCMR 5 drinking water sample results for PFAS and lithium. Filter by state, water system, contaminant, concentration, and collection date, and detect new or changed results.

Pricing

$1.00 / 1,000 results

Rating

0.0

(0)

Developer

Chee Chiaw Lim

Chee Chiaw Lim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Collect analytical results from the US EPA UCMR 5 occurrence dataset. Each item represents one contaminant result from one public water system sample. Filters select states, water systems, contaminants, detected results, concentrations, and collection dates.

The actor downloads the compressed archive to a temporary file and streams its tab-separated entries. It does not load the uncompressed results file into memory. Latin-1 decoding preserves the source units, µg/L. Water system ZIP codes come from UCMR5_ZIPCodes.txt when available.

Input

An empty input returns up to 100 detected results across all states and contaminants.

FieldDefaultMeaning
states[]Two-letter postal codes, such as ["CA", "NJ"]. Empty means all states.
pwsIds[]Exact public water system IDs. Empty means all systems.
contaminants[]Names such as ["PFOA", "PFOS"]. Empty includes PFAS and lithium.
detectsOnlytrueKeep results with EPA's = detection sign. Set false to include < non-detects.
minValueomittedMinimum concentration in source units, µg/L.
collectedAfteromittedCollection date after an ISO date, such as 2024-01-01.
onlyNewfalseSet true to emit only new and changed results.
maxItems100Maximum emitted results, from 1 to 10000.
stateStoreNameucmr5-pfas-results-monitor-stateNamed key-value store for result history.

Filters combine across categories. maxItems limits emitted results, not rows scanned. A narrow filter or a run with onlyNew=true may scan the full file.

Output

This example uses a detected PFOA result from the supplied EPA sample, joined to its service area ZIP code.

{
"pwsId": "010106001",
"pwsName": "Mashantucket Pequot Water System",
"systemSize": "L",
"facilityId": "00006",
"facilityName": "MPTN WTP",
"facilityWaterType": "GU",
"samplePointId": "TP1",
"samplePointName": "Entry point to Dist. System",
"samplePointType": "EP",
"collectionDate": "2023-09-27",
"sampleId": "810-79458-1",
"contaminant": "PFOA",
"detected": true,
"resultValue": 0.0074,
"units": "µg/L",
"mrl": 0.004,
"methodId": "EPA 533",
"sampleEventCode": "SE1",
"monitoringRequirement": "AM",
"epaRegion": 1,
"state": null,
"stateCode": "01",
"exceedsMrl": true,
"pfasMcl": 4,
"aboveMcl": true,
"zipCodes": ["06338"],
"source": "US EPA UCMR 5 occurrence data (https://www.epa.gov/system/files/other-files/2023-08/ucmr5-occurrence-data.zip)",
"licence": "US Government work (17 U.S.C. 105)",
"retrievedAt": "2026-10-22T00:00:00.000Z",
"changeType": "new",
"generatedId": "810-79458-1:PFOA:TP1:010106001"
}

resultValue is null when the source has no numeric result. A non-detect is not zero. mrl is the source minimum reporting level in µg/L. exceedsMrl is true only when a detected value is strictly greater than that reporting level. ZIP codes are strings so leading zeros survive.

The source State column contains postal abbreviations and numeric tribal region codes. The EPA data dictionary identifies numeric values as tribal EPA regions. Numeric tribal codes do not identify a single postal state. They must not be treated as FIPS state codes. The actor uses a postal prefix from PWSID when available. Unresolved states are null. stateCode preserves the original source code.

pfasMcl contains fixed EPA 2024 comparison values in parts per trillion, or null for other contaminants.

ContaminantpfasMcl, pptEquivalent, µg/L
PFOA40.004
PFOS40.004
PFHxS100.010
PFNA100.010
HFPO-DA100.010

aboveMcl is true only when a detected individual sample result is strictly greater than this fixed table value after unit conversion. It is null when no comparison applies. The table is a historical screening reference, not a statement of current regulations. Individual sample comparisons do not determine regulatory compliance, which requires the applicable averaging and monitoring rules. The actor does not calculate a mixture hazard index.

Change detection

generatedId is sampleId:contaminant:samplePointId:pwsId. The actor compares a hash of the result's value fields with the last saved hash for that ID. Retrieval timestamps and change labels do not cause changes. changeType is new, changed, or unchanged.

State saves follow successful dataset pushes. onlyNew=true skips unchanged results. Use separate state store names for independent histories. A crash between a dataset push and state save can repeat an item on the next run.

EPA has published quarterly updates. Its occurrence data page describes the August 2026 release as the final UCMR 5 dataset. Future revisions depend on EPA. The actor detects changes only among rows it visits. A capped run can repeatedly return the first matching rows when onlyNew=false. With onlyNew=true, later runs skip saved results and can reach later rows. The actor does not report deletions or provide a complete archive of prior publications.

RUN_SUMMARY in the default key-value store records the run counts and any error. The output schema links to this summary and the dataset.

Pricing

The actor uses pay per result with the event name result. There is no run fee. Every emitted item counts as a result, including unchanged items when onlyNew=false. Check the actor's pricing page for the configured price.

Source credit and licence

Source: US Environmental Protection Agency, UCMR 5 occurrence data, download archive. Source and licence text from TERMS.md:

EPA-produced data is a US Government work (17 U.S.C. 105). https://www.epa.gov/web-policies-and-procedures/epa-disclaimers notes EPA data "is by default in the public domain" (stated for geospatial data) and that third-party copyrighted items need permission; the "non-commercial" sentence there covers documents, not EPA data. Data has no personal data (public water systems).

No EPA endorsement is implied. The data dictionary PDF is not redistributed. Every item carries the dataset name and URL, licence, and retrieval time. The actor normalizes dates and states, converts numeric fields, adds ZIP codes, and calculates comparison and change fields.

Personal data and limitations

The actor collects public water system and facility sample data. It does not collect personal contact details or household addresses. Water system ZIP codes describe service areas, not individual sample addresses.

EPA can revise results and publication timing. This actor is not a real-time drinking water alert service. Source codes such as system size, water type, and monitoring requirement remain EPA codes. Non-detects and missing values limit concentration comparisons. Dataset order is source order, not newest collection date or highest concentration.

Run locally

Use Node.js 20 or later.

npm install
npm test
npm start

Local runs contact EPA. Tests use node:test, stub network requests, and use trimmed sample fixtures under test/fixtures. Read dataset items under storage/datasets/default and the summary at storage/key_value_stores/default/RUN_SUMMARY.json.