# Royal Caribbean Cruise Pricing Scraper (`automation-lab/royal-caribbean-cruise-pricing-scraper`) Actor

🚢 Extract Royal Caribbean sailings, itineraries, ships, ports, live cabin prices, taxes, and direct booking links for fare alerts and travel analysis.

- **URL**: https://apify.com/automation-lab/royal-caribbean-cruise-pricing-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## Royal Caribbean Cruise Pricing Scraper

Extract Royal Caribbean sailings, itineraries, ships, ports, taxes, cabin prices, and direct booking links from the cruise line's public inventory.

**Royal Caribbean Cruise Pricing Scraper** turns grouped cruise-search results into one clean record per sailing. Use it to compare Interior, Outside, Balcony, and Suite prices, build fare alerts, publish cruise inventory, or study routes over time.

- 🚢 Get ship, route, destination, departure port, and cruise duration.
- 💵 Compare all public cabin-category prices in one row.
- 📅 Filter by sailing date, destination, departure port, ship, or nights.
- 🔗 Keep direct Royal Caribbean product and booking URLs.
- ⚡ Run an HTTP-only workflow without a browser or login.

### What does Royal Caribbean Cruise Pricing Scraper do?

The Actor queries Royal Caribbean's anonymous cruise-search service and paginates grouped itineraries. It then expands each group into individual sailing records.

Every record preserves its cruise group and itinerary IDs while adding the actual sailing date, cabin-price map, taxes, ship, port sequence, and booking link. That structure is useful for both one-time exports and scheduled price snapshots.

### Who is it for?

#### Travel agencies

Export available sailings and cabin prices for client research, quote preparation, and internal dashboards.

#### Cruise affiliates and comparison sites

Feed structured Royal Caribbean inventory into searchable landing pages while retaining source product URLs.

#### Fare-alert products

Schedule the Actor daily or weekly, compare records by `sailingId`, and notify customers when a cabin category changes price.

#### Market analysts

Track deployment by ship, destination, departure port, cruise duration, and sailing month without manually browsing hundreds of results.

### Why use this Royal Caribbean scraper?

Royal Caribbean's website groups many sailing dates under one itinerary card. Manual comparison becomes slow when you need repeatable, exportable data.

This Actor provides:

- one stable record per individual sailing;
- normalized cabin-price fields and a complete dynamic price map;
- source-supported search filters;
- bounded pagination and retries;
- JSON, CSV, Excel, XML, RSS, and API dataset access through Apify;
- reliable scheduling, webhooks, integrations, and monitoring.

### What Royal Caribbean data can I extract?

| Field | Description |
|---|---|
| `cruiseGroupId` | Royal Caribbean grouped cruise result ID |
| `sailingId` | Stable itinerary-and-date sailing ID |
| `itineraryCode` | Source itinerary/package code |
| `itineraryName` | Public itinerary title |
| `destinationName` | Destination region |
| `shipName` | Royal Caribbean ship |
| `departurePortName` | Embarkation port and region |
| `nights` | Cruise duration |
| `sailDate`, `startDate`, `endDate` | Sailing dates |
| `interiorPrice` | Interior cabin price, when offered |
| `outsidePrice` | Outside/Ocean View price, when offered |
| `balconyPrice` | Balcony cabin price, when offered |
| `suitePrice` | Deluxe/Suite cabin price, when offered |
| `cabinPrices` | Every source cabin category with currency and code |
| `taxesAndFees` | Source-reported taxes and fees |
| `taxesAndFeesIncluded` | Whether the displayed fare includes those fees |
| `itinerary` | Day-by-day port calls and activities |
| `productUrl`, `bookingUrl` | Direct Royal Caribbean links |
| `scrapedAt` | UTC extraction timestamp |

### How to scrape Royal Caribbean cruise prices

1. Open the Actor input page.
2. Optionally enter destination, departure-port, or ship codes.
3. Add a sailing date or cruise-duration range if needed.
4. Set **Maximum sailings** to a small value for the first run.
5. Click **Start**.
6. Preview the dataset, then export it or connect an integration.

No Royal Caribbean account, API key, or browser session is required for the public cruise-search scope.

### Input

A broad Bahamas search:

```json
{
  "destinationCodes": ["BAHAM"],
  "maxItems": 25
}
````

Cruises departing Miami in a date window:

```json
{
  "departurePortCodes": ["MIA"],
  "startDate": "2026-10-01",
  "endDate": "2027-03-31",
  "minNights": 3,
  "maxNights": 7,
  "maxItems": 100
}
```

A selected ship:

```json
{
  "shipCodes": ["WN"],
  "maxItems": 50
}
```

### Filter codes

The source uses compact codes rather than free-text labels. Common examples include:

- Destinations: `BAHAM` (Bahamas), `ALCAN` (Alaska), `AUSTL` (Australia & New Zealand), `BERMU` (Bermuda).
- Departure ports: `MIA` (Miami), `FLL` (Fort Lauderdale), `PCN` (Port Canaveral), `SEA` (Seattle), `STH` (Southampton).
- Ships: `UT` (Utopia of the Seas), `WN` (Wonder of the Seas), `AN` (Anthem of the Seas), `OV` (Ovation of the Seas).

Codes are validated structurally and sent to Royal Caribbean's source filters. An unknown but well-formed code naturally returns no matching sailings.

### Output example

```json
{
  "cruiseGroupId": "VY03LAX-1965471073",
  "sailingId": "VY03X045_2026-10-05",
  "itineraryCode": "VY03X045",
  "itineraryName": "Ensenada Cruise",
  "destinationName": "Mexico",
  "shipName": "Voyager of the Seas",
  "departurePortName": "Los Angeles, California",
  "nights": 3,
  "sailDate": "2026-10-05",
  "currency": "USD",
  "interiorPrice": 250.02,
  "outsidePrice": 278.52,
  "balconyPrice": 345.52,
  "suitePrice": 660.52,
  "taxesAndFees": 127.52,
  "taxesAndFeesIncluded": true,
  "productUrl": "https://www.royalcaribbean.com/itinerary/...",
  "bookingUrl": "https://www.royalcaribbean.com/booking/landing?...",
  "scrapedAt": "2026-07-18T03:30:00.000Z"
}
```

Prices reflect the public USA/USD shopping context used by this Actor. They can change between runs and are not a reservation or fare guarantee.

### Pagination and result limits

`pageSize` controls how many grouped itineraries the Actor requests at once. Each group can contain several individual sailings, and `maxItems` applies to the emitted sailing records.

The Actor stops exactly at the requested maximum. Use 10–25 items for a quick sample and increase the limit for production exports.

### How much does it cost to scrape Royal Caribbean cruises?

The Actor uses pay-per-event pricing: a **$0.005 run-start charge** plus a tiered charge for each sailing saved.

| Apify tier | Price per sailing | 1,000 sailings plus start |
|---|---:|---:|
| Free | $0.000057387 | about $0.0624 |
| Bronze | $0.000049902 | about $0.0549 |
| Silver | $0.000038923 | about $0.0439 |
| Gold | $0.000029941 | about $0.0349 |
| Platinum | $0.000019961 | about $0.0250 |
| Diamond | $0.000013973 | about $0.0190 |

The displayed Apify pricing table is authoritative. Higher subscription tiers receive lower per-sailing prices. Because this is an HTTP-only Actor, there is no browser overhead, and direct requests are the default.

Before a larger run, use a small `maxItems` value to estimate your total charge from the run console.

### Fare monitoring workflow

1. Choose a ship, departure port, destination, or date window.
2. Save the configuration as an Apify task.
3. Schedule it daily or weekly.
4. Export each dataset to your database or spreadsheet.
5. Match records by `sailingId` and compare cabin fields.
6. Trigger an alert when a preferred category drops below your threshold.

Keep `scrapedAt` to distinguish snapshots and `currency` to avoid comparing unlike values.

### Data quality notes

- Prices are captured exactly as returned by the public cruise-search endpoint.
- Missing cabin fields mean that category was not offered in that source response.
- `suitePrice` maps Royal Caribbean's `DELUXE` top-level category for consistent comparison.
- Taxes and fee inclusion are stored separately to prevent misleading totals.
- Product and booking URLs are converted to absolute Royal Caribbean URLs.
- Duplicate sailing IDs are removed within each run.

### Tips for reliable runs

- Start with one filter family and a low result limit.
- Use official source codes shown in the Royal Caribbean search experience.
- Keep date windows bounded for focused monitoring.
- Avoid launching many overlapping runs against the same inventory.
- Enable an Apify proxy only if direct requests are blocked in your environment.
- Review the run log if the source changes its GraphQL schema.

### Integrations

#### Google Sheets

Send new dataset items to a sheet, then use formulas to compare cabin fields across snapshots.

#### Slack or email alerts

Connect a webhook to your fare-difference service and notify agents when a selected sailing changes.

#### Airtable or a CRM

Store upcoming sailings as inventory records for sales and customer follow-up workflows.

#### Data warehouses

Load datasets into BigQuery, Snowflake, or PostgreSQL and model fare history by `sailingId` and `scrapedAt`.

#### Zapier and Make

Use Apify's integrations to route completed runs into no-code automations without maintaining scraper infrastructure.

### Apify API usage with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/royal-caribbean-cruise-pricing-scraper').call({
  departurePortCodes: ['MIA'],
  maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Apify API usage with Python

```python
from apify_client import ApifyClient

client = ApifyClient(token='YOUR_APIFY_TOKEN')
run = client.actor('automation-lab/royal-caribbean-cruise-pricing-scraper').call(run_input={
    'destinationCodes': ['BAHAM'],
    'maxItems': 25,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Apify API usage with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~royal-caribbean-cruise-pricing-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"shipCodes":["WN"],"maxItems":25}'
```

Fetch results after the run succeeds:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true&format=json"
```

### Use with Apify MCP and Claude

#### Claude Code

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=automation-lab/royal-caribbean-cruise-pricing-scraper"
```

#### Claude Desktop

Add this server in Claude Desktop **Settings → Developer → Edit Config**:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=automation-lab/royal-caribbean-cruise-pricing-scraper"
    }
  }
}
```

#### Cursor

Open **Settings → Tools & MCP → New MCP Server** and use the same `mcpServers` JSON configuration.

#### VS Code

Open **MCP: Add Server** from the command palette, select HTTP, and enter the Apify MCP URL above.

Example prompts:

- “Run the Royal Caribbean cruise price scraper for Miami departures and return 25 sailings.”
- “Extract Wonder of the Seas sailings, then summarize the cheapest Balcony fares.”
- “Compare Interior and Suite prices for Bahamas cruises in the exported dataset.”

Keep Apify tokens in environment variables or your client's secure authentication flow rather than committed configuration files.

### Scheduling and webhooks

Save a tested input as an Apify task, choose a cron schedule, and attach a webhook for `ACTOR.RUN.SUCCEEDED`. The webhook can pass the dataset ID to your downstream comparison job.

For price monitoring, keep the same filter scope between runs. Otherwise, additions caused by a wider search can look like inventory changes.

### Proxy support

Direct HTTP is used by default and normally works for this public endpoint. The optional `proxyConfiguration` field accepts Apify Proxy or custom proxy URLs.

A proxy is a fallback, not a requirement. Proxies can add bandwidth cost and may change response latency. Use stable sessions and conservative schedules rather than aggressive concurrency.

### Limitations

- The Actor covers public cruise-search inventory, not logged-in bookings, casino offers, loyalty discounts, excursions, drinks, Wi-Fi, or passenger data.
- Output availability and prices depend on Royal Caribbean's current public response.
- The initial release uses a coherent USA/USD market context; it does not claim arbitrary currency conversion.
- The source can rename filters, cabin categories, or GraphQL fields.
- A completed scrape is not a fare hold, quote, or reservation.

### Is it legal to scrape Royal Caribbean cruise data?

This Actor accesses public cruise-search data without authentication. Web scraping laws and contractual requirements vary by jurisdiction and use case.

Use the data responsibly, respect applicable terms and rate limits, avoid personal data, and obtain legal advice for regulated or high-volume commercial use. Do not use the Actor to interfere with the website or misrepresent live availability.

### Troubleshooting

#### The run returns zero records

Check that the codes exist and that the date ranges overlap available inventory. Remove filters one family at a time to identify an over-constrained combination.

#### A code is rejected

Codes may contain only letters, numbers, and periods. Enter Royal Caribbean source codes such as `MIA`, not full free-text names.

#### The endpoint temporarily fails

The Actor retries bounded transient failures. Try again later or enable an Apify proxy configuration if your route is blocked.

#### A cabin price is missing

That top-level category was not included for that sailing in the public response. Inspect `cabinPrices` for every category the source returned.

### FAQ

#### Does it need a Royal Caribbean login?

No. It extracts the public cruise-search scope anonymously.

#### Can it track a cruise I already booked?

It can monitor the matching public sailing fare, but it cannot access your booking, paid amount, or account-specific offers.

#### Are taxes included in the cabin prices?

Check `taxesAndFeesIncluded`. The separate `taxesAndFees` field preserves the source amount so your application can label prices correctly.

#### Can I export to CSV or Excel?

Yes. Open the run dataset and choose CSV, Excel, JSON, XML, RSS, or another Apify export format.

#### How often should I schedule it?

Daily or weekly is typical for fare monitoring. Choose a frequency proportionate to your use case and avoid unnecessary overlapping runs.

### Related scrapers

Combine this Actor with other Automation Labs travel workflows:

- [Google Maps Scraper](https://apify.com/automation-lab/google-maps-scraper) for travel-agent and local-tour lead research.
- [Booking Scraper](https://apify.com/automation-lab/booking-scraper) for destination accommodation research.
- [Tripadvisor Scraper](https://apify.com/automation-lab/tripadvisor-scraper) for destination and attraction intelligence.

Only public, relevant Automation Labs links are listed here. Availability may differ by account or publication status.

### Start extracting Royal Caribbean fares

Choose a small source-supported filter, keep the first `maxItems` low, and run the Actor. The resulting sailing-level dataset is ready for export, scheduling, analysis, and fare-alert integrations.

# Actor input Schema

## `destinationCodes` (type: `array`):

Royal Caribbean destination codes, such as BAHAM (Bahamas), CARIB (Caribbean), ALCAN (Alaska), or EURO (Europe). Leave empty for all destinations.

## `departurePortCodes` (type: `array`):

Royal Caribbean port codes, for example MIA (Miami), FLL (Fort Lauderdale), PCN (Port Canaveral), or SEA (Seattle).

## `shipCodes` (type: `array`):

Royal Caribbean ship codes, such as UT (Utopia), IC (Icon), or WN (Wonder).

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

Include sailings on or after this date (YYYY-MM-DD).

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

Include sailings on or before this date (YYYY-MM-DD).

## `minNights` (type: `integer`):

Minimum cruise duration supported by the source.

## `maxNights` (type: `integer`):

Maximum cruise duration supported by the source.

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

Stop after saving this many individual sailing records.

## `pageSize` (type: `integer`):

Number of grouped itineraries requested per source page. Lower this if the endpoint is unstable.

## `proxyConfiguration` (type: `object`):

Optional Apify proxy fallback. Direct HTTP is used by default and is normally sufficient.

## Actor input object example

```json
{
  "destinationCodes": [
    "BAHAM"
  ],
  "departurePortCodes": [],
  "shipCodes": [],
  "maxItems": 20,
  "pageSize": 20
}
```

# Actor output Schema

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

No description

# 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 = {
    "destinationCodes": [
        "BAHAM"
    ],
    "departurePortCodes": [],
    "shipCodes": [],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/royal-caribbean-cruise-pricing-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 = {
    "destinationCodes": ["BAHAM"],
    "departurePortCodes": [],
    "shipCodes": [],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/royal-caribbean-cruise-pricing-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 '{
  "destinationCodes": [
    "BAHAM"
  ],
  "departurePortCodes": [],
  "shipCodes": [],
  "maxItems": 20
}' |
apify call automation-lab/royal-caribbean-cruise-pricing-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/royal-caribbean-cruise-pricing-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Royal Caribbean Cruise Pricing Scraper",
        "description": "🚢 Extract Royal Caribbean sailings, itineraries, ships, ports, live cabin prices, taxes, and direct booking links for fare alerts and travel analysis.",
        "version": "0.1",
        "x-build-id": "4Dej2pIg7jgfBOhI4"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~royal-caribbean-cruise-pricing-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-royal-caribbean-cruise-pricing-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/automation-lab~royal-caribbean-cruise-pricing-scraper/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-royal-caribbean-cruise-pricing-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/automation-lab~royal-caribbean-cruise-pricing-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-royal-caribbean-cruise-pricing-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": {
                    "destinationCodes": {
                        "title": "🌎 Destination codes",
                        "type": "array",
                        "description": "Royal Caribbean destination codes, such as BAHAM (Bahamas), CARIB (Caribbean), ALCAN (Alaska), or EURO (Europe). Leave empty for all destinations.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "departurePortCodes": {
                        "title": "⚓ Departure port codes",
                        "type": "array",
                        "description": "Royal Caribbean port codes, for example MIA (Miami), FLL (Fort Lauderdale), PCN (Port Canaveral), or SEA (Seattle).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "shipCodes": {
                        "title": "🚢 Ship codes",
                        "type": "array",
                        "description": "Royal Caribbean ship codes, such as UT (Utopia), IC (Icon), or WN (Wonder).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startDate": {
                        "title": "Earliest sailing date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Include sailings on or after this date (YYYY-MM-DD)."
                    },
                    "endDate": {
                        "title": "Latest sailing date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Include sailings on or before this date (YYYY-MM-DD)."
                    },
                    "minNights": {
                        "title": "Minimum nights",
                        "minimum": 2,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Minimum cruise duration supported by the source."
                    },
                    "maxNights": {
                        "title": "Maximum nights",
                        "minimum": 2,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Maximum cruise duration supported by the source."
                    },
                    "maxItems": {
                        "title": "Maximum sailings",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Stop after saving this many individual sailing records.",
                        "default": 25
                    },
                    "pageSize": {
                        "title": "Cruise groups per request",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Number of grouped itineraries requested per source page. Lower this if the endpoint is unstable.",
                        "default": 20
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional Apify proxy fallback. Direct HTTP is used by default and is normally sufficient."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
