# Surfline Scraper (`solidcode/surfline-scraper`) Actor

\[💰 $3.0 / 1K] Extract Surfline surf forecasts — wave height, swell direction & period, wind, tides, water temperature, and weather for any spot. Search by name, paste spot URLs, or filter by region. Up to a 16-day horizon.

- **URL**: https://apify.com/solidcode/surfline-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Automation, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Surfline Scraper

Pull complete surf forecasts from Surfline for any break on earth — wave height, primary and secondary swell trains, wind, tides, water temperature, weather, and sunrise/sunset — all merged into one timestamp-aligned forecast for each spot. Search by spot name, paste report URLs, or filter by region, then get a clean forecast up to 16 days out. Built for surf-travel planners, surf schools, and coastal researchers who need structured, ready-to-use forecast data without clicking through Surfline spot by spot.

### Why This Scraper?

- **Five forecast dimensions in one row** — waves, wind, tides, weather, and sunlight are merged onto a single timestamp grid per spot, so every reading lines up instead of arriving as five separate feeds you have to stitch together.
- **Up to a 16-day horizon** — wave, wind, and tide data run out to 10 days; air temperature and daylight extend to a full 16, and you pick 1, 2, 3, 5, 7, 10, or 16 days per run.
- **Hourly, 3-hourly, or 6-hourly resolution** — dial reading density from one point every hour for dawn-patrol precision down to a light 6-hour summary.
- **Primary and secondary swell trains** — each wave reading carries every real swell partition with its `height`, `period` (seconds), and `direction` (degrees), so you can tell a clean groundswell from messy windswell.
- **Exact high and low tide extrema** — every reading gets a tide height, and the precise high/low turning points are tagged with `tideType` in place, not just an interpolated grid.
- **Wind type classification plus gusts** — every reading labels the wind as offshore, onshore, or cross-shore alongside speed, compass direction, and gust strength.
- **Overall condition rating and water temperature per spot** — Surfline's spot rating (e.g. POOR, FAIR, GOOD) and the day's water-temperature range come on every spot row.
- **Global coverage, one search returns them all** — search any named break worldwide (e.g. "Ocean Beach" surfaces every matching Surfline spot); narrow with a region breadcrumb filter like "California" or "Portugal".
- **Metric or imperial, your call** — switch wave height, wind speed, and temperature between meters/kph/°C and feet/mph/°F for the whole run.

### Use Cases

**Surf Travel Planning**
- Compare the forecast across a shortlist of breaks before booking a trip
- Spot the best swell window in the next 10 days for a target coastline
- Rank nearby spots by wave height and wind direction on a given day
- Plan around daylight with per-day sunrise and sunset times

**Surf Schools & Camps**
- Schedule beginner sessions around the mildest wave and wind windows
- Build daily condition briefings for students and instructors
- Match lesson locations to forecast rating across a region

**Coastal Research & Tide Analysis**
- Extract exact high/low tide times and heights for study sites
- Correlate swell period and direction with local coastal behavior
- Track water temperature trends across spots and seasons

**Surf Media & Content**
- Auto-populate forecast widgets and daily reports for surf websites
- Feed swell, wind, and tide data into newsletters and social posts
- Build "best conditions this week" roundups across multiple regions

**Watersports & Coastal Businesses**
- Time rentals, tours, and staffing to favorable wind and tide windows
- Alert customers when conditions at a home break turn favorable
- Enrich booking apps with live wave, wind, and daylight data

### Getting Started

#### Search by Spot Name

The simplest way to start — one break by name:

```json
{
    "spotSearch": ["Pipeline"]
}
````

#### Compare Several Spots at Higher Detail

```json
{
    "spotSearch": ["Trestles", "Malibu", "Rincon"],
    "forecastDays": "5",
    "intervalHours": "1",
    "units": "imperial"
}
```

#### Region-Filtered Search with Selected Conditions

```json
{
    "spotSearch": ["Ocean Beach"],
    "region": "California",
    "forecastDays": "7",
    "conditions": ["wave", "wind", "tides"],
    "maxSpots": 10
}
```

#### Exact Spots by URL

Paste Surfline surf-report URLs to target precise breaks you already know:

```json
{
    "spotUrls": [
        "https://www.surfline.com/surf-report/blacks-beach/5842041f4e65fad6a770883b"
    ],
    "forecastDays": "16",
    "intervalHours": "3",
    "units": "metric"
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `spotSearch` | string\[] | `["Pipeline"]` | Search surf spots by name (e.g. "Pipeline", "San Diego", "Bondi Beach"). Each term returns the best-matching spots. Leave empty if you are pasting spot URLs instead. |
| `spotUrls` | string\[] | `[]` | Direct Surfline spot URLs (e.g. a `/surf-report/<name>/<id>` link). Use these to target exact spots you already know. |
| `region` | string | `""` | Keep only spots whose location breadcrumb contains this text (e.g. "California", "Portugal", "Gold Coast"). Only affects name-searched spots; spots targeted directly by URL are always kept. |

#### Forecast Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `forecastDays` | select | `7 days` | Forecast horizon, starting today: 1, 2, 3, 5, 7, 10, or 16 days. Waves, wind, and tides run to 10 days; temperature and sunrise/sunset extend to 16. |
| `intervalHours` | select | `Every 3 hours` | Spacing between forecast readings: every hour, every 3 hours, or every 6 hours. Hourly gives the most detail. |
| `conditions` | multi-select | *all* | Which conditions to include: Waves & swell, Wind, Tides, Weather, Sunrise & sunset. Leave empty to include all of them. |
| `units` | select | `Imperial (ft, mph, °F)` | Measurement units for wave height, wind speed, and temperature: Metric (m, kph, °C) or Imperial (ft, mph, °F). |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxSpots` | integer | `20` | Hard cap on how many spots to forecast in one run. Protects you from an over-broad search returning thousands of spots. Set to 0 for no limit (capped at 2,000 spots as a safety ceiling). |

### Output

Each result is one surf spot with its full forecast embedded as a `forecast[]` time-series. Here is a representative row (trimmed to a few forecast readings):

```json
{
    "spotId": "5842041f4e65fad6a770883b",
    "spotName": "Blacks Beach",
    "region": "United States / California / San Diego",
    "latitude": 32.8894,
    "longitude": -117.2519,
    "timezone": "America/Los_Angeles",
    "url": "https://www.surfline.com/surf-report/blacks-beach/5842041f4e65fad6a770883b",
    "rating": "FAIR",
    "ratingScore": 2,
    "waterTempMin": 64,
    "waterTempMax": 66,
    "waveHeightMin": 3,
    "waveHeightMax": 4,
    "units": "imperial",
    "forecastDays": 3,
    "scrapedAt": "2026-07-02T14:30:00+00:00",
    "forecast": [
        {
            "timestamp": "2026-07-02T06:00:00-07:00",
            "waveMin": 3,
            "waveMax": 4,
            "waveHumanRelation": "Waist to shoulder high",
            "swells": [
                { "height": 2.6, "period": 14, "direction": 201 },
                { "height": 1.1, "period": 8, "direction": 285 }
            ],
            "windSpeed": 6,
            "windDirection": 240,
            "windType": "Offshore",
            "windGust": 9,
            "temperature": 68,
            "weatherCondition": "CLEAR",
            "tideHeight": 2.1,
            "tideType": "HIGH",
            "sunrise": "2026-07-02T05:47:00-07:00",
            "sunset": "2026-07-02T20:01:00-07:00"
        }
    ]
}
```

#### Spot Fields

| Field | Type | Description |
|-------|------|-------------|
| `spotId` | string | Surfline spot identifier |
| `spotName` | string | Human-readable spot name |
| `region` | string | Location breadcrumb (Country / State / Region) |
| `latitude` | number | Spot latitude |
| `longitude` | number | Spot longitude |
| `timezone` | string | Spot timezone (e.g. "America/Los\_Angeles") |
| `url` | string | Surfline surf-report URL |
| `rating` | string | Overall condition rating (e.g. POOR, FAIR, GOOD) |
| `ratingScore` | number | Numeric sort value behind the rating |
| `waterTempMin` | number | Day's minimum water temperature |
| `waterTempMax` | number | Day's maximum water temperature |
| `waveHeightMin` | number | Summary minimum wave height |
| `waveHeightMax` | number | Summary maximum wave height |
| `units` | string | Units used for this row (`metric` or `imperial`) |
| `forecastDays` | number | Number of days actually covered by the forecast |
| `scrapedAt` | string | ISO timestamp of data collection |
| `forecast` | object\[] | Per-reading forecast time-series (see below) |

#### Forecast Reading Fields

Each entry in `forecast[]` is one timestamp on the merged grid.

| Field | Type | Description |
|-------|------|-------------|
| `timestamp` | string | Reading time in the spot's local timezone |
| `waveMin` | number | Minimum surf height at this reading |
| `waveMax` | number | Maximum surf height at this reading |
| `waveHumanRelation` | string | Plain-language size (e.g. "Waist to shoulder high") |
| `swells` | object\[] | Swell trains, each with `height`, `period` (seconds), `direction` (degrees) |
| `windSpeed` | number | Wind speed at this reading |
| `windDirection` | number | Wind direction in degrees |
| `windType` | string | Wind quality: Offshore, Onshore, or Cross-shore |
| `windGust` | number | Gust speed at this reading |
| `temperature` | number | Air temperature at this reading |
| `weatherCondition` | string | Weather condition code (e.g. CLEAR, RAIN) |

#### Tide & Sunlight Fields

Also carried on each `forecast[]` entry.

| Field | Type | Description |
|-------|------|-------------|
| `tideHeight` | number | Tide height at this reading |
| `tideType` | string | `HIGH` or `LOW` when the reading falls on a tide turning point |
| `sunrise` | string | Local sunrise time for this reading's day |
| `sunset` | string | Local sunset time for this reading's day |

### Tips for Best Results

- **Start with one or two spots** to confirm the units, horizon, and conditions match what you need, then widen the search or raise `maxSpots`.
- **Use `intervalHours: 1` with a 3-day horizon** for the most granular dawn-patrol planning — hourly readings across three days give you precise swell and wind windows without a huge, slow response.
- **Select only the conditions you need** — dropping to `["wave", "wind"]` skips tide, weather, and sunlight lookups for faster runs when you only care about the surf.
- **Choosing 16 days** returns the full 10-day surf forecast plus 16-day temperature and daylight — the reported `forecastDays` reflects the actual horizon of the merged data.
- **Filter broad names with `region`** — searching "Ocean Beach" alone returns matches worldwide, so add a breadcrumb like "California" or "New Zealand" to zero in.
- **Read swell direction in degrees** — the `direction` on each swell in `swells[]` is a compass bearing the swell comes from, letting you match it to a spot's ideal swell window.
- **Pair `spotUrls` with a saved list** — the exact spot URL always targets the break you mean, even when several spots share a name.

### Pricing

**From $3.00 per 1,000 results** — one result is a single surf spot with its complete embedded forecast, not a per-reading charge, so a heavy 16-day hourly spot still counts as one result. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.36 | $0.34 | $0.32 | $0.30 |
| 1,000 | $3.60 | $3.40 | $3.20 | $3.00 |
| 10,000 | $36.00 | $34.00 | $32.00 | $30.00 |
| 100,000 | $360.00 | $340.00 | $320.00 | $300.00 |

No compute or time-based charges — you pay per result, plus a small fixed per-run start fee. Each result is one surf spot with its full embedded forecast.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate surf-forecast research, travel planning, and content use. You are responsible for complying with applicable laws and Surfline's Terms of Service. Use the data responsibly, respect reasonable request volumes, and do not use it for any unlawful purpose.

# Actor input Schema

## `spotSearch` (type: `array`):

Search for surf spots by name (e.g. 'Pipeline', 'San Diego', 'Bondi Beach'). Each term returns the best-matching spots. Leave empty if you are pasting spot URLs instead.

## `spotUrls` (type: `array`):

Direct Surfline spot URLs, e.g. 'https://www.surfline.com/surf-report/blacks-beach/5842041f4e65fad6a770883b'. Use these to target exact spots you already know.

## `region` (type: `string`):

Only keep spots whose location breadcrumb contains this text (e.g. 'California', 'Portugal', 'Gold Coast'). Only affects name-searched spots; spots targeted directly by URL are always kept. Leave blank for no region filter.

## `forecastDays` (type: `string`):

How many days of forecast to pull for each spot, starting today. Wave, wind and tide forecasts are available up to 10 days; air temperature and sunrise/sunset extend to 16. Selecting 16 returns the full 10-day surf forecast plus 16-day weather and daylight.

## `intervalHours` (type: `string`):

Spacing between forecast readings. Hourly gives the most detail; 3-hourly or 6-hourly gives a lighter summary with fewer readings per day.

## `conditions` (type: `array`):

Which forecast conditions to fetch for each spot. Fewer conditions means faster runs. Leave empty to include all of them.

## `units` (type: `string`):

Measurement units for wave height, wind speed, and temperature.

## `maxSpots` (type: `integer`):

Hard cap on how many spots to forecast in one run. Protects you from an over-broad search returning thousands of spots. Set to 0 for no limit (capped at 2,000 spots as a safety ceiling).

## Actor input object example

```json
{
  "spotSearch": [
    "Pipeline"
  ],
  "spotUrls": [],
  "forecastDays": "7",
  "intervalHours": "3",
  "conditions": [],
  "units": "imperial",
  "maxSpots": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of surf spots with location, current conditions, and forecast horizon.

# 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 = {
    "spotSearch": [
        "Pipeline"
    ],
    "spotUrls": [],
    "region": "",
    "forecastDays": "7",
    "intervalHours": "3",
    "conditions": [],
    "units": "imperial",
    "maxSpots": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/surfline-scraper").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 = {
    "spotSearch": ["Pipeline"],
    "spotUrls": [],
    "region": "",
    "forecastDays": "7",
    "intervalHours": "3",
    "conditions": [],
    "units": "imperial",
    "maxSpots": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/surfline-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "spotSearch": [
    "Pipeline"
  ],
  "spotUrls": [],
  "region": "",
  "forecastDays": "7",
  "intervalHours": "3",
  "conditions": [],
  "units": "imperial",
  "maxSpots": 20
}' |
apify call solidcode/surfline-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/surfline-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Surfline Scraper",
        "description": "[💰 $3.0 / 1K] Extract Surfline surf forecasts — wave height, swell direction & period, wind, tides, water temperature, and weather for any spot. Search by name, paste spot URLs, or filter by region. Up to a 16-day horizon.",
        "version": "1.0",
        "x-build-id": "HA7wbh33AEdKQJs2d"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/solidcode~surfline-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-solidcode-surfline-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/solidcode~surfline-scraper/runs": {
            "post": {
                "operationId": "runs-sync-solidcode-surfline-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/solidcode~surfline-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-solidcode-surfline-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "spotSearch": {
                        "title": "Spot Search",
                        "type": "array",
                        "description": "Search for surf spots by name (e.g. 'Pipeline', 'San Diego', 'Bondi Beach'). Each term returns the best-matching spots. Leave empty if you are pasting spot URLs instead.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "spotUrls": {
                        "title": "Spot URLs",
                        "type": "array",
                        "description": "Direct Surfline spot URLs, e.g. 'https://www.surfline.com/surf-report/blacks-beach/5842041f4e65fad6a770883b'. Use these to target exact spots you already know.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "region": {
                        "title": "Region Filter",
                        "type": "string",
                        "description": "Only keep spots whose location breadcrumb contains this text (e.g. 'California', 'Portugal', 'Gold Coast'). Only affects name-searched spots; spots targeted directly by URL are always kept. Leave blank for no region filter."
                    },
                    "forecastDays": {
                        "title": "Forecast Days",
                        "enum": [
                            "1",
                            "2",
                            "3",
                            "5",
                            "7",
                            "10",
                            "16"
                        ],
                        "type": "string",
                        "description": "How many days of forecast to pull for each spot, starting today. Wave, wind and tide forecasts are available up to 10 days; air temperature and sunrise/sunset extend to 16. Selecting 16 returns the full 10-day surf forecast plus 16-day weather and daylight.",
                        "default": "7"
                    },
                    "intervalHours": {
                        "title": "Time Resolution",
                        "enum": [
                            "1",
                            "3",
                            "6"
                        ],
                        "type": "string",
                        "description": "Spacing between forecast readings. Hourly gives the most detail; 3-hourly or 6-hourly gives a lighter summary with fewer readings per day.",
                        "default": "3"
                    },
                    "conditions": {
                        "title": "Conditions to Include",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Which forecast conditions to fetch for each spot. Fewer conditions means faster runs. Leave empty to include all of them.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "wave",
                                "wind",
                                "tides",
                                "weather",
                                "sunlight"
                            ],
                            "enumTitles": [
                                "Waves & swell",
                                "Wind",
                                "Tides",
                                "Weather (temperature, water temp)",
                                "Sunrise & sunset"
                            ]
                        },
                        "default": []
                    },
                    "units": {
                        "title": "Units",
                        "enum": [
                            "metric",
                            "imperial"
                        ],
                        "type": "string",
                        "description": "Measurement units for wave height, wind speed, and temperature.",
                        "default": "imperial"
                    },
                    "maxSpots": {
                        "title": "Maximum Spots",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Hard cap on how many spots to forecast in one run. Protects you from an over-broad search returning thousands of spots. Set to 0 for no limit (capped at 2,000 spots as a safety ceiling).",
                        "default": 20
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
