# US NOAA Tide Times Scraper (Predictions & Water Levels) (`steadfetch/us-tide-times-extractor`) Actor

Fetches NOAA tide predictions (high/low tides) and water-level data for US coastal stations. Returns one normalized row per tidal event with station info, timestamps (UTC), values in meters and source URLs. For surf and fishing apps, coastal monitoring and tourism planning.

- **URL**: https://apify.com/steadfetch/us-tide-times-extractor.md
- **Developed by:** [Steadfetch](https://apify.com/steadfetch) (community)
- **Categories:** Developer tools, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 row delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## steadfetch/us-tide-times-extractor

Returns NOAA tide predictions (high/low tides) and water-level measurements for US coastal stations, as JSON. One row per tidal event, with station info, UTC timestamps, values in meters, and source URLs.

### What it does

- Queries the public, keyless NOAA CO-OPS API (`api.tidesandcurrents.noaa.gov`) for tide predictions or water-level data.
- Returns one row per predicted high/low tide or water-level measurement: `station_id`, `product`, `event_type`, `time`, `value`, `unit`, `datum`, `source_url`, `captured_at`.
- Supports two product modes: `predictions` (high/low tides) and `water_level` (continuous measurements with H/L detection).
- Uses plain HTTP + JSON. No browser, no login, no paywall.
- Validates every row against the dataset schema before it reaches the dataset.
- Geo-discovery: find stations near a lat/lon coordinate within a radius.

### How to use

Run it from the Apify Console or with the CLI:

```bash
apify call steadfetch/us-tide-times-extractor --input='{"stations":["8443970","9414290"]}'
```

Read the rows from the run's default dataset (JSON, CSV or the API).

#### Minimum input

```json
{ "stations": ["9414290"] }
```

With no input the Actor checks the default US stations (8443970 Boston, 9414290 San Francisco) for today.

#### Input fields

| Field | Type | Required | Default | Description | Example |
| --- | --- | --- | --- | --- | --- |
| `stations` | array | No | \[] | NOAA station IDs (7-10 digits). Use lat/lon for geo-discovery instead. | `["8443970","9414290"]` |
| `lat` | number | No | null | Latitude for geo-discovery (requires lon + radiusKm). | `36.95` |
| `lon` | number | No | null | Longitude for geo-discovery (requires lat + radiusKm). | `-121.99` |
| `radiusKm` | integer | No | `25` | Radius in km for geo-discovery (1-100). | `25` |
| `product` | string | No | `predictions` | NOAA product: `predictions` or `water_level`. | `predictions` |
| `date` | string | No | today | Query date in `YYYY-MM-DD` format. Defaults to today for predictions. | `"2026-10-26"` |
| `monitorMode` | boolean | No | `false` | When true, only emits rows whose values changed vs `knownState`. | `false` |
| `knownState` | object | No | {} | Maps station IDs to their last known value (for monitor mode). | `{"9414290":1.521}` |

### Output

#### Example output

```json
{
  "station_id": "9414290",
  "station_name": "San Francisco, CA",
  "latitude": 37.8063,
  "longitude": -122.4659,
  "product": "predictions",
  "event_type": "H",
  "time": "2026-10-26T07:25:00.000Z",
  "value": 1.521,
  "unit": "m",
  "datum": "MLLW",
  "source_url": "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?product=predictions&station=9414290&date=2026-10-26&timezone=gmt&units=metric&format=json",
  "captured_at": "2026-10-26T09:00:00.000Z"
}
```

#### Output fields

| Field | Type | Description |
| --- | --- | --- |
| `station_id` | string | Seven- to ten-digit NOAA station identifier (required). |
| `station_name` | string or null | Human-readable station name. |
| `latitude` | number or null | Station latitude in decimal degrees. |
| `longitude` | number or null | Station longitude in decimal degrees. |
| `product` | string | `predictions` or `water_level` (required). |
| `event_type` | string or null | High tide (`H`) or low tide (`L`). Predictions only. |
| `time` | date-time | UTC ISO 8601 timestamp (required). |
| `value` | number | Tide height or water level in meters (required). |
| `unit` | string | Always `m` (metric). Required. |
| `datum` | string or null | Vertical datum reference (e.g., MLLW). |
| `source_url` | string | Public NOAA URL that returns the same data (required). |
| `captured_at` | date-time | UTC timestamp when the data was fetched (required). |

### Pricing

Pay-per-event: `apify-actor-start` at 0.00005 USD per run (Apify-recommended default) and `apify-default-dataset-item` at **1.50 USD per 1,000 results** (0.0015 USD per row delivered), plus `steadfetch-monitor-check` at **0.0004 USD per monitor check** (0 results delivered).

Measured cost per 1,000 results: about **0.010 USD** (local run of two stations: ~12 rows each, 4 HTTP requests, 8 s at 256 MB and 0.2 USD per GB-hour), so the price leaves about 99% margin.

**Works on the Apify free plan - about 3,333 results for the $5 monthly credit.**

### FAQ

**Does the Actor need an API key from NOAA?** No. The NOAA CO-OPS datagetter API is public and keyless.

**Which stations are available?** Any NOAA CO-OPS station in the US and its territories. Use the station list or geo-discovery to find the nearest station to a coordinate.

**Can I monitor a station for changes?** Yes. Set `monitorMode: true` and pass `knownState` mapping station IDs to their last known values. Only changed rows are emitted.

**What time zone are the timestamps in?** All timestamps are UTC. The NOAA API returns times in local time; the Actor converts to UTC when `time_zone=gmt` is used.

**Can I get water-level data?** Yes. Set `product` to `water_level` and the Actor returns continuous water-level measurements. H/L extrema are auto-detected from the measurements.

**When am I charged?** Once per run start and once per row delivered. Monitor checks without new data only charge the monitor-check event.

### Maintenance

This Actor is tested daily. Data comes from the NOAA CO-OPS API, a public US federal source with no copyright restrictions (17 U.S.C. section 105). No known rotatable anti-bot patterns; the only rate limit is 1 request/second between calls.

### Support

Report bugs or request features through the Apify Store page (Issues tab) of the Actor, or through the Steadfetch actors repository issues. Include the run ID and the input used.

# Actor input Schema

## `stations` (type: `array`):

Seven- to ten-digit NOAA station identifiers. Use lat/lon with radiusKm for geo-discovery instead.

## `lat` (type: `number`):

Latitude in decimal degrees for geo-based station discovery. Requires lon and radiusKm.

## `lon` (type: `number`):

Longitude in decimal degrees for geo-based station discovery. Requires lat and radiusKm.

## `radiusKm` (type: `integer`):

Radius in kilometers for geo-based station discovery. Default 25, maximum 100.

## `product` (type: `string`):

Which NOAA product to query: tide predictions or water-level measurements.

## `date` (type: `string`):

Query date in YYYY-MM-DD format. Optional: defaults to today for predictions.

## `monitorMode` (type: `boolean`):

When true, only emits rows whose values changed compared to knownState.

## `knownState` (type: `object`):

Object mapping station IDs to their last known value for change detection in monitor mode.

## Actor input object example

```json
{
  "stations": [
    "8443970",
    "9414290"
  ],
  "lat": 36.95,
  "lon": -121.99,
  "radiusKm": 20,
  "product": "predictions",
  "date": "2026-10-26",
  "monitorMode": false,
  "knownState": {
    "9414290": 1.234
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items validated against the item schema in dataset_schema.json (fields).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "stations": [
        "8443970",
        "9414290"
    ],
    "radiusKm": 25,
    "product": "predictions",
    "monitorMode": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadfetch/us-tide-times-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "stations": [
        "8443970",
        "9414290",
    ],
    "radiusKm": 25,
    "product": "predictions",
    "monitorMode": False,
}

# Run the Actor and wait for it to finish
run = client.actor("steadfetch/us-tide-times-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "stations": [
    "8443970",
    "9414290"
  ],
  "radiusKm": 25,
  "product": "predictions",
  "monitorMode": false
}' |
apify call steadfetch/us-tide-times-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadfetch/us-tide-times-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/8Tz6gq1sBxQb1GBuh/builds/1686T0HQf7t2CojAA/openapi.json
