# CruiseMapper Scraper - Cruises, Itineraries & Ship Tracker (`scrapewise/cruisemapper-scraper`) Actor

Scrape CruiseMapper cruises by date, region, ship, line or port: full itinerary with port times, nights, lowest price. Plus ship specs (IMO, MMSI, tonnage, capacity), live positions of 1,100+ cruise ships and port schedules. Accepts the input of the old CruiseMapper actor.

- **URL**: https://apify.com/scrapewise/cruisemapper-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** Travel, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.14 / 1,000 result delivereds

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

## CruiseMapper Scraper: cruises, itineraries, ship tracker and port schedules

Scrape **CruiseMapper** into clean rows: every cruise that matches your dates, destination, ship, cruise line or port,
with its **full itinerary** (each port with arrival and departure time, country and link), nights, departure and
arrival port and the **lowest advertised price**. Switch the mode to get **ship data** (IMO, MMSI, tonnage, passengers,
crew, current position, upcoming cruises), the **live position of every cruise ship** on the map in one request, or
the **port schedule** of any cruise port, month by month.

No account, no cookies, no API key. Already using another CruiseMapper actor? **Paste your input as it is**: the
classic `start_date`, `end_date`, `ship_name`, `cruise_line`, `destination` and `stop_N_date` columns all work.

### At a glance

- **Price:** US$ 1.50 per 1,000 results, same price with or without the full itinerary
- **Fee per run:** US$ 0.0005
- **Four modes:** cruises, ships, live fleet positions, port schedule
- **Cruise filters:** departure date window, destination region, ship, cruise line, departure port, port of call,
  length in nights, ocean or river ship, themed and repositioning cruises, max price per person
- **Speed (tested 2026-10-20):** 1,000 cruises with full itineraries in about 40 seconds; 1,128 ship positions in
  under 2 seconds; a month of Miami port calls in 2 seconds
- **Monitoring:** only new cruises since the last run, and price change tracking
- **Safe on long runs:** if the platform moves the run to another server, it continues where it stopped and never
  charges a result twice
- **Error rows** (unknown ship or port, bad date): free, with an `errorCode`

### One real row

From a test on 2026-10-20 with `{"shipName": "Allure Of The Seas", "startDate": "2026-12-01", "maxItems": 1}`
(stops cut to two here; the real row has all five):

```json
{
  "type": "cruise",
  "id": "5281301",
  "ship_name": "Allure Of The Seas",
  "cruise_date": "2026 Dec 06",
  "cruise_title": "7 nights, round-trip from Miami, USA",
  "cruise_price": "$805",
  "cruise_line": "Royal Caribbean Cruises cruise line",
  "stop_1_date": "06 Dec 16:00",
  "stop_1_text": "Departing from Miami, Florida",
  "stop_2_date": "09 Dec 08:00 - 17:00",
  "stop_2_text": "Philipsburg St Maarten, Netherlands Antilles",
  "cruise_url": "https://www.cruisemapper.com/ships/Allure-Of-The-Seas-662#ship-itinerary-5281301-2026",
  "line_name": "Royal Caribbean",
  "ship_id": "662",
  "departure_date": "2026-12-06",
  "return_date": "2026-12-13",
  "duration_nights": 7,
  "trip_type": "round-trip",
  "departure_port": "Miami, Florida",
  "arrival_port": "Miami, Florida",
  "departure_time": "2026-12-06T16:00",
  "arrival_time": "2026-12-13T06:00",
  "price_usd": 805,
  "ports_of_call": ["Philipsburg St Maarten", "St Thomas Island USVI", "Puerto Plata-Amber Cove"],
  "countries": ["Dominican Rep", "Netherlands", "US Virgin Islands", "USA"],
  "stop_count": 5,
  "stops": [
    {"stop": 1, "type": "departure", "date": "2026-12-06", "departure": "2026-12-06T16:00", "port": "Miami",
     "country": "USA", "country_code": "US", "port_id": "40", "port_url": "https://www.cruisemapper.com/ports/miami-port-40"},
    {"stop": 2, "type": "port_of_call", "date": "2026-12-09", "arrival": "2026-12-09T08:00",
     "departure": "2026-12-09T17:00", "port": "Philipsburg St Maarten", "country": "Netherlands", "country_code": "NL"}
  ],
  "scraped_at": "2026-10-20T15:46:16Z"
}
```

Times are local port times, as CruiseMapper shows them. `cruise_price` is the site's text; `price_usd` is the number.

### How to use this CruiseMapper scraper

Cruises in the Caribbean leaving in the next 60 days (the prefill):

```json
{ "mode": "cruises", "region": "8", "daysAhead": 60, "maxItems": 50 }
```

Seven to ten night Royal Caribbean cruises from Miami in December, up to US$ 1,000 per person:

```json
{
  "startDate": "2026-12-01",
  "endDate": "2026-12-31",
  "cruiseLine": "Royal Caribbean",
  "departurePort": "Miami",
  "cruiseLength": "6-10",
  "maxPricePerPerson": 1000,
  "maxItems": 200
}
```

Ship data for a whole fleet, or for single ships by name or IMO:

```json
{ "mode": "ships", "cruiseLine": "Celebrity Cruises" }
```

```json
{ "mode": "ships", "shipNames": ["Allure Of The Seas", "9812705"] }
```

Live positions of every cruise ship (about 1,100 rows, one request), or of one line:

```json
{ "mode": "fleetPositions", "cruiseLine": "MSC Cruises" }
```

Which ships call at Miami and Nassau in December, and in January:

```json
{ "mode": "portSchedule", "ports": ["Miami", "Nassau"], "month": "2026-12", "numberOfMonths": 2, "maxItems": 1000 }
```

| Field | What it does |
|---|---|
| `mode` | `cruises` (default), `ships`, `fleetPositions`, `portSchedule` |
| `startUrls` | Cruise finder, ship, cruise line or port links from cruisemapper.com |
| `region` | Destination region (Caribbean, Mediterranean, Alaska, Europe rivers and 20 more) |
| `startDate`, `endDate`, `daysAhead` | Departure date window |
| `shipName`, `cruiseLine`, `departurePort`, `portOfCall` | Names as on CruiseMapper, any capitalization |
| `cruiseLength` | `any`, `1-2`, `3-5`, `6-10`, `11-14`, `15+` nights |
| `shipType` | `any`, `ocean`, `river` |
| `cruiseType` | `transatlantic`, `world`, `christmas`, repositioning seasons and more |
| `maxPricePerPerson` | Lowest advertised price per person, US dollars |
| `includeItinerary` | Full itinerary per cruise (default on) |
| `shipNames`, `includeShipDetails`, `includeUpcomingCruises` | Ships mode |
| `ports`, `month`, `numberOfMonths` | Port schedule mode |
| `maxItems` | Results per search, ship list or port (50 when empty) |
| `onlyNew`, `compareWithPreviousRun` | Monitoring for scheduled runs |

A name CruiseMapper does not know (a typo in a ship or port) returns a free error row with suggestions. The site
itself would silently ignore it and return every cruise; this cruise scraper checks every name first.

### Switching from another CruiseMapper actor? Your existing input works

Paste the input you already use. These names and values are read as they are:

| You may already send | Read as |
|---|---|
| `start_date`, `end_date` (`2026-06-01` or `01-Jun-2026`) | `startDate`, `endDate` |
| `destination` (`"8"`, `"0"`, or a name like `"Caribbean"`) | `region` |
| `cruise_length` (`"0"` to `"5"`) | `cruiseLength` |
| `ship_name`, `cruise_line`, `departure_port`, `port_of_call` | `shipName`, `cruiseLine`, `departurePort`, `portOfCall` |
| `ship_type` (`"0"`, `"1"`, `"2"`) | `shipType` (any, ocean, river) |
| `max_number_of_pages` (`-1` = all, 15 cruises per page) | page limit, as before |
| `cruise_line` + `get_ship_details` | `ships` mode for that line |
| `searchType` (`cruises`, `ports`), `startDate`, `endDate`, `shipName`, `departurePort`, `maxResults`, `startUrls` | same meaning |

The output keeps the classic columns, with the same names and formats: `id`, `ship_name`, `cruise_date`
(`2026 Dec 06`), `cruise_title`, `cruise_price` (`$805`), `cruise_line` and one `stop_N_date` / `stop_N_text` pair per
stop, so spreadsheets and scripts built on them keep working. The new fields are added after them. The `legacy`
dataset view shows only the classic columns.

```json
{ "start_date": "2026-12-01", "end_date": "2026-12-20", "cruise_length": "3", "cruise_line": "Royal Caribbean",
  "departure_port": "Miami", "destination": "8", "ship_type": "0", "max_number_of_pages": -1 }
```

### Output fields

| Field | Meaning |
|---|---|
| `id`, `cruise_url`, `ship_name`, `ship_id`, `ship_url`, `line_name` | Cruise and ship identity |
| `departure_date`, `return_date`, `duration_nights`, `trip_type` | Dates and length (`round-trip` or `one-way`) |
| `departure_port`, `arrival_port`, `departure_time`, `arrival_time` | Where and when it leaves and ends |
| `price_usd`, `cruise_price` | Lowest advertised price per person ("from"), number and text |
| `stops` | Every stop: type, date, arrival, departure, port, country, country code, port id and link |
| `ports_of_call`, `countries`, `stop_count` | Itinerary summary |
| `ship_type` | `ocean` or `river`, when the ship type filter is used |

**Ships:** `imo`, `mmsi`, `flag`, `year_built`, `builder`, `ship_class`, `gross_tonnage`, `length_m`, `beam_m`,
`speed_knots`, `passengers`, `passengers_max`, `crew`, `decks`, `cabins`, `last_refurbishment`, `owner`, `operator`,
`homeports`, `latitude`, `longitude`, `position_text`, `destination`, `ais_speed_knots`, `ais_course`,
`position_time`, `current_cruise`, `upcoming_cruises`, `rating_stars`, `rating_votes`, `image_url`.

**Live positions:** `ship_name`, `imo`, `mmsi`, `line_name`, `flag`, `ship_category` (ocean, river, ferry,
small_ship, icebreaker_research), `latitude`, `longitude`, `speed_knots`, `course`, `heading`, `destination`,
`position_time`.

**Port calls:** `port_name`, `port_country`, `port_locode`, `port_region`, `port_latitude`, `port_longitude`, `date`,
`weekday`, `ship_name`, `ship_url`, `line_name`, `arrival`, `departure`.

#### Error codes (never charged)

| Code | When |
|---|---|
| `INVALID_INPUT` | Unknown ship, line, port or region; a date that is not a date; a link from another site |
| `NOT_FOUND` | A ship, line or port page that does not exist |
| `NO_RESULTS` | Nothing matches your filters in your dates |
| `BLOCKED` | CruiseMapper did not answer after retries; run again |
| `NOT_REACHED` | The run timeout or the cost guard came before this input |

### Pricing

Pay per event, no monthly fee:

| Event | Price |
|---|---|
| Result delivered (cruise, ship, ship position or port call) | US$ 1.50 per 1,000 |
| Run start | US$ 0.0005 |

A run of 50 cruises with full itineraries costs about US$ 0.08. Error rows, duplicates, filtered results and results
already seen (`onlyNew`) are never charged. Set a maximum cost per run in Apify and the Actor stops cleanly at it.

### Use it from code and AI agents

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("scrapewise/cruisemapper-scraper").call(run_input={
    "region": "8", "departurePort": "Miami", "daysAhead": 90, "maxItems": 200})
for c in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(c["departure_date"], c["ship_name"], c["duration_nights"], c["price_usd"], c["ports_of_call"])
```

The same works from the HTTP API (`run-sync-get-dataset-items`), n8n, Make, Zapier and Google Sheets. For AI agents
(Claude, ChatGPT, Cursor and any MCP client): `https://mcp.apify.com/?actors=scrapewise/cruisemapper-scraper`.

Requests an agent can pass straight through:

- "Find Caribbean cruises from Miami in March under $800" -> `{"region": "8", "departurePort": "Miami", "startDate": "2027-03-01", "endDate": "2027-03-31", "maxPricePerPerson": 800, "maxItems": 100}`
- "Where is Allure of the Seas right now and what are its next cruises?" -> `{"mode": "ships", "shipNames": ["Allure Of The Seas"]}`
- "Which cruise ships are in Nassau next week?" -> `{"mode": "portSchedule", "ports": ["Nassau"], "maxItems": 200}`

### FAQ

**Is there an official CruiseMapper API?** No public one. CruiseMapper offers no developer API or data feed for
cruise itineraries, ship positions or port schedules. This Actor reads the same public pages and map data the website
shows, and returns them as JSON, CSV or Excel.

**Is the price per cabin?** No. CruiseMapper shows one "from" price per person (double occupancy) per cruise, and not
for every cruise. `price_usd` is that number, or empty.

**How far ahead and back does it go?** As far as CruiseMapper lists sailings: usually two to three years ahead, and
recent past cruises when you set a past start date.

**Can I monitor new cruises or price drops?** Yes. Save a Task with `onlyNew: true` and `compareWithPreviousRun: true`
and schedule it daily. New cruises and price changes come with `is_new`, `previous_price_usd` and `is_price_drop`.

**Does it collect passenger reviews?** No. Only the ship's average star rating and number of votes. No reviews, no
names, no personal data.

**Is it legal?** It reads public pages that anyone can open without logging in. How you use the data is your
responsibility under CruiseMapper's terms and the laws that apply to you.

### Changelog

- **2026-10-20:** first release. Cruise search with full itineraries, ships, live fleet positions and port
  schedules; input of older CruiseMapper actors accepted; new cruise and price monitoring; resume after migration.

This Actor collects only publicly visible data from CruiseMapper. Independent tool, not affiliated with CruiseMapper.

# Actor input Schema

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

Cruises: the CruiseMapper cruise finder with the filters below, one row per sailing with its full itinerary. Ships: one row per ship with IMO, MMSI, specs, current position and upcoming cruises. Live fleet positions: every ship on CruiseMapper's live map (about 1,100) with latitude, longitude, speed, course and destination. Port schedule: every ship calling at the ports you list, with arrival and departure times, month by month.

## `startUrls` (type: `array`):

Links copied from cruisemapper.com: a cruise finder results page (its filters are kept), a ship page (https://www.cruisemapper.com/ships/Allure-Of-The-Seas-662), a cruise line page or a port page (https://www.cruisemapper.com/ports/miami-port-40). Ship and line links give cruises in 'Cruises' mode and ship rows in 'Ships' mode; port links give the port schedule.

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

CruiseMapper's destination regions. Leave empty for all destinations. The 'destination' field of older CruiseMapper actors (codes such as "8" or names such as "Caribbean") is also read.

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

First departure date, YYYY-MM-DD (for example 2026-12-01). Empty = today. DD-MMM-YYYY (01-Dec-2026) also works.

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

Last departure date, YYYY-MM-DD. Results come in date order and the run stops after this date. Empty = no end date (use 'Days ahead' or 'Max results').

## `daysAhead` (type: `integer`):

Window of departure dates counted from 'Departing from' (or today), used when 'Departing until' is empty. 60 = cruises leaving in the next 60 days.

## `cruiseLength` (type: `string`):

Length filter of the site. Codes "0" to "5" from older actors are read too.

## `shipName` (type: `string`):

Ship name as on CruiseMapper, for example Allure Of The Seas or Celebrity Edge. Capital letters do not matter; an unknown name returns a free error row with suggestions instead of every cruise.

## `cruiseLine` (type: `string`):

Cruise line, for example Royal Caribbean, Carnival Cruise Line, MSC Cruises, Viking River Cruises. In 'Ships' mode it lists the whole fleet of the line.

## `departurePort` (type: `string`):

Port the cruise leaves from, for example Miami, Fort Lauderdale, Barcelona, Southampton.

## `portOfCall` (type: `string`):

Only cruises that stop at this port, for example Nassau, Cozumel, Santorini.

## `shipType` (type: `string`):

CruiseMapper has no ship type filter, so the Actor checks each ship against the site's live map category (river cruise ships are their own category). Filtered cruises are not charged.

## `cruiseType` (type: `string`):

Themed and holiday cruises, ocean crossings and repositioning cruises, as in the site's finder.

## `maxPricePerPerson` (type: `integer`):

Lowest advertised price per person, in US dollars, as the site filters it. Cruises with no price shown are kept by the site.

## `includeItinerary` (type: `boolean`):

On (default): every cruise gets its ports with arrival and departure times, countries, port links, return date and arrival port (a little slower, same price). Off: faster, only the search row.

## `shipNames` (type: `array`):

For 'Ships' and 'Live fleet positions': ship names (Allure Of The Seas), IMO numbers (9383948) or MMSI numbers, one per line. In 'Ships' mode, 'Cruise line' adds the whole fleet of that line.

## `includeShipDetails` (type: `boolean`):

On (default): opens each ship page for IMO, MMSI, specs, current position and cruise list. Off: only name, link and line, from the ship list (fast).

## `includeUpcomingCruises` (type: `boolean`):

Adds every upcoming cruise listed on the ship page (date, title, departure port, lowest price, link) to ship rows.

## `ports` (type: `array`):

For 'Port schedule': port names (Miami, Barcelona, Nassau), port ids or port links, one per line. Empty = Miami as an example.

## `month` (type: `string`):

First month of the port schedule, YYYY-MM (2026-12). Empty = the month of 'Departing from', or this month.

## `numberOfMonths` (type: `integer`):

How many months of schedule to read per port, starting from 'First month'.

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

Results per search, ship list or port. Empty = 50 (all ships in 'Live fleet positions'). The old 'max_number_of_pages' (15 cruises per page, -1 = all) is read too.

## `onlyNew` (type: `boolean`):

For scheduled runs. Remembers what each search (filters, not dates) already returned, in a key-value store in your account ('cruisemapper-scraper-state'), and delivers only cruises, ships or port calls not seen before. Already seen results are not delivered and not charged. Delete the store to start over.

## `compareWithPreviousRun` (type: `boolean`):

Compares each cruise's lowest price with your previous runs of the same search and adds is_new, first_seen_at, previous_price_usd, price_change, price_change_pct and is_price_drop. With 'Only new' on too, you get new cruises plus the ones whose price changed.

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

Not needed: CruiseMapper answers without a proxy (tested from datacenter and residential IPs too). Turn on Apify Proxy only if your runs get refused.

## Actor input object example

```json
{
  "mode": "cruises",
  "region": "8",
  "daysAhead": 60,
  "shipType": "any",
  "includeItinerary": true,
  "includeShipDetails": true,
  "includeUpcomingCruises": true,
  "numberOfMonths": 1,
  "maxItems": 50,
  "onlyNew": false,
  "compareWithPreviousRun": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

## `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 = {
    "region": "8",
    "daysAhead": 60,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/cruisemapper-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 = {
    "region": "8",
    "daysAhead": 60,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/cruisemapper-scraper").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 '{
  "region": "8",
  "daysAhead": 60,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scrapewise/cruisemapper-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapewise/cruisemapper-scraper"
        }
    }
}
```

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/KNTOxF9nO2QSwuOfb/builds/kBc0XmUHNePe7e1JT/openapi.json
