# Evergreen Sailing Schedules: Cut-offs, ETD/ETA & Loops (`arman-bd/evergreen-sailing-schedules-scraper`) Actor

Scrape Evergreen Line point-to-point sailing schedules: service loop, port cut-off, ETD/ETA, transit days, vessel/voyage. Give port names, no login, no browser.

- **URL**: https://apify.com/arman-bd/evergreen-sailing-schedules-scraper.md
- **Developed by:** [Arman Hossain](https://apify.com/arman-bd) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 sailing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Evergreen Sailing Schedules: Cut-offs & ETD/ETA

![Evergreen Sailings: Point to point sailing schedules with transit days, cut-off dates and the service loop](https://api.apify.com/v2/key-value-stores/ZQOcNAOHrIgTacAmy/records/evergreen-sailing-schedules-scraper.jpg)

Pulls Evergreen Line's point-to-point sailing schedules straight from its own booking
site: service loop, port cut-off, estimated departure and arrival, transit days, and
the vessel and voyage working the leg. Give an origin and destination as ordinary port
or city names; Evergreen's own internal location codes (not UN/LOCODEs) are resolved
for you.

**Agent skill: [SKILL.md](https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/evergreen-sailing-schedules-scraper.md)**

```
https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/evergreen-sailing-schedules-scraper.md
```

### What you get

| Field | What it holds |
|---|---|
| `routeRequested` | The route as you wrote it, `"Origin > Destination"` |
| `originCode`, `destinationCode` | Evergreen's own 5-character location codes for the lane |
| `originLabel`, `destinationLabel` | The port name used for the query, upper-cased |
| `recordNo` | Row number in Evergreen's own results table for this search |
| `placeOfReceipt`, `portOfLoading` | Where cargo is received and where it's loaded |
| `portCutOffDate` | Port cut-off date and time for the sailing |
| `service` | The loop/service code, e.g. `FAL3` |
| `portOfDischarge`, `placeOfDelivery` | Where the container is discharged and delivered |
| `transitDays` | Total transit time, in days |
| `departureDate`, `arrivalDate` | ETD at the port of loading, ETA at the port of discharge |
| `vesselVoyage` | Vessel name and voyage number working the leg |
| `vgmHardCopyCutOff`, `vgmEdiCutOff` | VGM cut-off, by hard copy and by EDI/WEB/APP, when Evergreen publishes one |
| `routingDetailSeq` | The sequence ID Evergreen uses for this sailing's full routing detail |
| `remark` | Any remark Evergreen attaches to the sailing, or `null` |
| `searchedDepartureDate`, `durationWeeks` | The date window this record was found in |
| `scrapedAt` | Run timestamp |

`RUN_SUMMARY` in the key-value store holds per-run counts, the filters you used, and
any route that failed to resolve or fetch.

### Use cases

- **Rate quoting.** Pull the next sailings on a lane before quoting a customer, with
  cut-off and transit time in hand.
- **Loop/alliance tracking.** The `service` field names the loop, so runs over time
  build a picture of which vessels rotate through which loop.
- **Multi-carrier schedule comparison.** Evergreen is one of a shrinking number of
  top-10 carriers still reachable this way; join its sailings against other carrier
  Actors on lane and departure week.
- **Cut-off reminders.** Watch `portCutOffDate` and `vgmEdiCutOff` for lanes you book
  often and alert before they pass.
- **Transit-time benchmarking.** Compare `transitDays` across loops on the same lane
  to see which service is actually faster this quarter.

### Quick start

The default lane, the next 4 weeks:

```json
{
 "routes": ["Shanghai > Rotterdam"]
}
```

Several lanes, a wider window, sorted by transit time:

```json
{
 "routes": ["Shanghai > Rotterdam", "Kaohsiung > Los Angeles", "Hamburg > New York"],
 "durationWeeks": 8,
 "sortBy": "TRANSDAY",
 "sortOrder": "ASC"
}
```

A specific departure date, reefer service only:

```json
{
 "routes": ["Shanghai > Rotterdam"],
 "departureDate": "2026-09-15",
 "durationWeeks": 4,
 "reeferCargo": true
}
```

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `routes` | array | `["Shanghai > Rotterdam"]` | One lane per entry, written `"Origin > Destination"` as port or city names. A 5-character Evergreen code works too if you already know it. |
| `departureDate` | string | today | Earliest sailing to include, `YYYY-MM-DD`. Empty means today, on the Actor's server clock. |
| `durationWeeks` | integer | `4` | How many weeks ahead of `departureDate` to search. Clamped to 1-12. |
| `sortBy` | string | `"LINE"` | `LINE` (service loop), `TRANSDAY` (transit time), `POLDEP` (loading departure) or `PODARR` (discharge arrival). |
| `sortOrder` | string | `"ASC"` | `ASC` or `DESC`. |
| `reeferCargo` | boolean | `false` | Restrict to sailings that carry reefer cargo on this lane. |
| `maxSailingsPerRoute` | integer | `50` | Cap on sailings saved, and charged for, per route. Clamped to 1-200. |

Nothing is required. Running with no input returns Shanghai to Rotterdam sailings for
the next 4 weeks.

### Output example

A real record:

```json
{
 "routeRequested": "Shanghai > Rotterdam",
 "originCode": "CNSHG",
 "destinationCode": "NLRDM",
 "originLabel": "SHANGHAI",
 "destinationLabel": "ROTTERDAM",
 "recordNo": 1,
 "placeOfReceipt": "SHANGHAI",
 "portOfLoading": "SHANGHAI",
 "portCutOffDate": "AUG-19-2026 12:00",
 "service": "FAL3",
 "portOfDischarge": "ROTTERDAM",
 "placeOfDelivery": "ROTTERDAM",
 "transitDays": 36,
 "departureDate": "AUG-22-2026",
 "arrivalDate": "SEP-27-2026",
 "vesselVoyage": "CMA CGM JACQUES SAADE 0FMMQW1MA",
 "vgmHardCopyCutOff": null,
 "vgmEdiCutOff": "AUG-18-2026 17:00",
 "routingDetailSeq": 21,
 "remark": null,
 "searchedDepartureDate": "2026-08-22",
 "durationWeeks": 4,
 "scrapedAt": "2026-08-22T09:14:03.187Z"
}
```

Evergreen sails partner-line vessels on its own loops, so `vesselVoyage` naming another
carrier (as above) is expected, not an error, the `service` loop code is Evergreen's.

### Writing a route

`routes` entries read `"Origin > Destination"`:

| You write | Actor resolves to |
|---|---|
| `"Shanghai > Rotterdam"` | `oriLocation=CNSHG`, `desLocation=NLRDM` |
| `"Kaohsiung > Los Angeles"` | `oriLocation=TWKSG`, `desLocation=USLAX` |
| `"CNSHG > NLRDM"` | Used directly, any 5-character token skips the name lookup |

Evergreen's location codes are its own, not UN/LOCODEs: Kaohsiung is `TWKSG`, not
`TWKHH`; Rotterdam is `NLRDM`, not `NLRTM`. A name that Evergreen's own location search
can't match (a typo, or a place it doesn't book) is recorded in `RUN_SUMMARY.failures`
with `stage: "resolve-location"`, and the run continues with whatever routes did
resolve.

### API example

```bash
curl -X POST "https://api.apify.com/v2/acts/arman-bd~evergreen-sailing-schedules-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
 "routes": ["Shanghai > Rotterdam"],
 "durationWeeks": 4
 }'
```

### JavaScript example

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

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/evergreen-sailing-schedules-scraper').call({
 routes: ['Shanghai > Rotterdam', 'Hamburg > New York'],
 durationWeeks: 6,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const s of items) {
 console.log(`${s.routeRequested} · ${s.service} · ${s.vesselVoyage} · ETD ${s.departureDate} → ETA ${s.arrivalDate} (${s.transitDays}d)`);
}
```

### Notes

- Evergreen does not paginate this endpoint: `durationWeeks` is the only window
  control, and every sailing in that window comes back in one page. `maxSailingsPerRoute`
  bounds what's kept and charged for on a busy lane or a wide window.
- A route with no sailings in the window (a self-loop, or a lane Evergreen doesn't
  run) comes back as zero records for that route, not an error. Only a route that
  fails to resolve or fetch lands in `RUN_SUMMARY.failures`.
- Dates and times are kept exactly as Evergreen displays them (`AUG-22-2026`,
  `AUG-18-2026 17:00`), not converted to ISO, since the site's own format is what a
  booking desk expects to match against.
- `vgmHardCopyCutOff` and `vgmEdiCutOff` are `null` on a sailing where Evergreen has
  not published that cut-off yet, which is common further out in the window.
- The same lane listed twice, in any case, is charged once.
- Requests are spaced out between routes and between location look-ups, so a run with
  several routes takes some seconds even though each route itself is a single request.

### FAQ

**Do I need an Evergreen or ShipmentLink account?** No. You supply no credentials.

**Can I use a UN/LOCODE?** No, Evergreen's internal codes are its own scheme and
differ from UN/LOCODEs for some ports (Rotterdam, Kaohsiung, and others). Write the
port name instead and let the Actor resolve it, or pass Evergreen's own code if you
already have it.

**How far ahead can I search?** `durationWeeks` goes up to 12 from `departureDate`.
For a date further in the future than that, set `departureDate` closer to it and run
again.

**Does it fetch the leg-by-leg routing detail (transshipment ports)?** Not the full
per-leg breakdown, `routingDetailSeq` is the ID Evergreen uses for that sub-page, so
you can reference or fetch it yourself if you need the intermediate calls.

**What if a port I search for has multiple matches (e.g. several towns named
"Hamburg")?** The Actor uses Evergreen's own best/first match for the name you gave.
If that's the wrong one, use a more specific name (add the state or country) or pass
Evergreen's 5-character code directly.

**Can I plug it into something else?** Yes. Apify API, the client libraries, webhooks,
scheduled runs, dataset exports to JSON, CSV or Excel, or MCP. The output is
structured JSON.

# Actor input Schema

## `routes` (type: `array`):

Which lanes to pull, one per entry, written as 'Origin > Destination' using port or city names, e.g. 'Shanghai > Rotterdam'. Names are resolved to Evergreen's own internal location codes for you (these are not UN/LOCODEs), or give a 5-character Evergreen code directly if you already know it. A name Evergreen's own location search cannot match is recorded in RUN\_SUMMARY.failures instead of stopping the run.

## `departureDate` (type: `string`):

Earliest sailing to include, as YYYY-MM-DD. Leave empty to start from today, on the Actor's server clock.

## `durationWeeks` (type: `integer`):

How many weeks ahead of 'Departure date' to search. Evergreen has no separate pagination, so this is the only control over how many sailings come back. Clamped to 1-12.

## `sortBy` (type: `string`):

How Evergreen orders the sailings before this Actor reads them: LINE (service loop), TRANSDAY (transit time), POLDEP (port of loading departure date) or PODARR (port of discharge arrival date).

## `sortOrder` (type: `string`):

Ascending or descending for 'Sort by'.

## `reeferCargo` (type: `boolean`):

Restrict results to sailings that carry refrigerated (reefer) cargo on this lane.

## `maxSailingsPerRoute` (type: `integer`):

Cap on sailings saved, and charged for, per route. Evergreen does not paginate this endpoint, so this is what bounds the dataset size on a busy lane or a wide 'Window (weeks)'.

## Actor input object example

```json
{
  "routes": [
    "Shanghai > Rotterdam",
    "Kaohsiung > Los Angeles",
    "Hamburg > New York"
  ],
  "departureDate": "2026-09-01",
  "durationWeeks": 4,
  "sortBy": "LINE",
  "sortOrder": "ASC",
  "reeferCargo": false,
  "maxSailingsPerRoute": 50
}
```

# Actor output Schema

## `items` (type: `string`):

Every sailing the run produced.

## `runsummary` (type: `string`):

The RUN\_SUMMARY record from the run's key-value store.

# 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 = {
    "routes": [
        "Shanghai > Rotterdam"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arman-bd/evergreen-sailing-schedules-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 = { "routes": ["Shanghai > Rotterdam"] }

# Run the Actor and wait for it to finish
run = client.actor("arman-bd/evergreen-sailing-schedules-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 '{
  "routes": [
    "Shanghai > Rotterdam"
  ]
}' |
apify call arman-bd/evergreen-sailing-schedules-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arman-bd/evergreen-sailing-schedules-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/e15N26GhvEZGoxi18/builds/zPHYdEdOiRHSDGr86/openapi.json
