# NOAA Buoy Data Scraper (`automation-lab/noaa-buoy-observations`) Actor

Export official NOAA NDBC buoy observations by station and time range, including wind, waves, pressure, temperatures, units, and provenance.

- **URL**: https://apify.com/automation-lab/noaa-buoy-observations.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Education, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.13 / 1,000 observation extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## NOAA Buoy Data Scraper

Export official **NOAA buoy data** from the National Data Buoy Center (NDBC) into a clean, timestamped dataset. Choose buoy station IDs, retrieve NOAA's rolling recent observations or complete yearly historical files, and receive normalized wind, wave, pressure, air temperature, water temperature, location, units, and source-provenance fields.

The Actor uses NOAA's first-party public data files. It needs no NOAA API key, browser, login, or proxy.

### What can NOAA Buoy Data Scraper do?

- Retrieve recent standard-meteorological observations for up to 20 NDBC stations per run.
- Download as many as five annual historical station files in one run.
- Filter results with inclusive ISO 8601 start and end times.
- Normalize NOAA's dynamic columns and missing-value markers.
- Sort observations newest first and cap output with `maxItems`.
- Attach active-station names, coordinates, owner, program, and source URLs.
- Export through Apify as JSON, CSV, Excel, XML, RSS, or an API response.

### Who is this NOAA buoy data Actor for?

Marine operations teams can monitor winds, waves, and pressure at relevant offshore stations. Coastal researchers and analysts can build bounded time-series datasets. Surf, fishing, and boating products can ingest official observations. Data engineers can schedule a Task and deliver fresh station readings to databases, webhooks, or BI tools.

This Actor returns measurements, not forecasts or safety advice. For daily land weather observations, use [NOAA Historical Weather Observations](https://apify.com/automation-lab/noaa-historical-weather-observations).

### What data is extracted?

| Group | Fields |
| --- | --- |
| Identity | `stationId`, `stationName`, `stationType`, `owner`, `program` |
| Time | `timestamp`, `year`, `month`, `day`, `hour`, `minute` |
| Wind | `windDirectionDegrees`, `windSpeedMetersPerSecond`, `windGustMetersPerSecond` |
| Waves | `waveHeightMeters`, `dominantWavePeriodSeconds`, `averageWavePeriodSeconds`, `meanWaveDirectionDegrees` |
| Weather | `seaLevelPressureHpa`, `airTemperatureCelsius`, `dewPointCelsius`, `visibilityNauticalMiles`, `pressureTendencyHpa` |
| Water | `waterTemperatureCelsius`, `tideFeet` |
| Location | `latitude`, `longitude` |
| Provenance | `mode`, `units`, `sourceUrl`, `sourceAgency`, `retrievedAt` |

A measurement is `null` when NOAA marks it missing or the station does not publish that sensor field. Nulls are preserved rather than replaced with misleading zeroes.

### How to get NOAA buoy observations

1. Open the Actor input page.
2. Enter one or more NDBC station IDs, such as `41004`.
3. Choose **Recent / realtime** or **Historical yearly files**.
4. For historical data, provide one to five years.
5. Optionally add start/end timestamps and adjust the result limit.
6. Click **Start** and download the default dataset in your preferred format.

### Input parameters

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `stationIds` | string array | `["41004"]` | 1–20 alphanumeric NDBC station IDs |
| `mode` | string | `realtime` | `realtime` rolling archive or `historical` annual files |
| `years` | integer array | `[2025]` | Required in historical mode; 1–5 years |
| `startDate` | string | — | Optional inclusive ISO 8601 lower bound |
| `endDate` | string | — | Optional inclusive ISO 8601 upper bound |
| `maxItems` | integer | `100` | Total rows to save, from 1 to 10,000 |

Historical files only exist for station/year combinations published by NOAA. A missing file is logged and skipped so another requested station or year can still produce data.

### Input examples

Recent observations for one buoy:

```json
{
  "stationIds": ["41004"],
  "mode": "realtime",
  "maxItems": 25
}
```

A bounded historical analysis:

```json
{
  "stationIds": ["41001"],
  "mode": "historical",
  "years": [2025],
  "startDate": "2025-06-01T00:00:00Z",
  "endDate": "2025-06-03T23:59:59Z",
  "maxItems": 250
}
```

### Output example

A real recent run produces rows shaped like this:

```json
{
  "stationId": "41004",
  "stationName": "EDISTO - 41 NM Southeast of Charleston, SC",
  "latitude": 32.502,
  "longitude": -79.099,
  "timestamp": "2026-09-19T04:00:00.000Z",
  "windDirectionDegrees": 240,
  "windSpeedMetersPerSecond": 3,
  "windGustMetersPerSecond": 4,
  "waveHeightMeters": null,
  "seaLevelPressureHpa": 1017.6,
  "airTemperatureCelsius": 28.1,
  "waterTemperatureCelsius": 28.9,
  "mode": "realtime",
  "sourceUrl": "https://www.ndbc.noaa.gov/data/realtime2/41004.txt",
  "sourceAgency": "NOAA National Data Buoy Center"
}
```

Every row also contains a `units` object, making downstream interpretation explicit.

### How much does it cost to export NOAA buoy observations?

Pay-per-event pricing consists of a **$0.00005 start fee** and one `observation` event per saved row. The BRONZE price is **$0.003552 per observation**, with lower unit prices on higher subscription tiers.

| Saved observations | BRONZE estimate |
| ---: | ---: |
| 1 | 0.003602 USD |
| 25 | 0.08885 USD |
| 100 | 0.35525 USD |
| 1,000 | 3.55205 USD |

Estimates use the current BRONZE price and include the start event. Actual billing can differ by subscription tier and can be affected by refunds, fraud, disputes, taxes, corrections, or clawbacks. Missing files and filtered-out rows are not charged as observations.

### Monitoring and automation workflows

Create an Apify Task with stable station IDs, schedule it hourly or daily, and send results through a webhook. Use `timestamp` plus `stationId` as a natural deduplication key in your destination. For historical backfills, request a bounded year/date range, export it once, and keep recurring jobs in realtime mode.

Useful integrations include Google Sheets, Make, Zapier, webhooks, cloud storage, PostgreSQL, and any client that can call the Apify API.

### Use the Actor through the API

Replace `APIFY_TOKEN` with your token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~noaa-buoy-observations/run-sync-get-dataset-items?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"stationIds":["41004"],"mode":"realtime","maxItems":25}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/noaa-buoy-observations').call({
  stationIds: ['41004'], mode: 'realtime', maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient(token="APIFY_TOKEN")
run = client.actor("automation-lab/noaa-buoy-observations").call(run_input={
    "stationIds": ["41004"], "mode": "realtime", "maxItems": 25
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with MCP and AI agents

#### Claude Code setup

Add this Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/noaa-buoy-observations"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this MCP configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/noaa-buoy-observations"
    }
  }
}
```

Example prompts:

- “Get the 20 newest NOAA observations for buoy 41004 and summarize wind and waves.”
- “Export station 41001 observations from June 1–3, 2025 as a table.”
- “Compare the latest water temperatures at buoys 41002, 41004, and 46042.”

### Reliability and failure behavior

The Actor retries transient network failures and HTTP 429/5xx responses up to three times with bounded backoff. Requests time out after 30 seconds. Invalid station identifiers, malformed dates, reversed date ranges, and unsupported modes fail the run with a clear error. Missing station/year files are warnings rather than fabricated empty records.

NOAA may change files, station availability, sensor packages, or update cadence. Source timestamps are authoritative; “realtime” means NOAA's rolling recent archive, not guaranteed instantaneous delivery.

### Limits and tips

- Use exact NDBC station IDs; this version does not search by place or nearest coordinate.
- The Actor supports NDBC standard meteorological files, not every specialized NDBC sensor product.
- Active-station metadata can be unavailable for retired historical stations; observation rows still retain their station ID and source URL.
- `maxItems` applies across all requested stations and years after newest-first sorting.
- A maximum of 20 stations, five historical years, and 10,000 saved observations keeps runs bounded.
- No proxy setting is needed because NOAA's public files are accessed directly.

### Legality and responsible use

NOAA/NDBC data is official U.S. government source material, but users remain responsible for checking applicable NOAA notices, attribution requirements, laws, and downstream-use obligations. Preserve `sourceUrl`, `sourceAgency`, and observation timestamps when redistributing records. Do not use this Actor as the sole source for navigation, emergency, or life-safety decisions.

### Troubleshooting

**Why did my run return no rows?** Check that NOAA publishes a standard meteorological file for the station/year, then remove or widen date filters. The run log identifies missing files.

**Why is a measurement null?** NOAA uses missing-value markers when a sensor is unavailable or did not report. Null is the accurate normalized representation.

**Why is my historical run large?** Annual files can contain many observations. Set dates and `maxItems` before increasing scope.

**Why is station metadata null?** NOAA's active-station feed may no longer list a retired station. Historical measurements and provenance can still be valid.

### FAQ

**Does this provide forecasts?** No. It exports measured NDBC observations.

**Can I retrieve several buoys at once?** Yes, provide up to 20 station IDs.

**How far back does history go?** Coverage varies by station. Request years from 1970 through the current year, but only NOAA-published files return records.

**Are output units consistent?** Yes. The Actor maps standard fields to explicit names and includes a units object on every row.

**Are duplicate rows charged?** No. Records are deduplicated by station ID and observation timestamp before charging and saving.

### Related Automation Lab Actors

- [NOAA Historical Weather Observations](https://apify.com/automation-lab/noaa-historical-weather-observations) — daily land/weather station history.
- [Weather.gov Active Alerts Tracker](https://apify.com/automation-lab/us-active-weather-alerts-tracker) — active U.S. warning events and affected areas.
- [NOAA Storm Events Database Scraper](https://apify.com/automation-lab/noaa-storm-events-database-scraper) — retrospective severe-weather incident records.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/noaa-buoy-observations/changelog.md

# Actor input Schema

## `stationIds` (type: `array`):

One to 20 station identifiers, for example 41004 or 46042.

## `mode` (type: `string`):

Realtime returns NOAA's rolling recent observations; historical downloads complete yearly NDBC files.

## `years` (type: `array`):

Required in historical mode. Select one to five years whose files NOAA has published.

## `startDate` (type: `string`):

Optional inclusive ISO 8601 lower bound, such as 2025-06-01T00:00:00Z.

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

Optional inclusive ISO 8601 upper bound.

## `maxItems` (type: `integer`):

Maximum total observation rows saved after sorting newest first.

## Actor input object example

```json
{
  "stationIds": [
    "41004"
  ],
  "mode": "realtime",
  "years": [
    2025
  ],
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing all normalized station observations.

# 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 = {
    "stationIds": [
        "41004"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/noaa-buoy-observations").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 = {
    "stationIds": ["41004"],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/noaa-buoy-observations").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 '{
  "stationIds": [
    "41004"
  ],
  "maxItems": 20
}' |
apify call automation-lab/noaa-buoy-observations --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/noaa-buoy-observations"
        }
    }
}
```

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/Jsk78jR0wb5V8ph0M/builds/tWLxYfpbTx4k4rsXM/openapi.json
