# NOAA Tides API - Tide Predictions, High Tide & Low Tide Times (`neverempty/noaa-tide-predictions-api`) Actor

High and low tide times and heights from the official NOAA CO-OPS API for all 3,499 US tide prediction stations. Give a station id or a lat,lon point and it finds the nearest station. Rows carry local time, a UTC timestamp with the offset that applied, feet and meters, and the range to the next.

- **URL**: https://apify.com/neverempty/noaa-tide-predictions-api.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Travel, Developer tools, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 tide predictions

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## NOAA Tides API - Tide Predictions, High Tide & Low Tide Times

Official **NOAA tide predictions** for the United States: the time and height of every **high tide** and
**low tide**, for any of NOAA's **3,499 tide prediction stations**, from the CO-OPS
(Center for Operational Oceanographic Products and Services) API.

Give it a station id, or just a `lat,lon` point and it finds the nearest station for you.

- **No API key, no scraping, no proxy.** US government data, public domain.
- **Reference and subordinate stations both work** — 1,256 reference stations and 2,243 subordinate
  stations (measured from the official station list on 2026-08-31).
- **Past and future dates.** Tide tables for a whole month, or just the next tides from right now.

### What this returns that the raw NOAA endpoint does not

The CO-OPS `predictions` endpoint answers with three fields per tide: a time string, a height, and `H` or `L`.
Everything below is the work this Actor does on top of it.

| Column | Why it matters |
|---|---|
| `timeUtc`, `utcOffsetHours` | The raw API returns **local clock time with no offset** (`2026-09-01 04:32`). A scheduler cannot use that. This Actor reads the same window in the station's local time **and** in UTC and lines the two up, so every tide carries a real ISO-8601 UTC timestamp and the offset that applied at that moment — daylight saving included. When the two cannot be lined up, `timeUtc` is `null` and the run says so: it never guesses an offset. |
| `stationId`, `stationName`, `state`, `latitude`, `longitude` | The raw API returns none of these with the predictions. |
| `distanceKm`, `requestedPoint` | Give `"37.81,-122.47"` and you get the nearest station plus how far away it is. |
| `heightMeters` | The raw API returns one unit system per request. Both are here (meters converted from the feet NOAA returns; within 1 cm of NOAA's own metric answer). |
| `minutesToNextTide`, `rangeToNextFeet`, `rangeToNextMeters` | How long until the water turns, and how far it moves. |
| `isNextTide` | In the default "days ahead" mode, exactly one row per station is marked as the next tide from the moment the run starts. In a fixed `beginDate`/`endDate` window it marks the first tide that is still ahead, and nothing at all for a window in the past. |
| `timeZoneName` | NOAA's own name for the station's **standard** time zone (`EST` even in July). Use `utcOffsetHours` for the offset that actually applied to that tide - it follows daylight saving. |
| `stationType`, `referenceStationId` | Whether a station is a NOAA reference station or a subordinate station, and which station it is derived from. |

### Input

| Field | Type | Default | Meaning |
|---|---|---|---|
| `locations` | array | `["8443970"]` | NOAA station ids (`8443970`, `TEC1603`) and/or points (`"42.36,-71.05"`). Points are resolved to the nearest tide prediction station. |
| `days` | integer | `7` | Days of tides from the moment the run starts. Only tides still ahead are returned. About 4 tides per day per station. |
| `beginDate` | string | `""` | Start of a fixed window, `"2026-09-01"`. The station's own local calendar days, like a printed tide table. Past dates work. |
| `endDate` | string | `""` | End of the fixed window. At most 365 days in one run. |
| `datum` | string | `"MLLW"` | `MLLW`, `MLW`, `MSL`, `MTL`, `MHW`, `MHHW`, `NAVD` or `STND`. |
| `maxRetries` | integer | `4` | Retries when NOAA does not answer. Bad requests are not retried. |

### Output

One row per predicted high or low tide:

```json
{
  "rowType": "tide",
  "stationId": "8443970",
  "stationName": "Boston",
  "state": "MA",
  "latitude": 42.35389,
  "longitude": -71.05028,
  "stationType": "reference",
  "tideType": "Mixed",
  "tide": "high",
  "tideCode": "H",
  "timeLocal": "2026-08-31 14:05",
  "dateLocal": "2026-08-31",
  "timeUtc": "2026-08-31T18:05:00.000Z",
  "utcOffsetHours": -4,
  "heightFeet": 10.43,
  "heightMeters": 3.179,
  "datum": "MLLW",
  "minutesToNextTide": 375,
  "rangeToNextFeet": 10.439,
  "rangeToNextMeters": 3.182,
  "isNextTide": true,
  "source": "NOAA CO-OPS Tides & Currents (official, public domain)"
}
```

### What it does when something is wrong

A tide feed that quietly answers "no tides" is worse than one that fails, so this Actor never does that.

- A station id that does not exist, a station with no predictions (the Great Lakes have none), or a datum
  the station does not publish → **one row saying which input failed and why**, and that row is not charged.
- NOAA rejecting a request with **HTTP 200 and an error body** — which is what happens when you ask for a
  datum a station does not carry — is treated as a failure, not as a day without tides.
- If no location at all could be read, the run **fails** instead of finishing green with an empty dataset.
- If the local and UTC copies of the predictions cannot be lined up, the rows still arrive with local time
  and heights, `timeUtc` is `null`, and the run logs it and records `RUN_UTC_UNMATCHED`.
- A run that hits the maximum total charge you set says so in the log and in `RUN_BUDGET_STOP`.

### Measured

Run on 2026-08-31 with 5 inputs — 2 station ids, 2 points, 1 station id that does not exist:
**35 tide rows + 1 error row in 7.9 seconds**, 0 rows with a missing UTC timestamp.
`13.44,144.66` resolved to Apra Harbor, Guam at 0.54 km, with a `+10` offset.
`42.36,-71.05` resolved to Boston at 0.68 km — the same station as the id `8443970` in the same run,
so it was read once and **charged once, not twice**.
A 365-day window was checked at Boston, Troy, Guam and Hawaii: both daylight saving changes were picked up
in the right places, and no timestamp went backwards.

The build is covered by 70 automated checks, and 65 deliberate defects were injected one at a time to
confirm those checks actually catch them.

### Billing

Pay per event: one charge per tide row delivered. Rows that report a problem, and the row that says
"no tides in this window", are **not** charged. Setting a maximum total charge on the run stops delivery
rather than handing rows over unpaid.

### Support

Questions and bug reports: use the **Issues** tab on this Actor. Include the input you ran and the run id.

Data source: [NOAA CO-OPS Tides & Currents](https://tidesandcurrents.noaa.gov/) — official US government
data, public domain. This Actor is not affiliated with NOAA.

# Actor input Schema

## `locations` (type: `array`):

NOAA station ids such as "8443970" (Boston) or "TEC1603", and/or points written as "lat,lon" such as "37.81,-122.47". A point is resolved to the nearest of the 3,499 official tide prediction stations and the distance in km is returned with every row. If none of the values are usable the run fails instead of quietly returning a default station.

## `days` (type: `integer`):

How many days of tides to return, counted from the moment the run starts. Only tides still in the future are returned. Ignored when you set a start and end date below. A station has about 4 tides a day, so 7 days is about 28 rows per station.

## `beginDate` (type: `string`):

First day of a fixed window, as "2026-09-01". Dates are the station's own local calendar days, the same as a printed tide table. Past dates work. Leave empty to use "Days ahead" instead.

## `endDate` (type: `string`):

Last day of the fixed window, as "2026-09-30". Must be given together with the start date. At most 365 days in one run, so a mistyped year cannot run up a bill.

## `datum` (type: `string`):

The zero the heights are measured from. MLLW (mean lower low water) is what US tide tables and nautical charts use. Not every station publishes every datum: NOAA rejects the ones it does not have, and this Actor reports that instead of returning an empty result.

## `maxRetries` (type: `integer`):

How many times to retry when the NOAA API does not answer or returns a server error. Bad requests, such as a datum a station does not publish, are not retried.

## Actor input object example

```json
{
  "locations": [
    "8443970"
  ],
  "days": 7,
  "beginDate": "",
  "endDate": "",
  "datum": "MLLW",
  "maxRetries": 4
}
```

# Actor output Schema

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

One row per predicted high or low tide, plus one row per station that could not be read.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/noaa-tide-predictions-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/noaa-tide-predictions-api").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 '{}' |
apify call neverempty/noaa-tide-predictions-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/noaa-tide-predictions-api"
        }
    }
}

```

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/aPltUHPsml9s4nuF2/builds/50wzdBXae0L48dm5y/openapi.json
