Singapore Port Statistics Scraper: MPA Throughput & Vessel Data avatar

Singapore Port Statistics Scraper: MPA Throughput & Vessel Data

Pricing

from $1.20 / 1,000 port statistic scrapeds

Go to Apify Store
Singapore Port Statistics Scraper: MPA Throughput & Vessel Data

Singapore Port Statistics Scraper: MPA Throughput & Vessel Data

Scrape monthly container throughput, vessel arrivals and shipping tonnage for the Port of Singapore from MPA's open data on data.gov.sg, back to 1995.

Pricing

from $1.20 / 1,000 port statistic scrapeds

Rating

0.0

(0)

Developer

Arman Hossain

Arman Hossain

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Singapore Port Statistics: Monthly container throughput, vessel arrivals and gross tonnage from the official open data API

Pulls the Maritime and Port Authority of Singapore's monthly port statistics from Singapore's official open data portal: container throughput, vessel arrivals (total and broken down by vessel type), and Singapore Registry of Ships tonnage. The series run monthly back to 1995 for the Port of Singapore, the world's second-largest container port and its largest bunkering port.

This Actor needs no browser, no proxy and no login to run. Point it at one or more of the four built-in series, or at any other data.gov.sg CKAN table by resource id, and it returns clean, typed rows.

Agent skill: SKILL.md

https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/singapore-port-statistics-scraper.md

What you get

FieldWhat it holds
datasetWhich series the row came from: container_throughput, vessel_arrivals_total, vessel_arrivals_by_type, registered_vessels_tonnage, or a custom resource id
datasetLabelHuman-readable name for the series (Custom for a caller-supplied resource id)
resourceIdThe underlying data.gov.sg resource id this row came from
idThe source's own row id, stable across runs
monthThe reporting month, YYYY-MM
vesselTypeVessel category (e.g. Container, Tanker, Tug); only set on vessel_arrivals_by_type rows, otherwise null
containerThroughputThousandTeuContainer throughput for the month, in thousand TEUs; only set on container_throughput rows
numberOfVesselsVessel count for the month; set on every series except container_throughput
grossTonnageThousandGtGross tonnage for the month, in thousand GT; set on every series except container_throughput
scrapedAtRun timestamp

RUN_SUMMARY in the key-value store holds per-dataset row counts, the totals available at the source, the filters you used, and any dataset that failed to fetch.

Use cases

  • Trade and transhipment analysis. Container throughput is a standard proxy for Asia-Pacific trade flow and transhipment activity.
  • Port-equity and comparables research. Feed PSA Singapore volumes into a comparables model against other major container ports.
  • Bunker and commodity desks. Vessel arrival counts and gross tonnage track activity at the world's largest bunkering port.
  • Macro dashboards. A monthly, decades-long series with no gaps back to 1995 for trade-cycle and shipping-cycle tracking.
  • Fleet and registry research. Singapore Registry of Ships counts and tonnage for flag-state and maritime-registry studies.

Quick start

Every built-in series, full history:

{}

Just container throughput, capped to the most recent 24 months:

{
"datasets": ["container_throughput"],
"maxRecordsPerDataset": 24
}

A specific window across two series:

{
"datasets": ["container_throughput", "vessel_arrivals_total"],
"fromMonth": "2015-01",
"toMonth": "2024-12"
}

Input

FieldTypeDefaultNotes
datasetsarrayall fourWhich built-in series to pull: container_throughput, vessel_arrivals_total, vessel_arrivals_by_type, registered_vessels_tonnage. An empty list means all four.
resourceIdsarray[]Any other data.gov.sg CKAN resource id (the d_... string from a dataset's API panel), read the same way and labelled Custom.
fromMonthstringnoneEarliest month to keep, YYYY-MM. Applied after fetching, since the source has no date-range parameter.
toMonthstringnoneLatest month to keep, YYYY-MM.
maxRecordsPerDatasetinteger0 (no limit)Cap rows saved per dataset, keeping the most recent months first when the cap is smaller than the full series.

Nothing is required. Running with no input returns the full history of all four series, about 4,100 rows in total.

Output example

A container throughput record:

{
"dataset": "container_throughput",
"datasetLabel": "Container throughput",
"resourceId": "d_da030f7028200d19ffcbe4a2d71af39c",
"id": 377,
"month": "2026-05",
"vesselType": null,
"containerThroughputThousandTeu": 3942.74,
"numberOfVessels": null,
"grossTonnageThousandGt": null,
"scrapedAt": "2026-08-21T22:47:54.897Z"
}

A vessel-arrivals-by-type record, same shape, different fields populated:

{
"dataset": "vessel_arrivals_by_type",
"datasetLabel": "Vessel arrivals, by vessel type",
"resourceId": "d_8f264219109e61fffa87ac64dd5a9a65",
"id": 3016,
"month": "2026-05",
"vesselType": "Miscellaneous",
"containerThroughputThousandTeu": null,
"numberOfVessels": 883,
"grossTonnageThousandGt": 13723.56,
"scrapedAt": "2026-08-21T22:47:54.897Z"
}

Reading a dataset key

datasets valueSeries
container_throughputMonthly container throughput, thousand TEUs
vessel_arrivals_totalMonthly vessel arrivals: count and total gross tonnage
vessel_arrivals_by_typeThe same arrivals, broken down into several rows per month by vessel type
registered_vessels_tonnageSingapore Registry of Ships: monthly registered ship count and gross tonnage

vessel_arrivals_by_type carries roughly 8 rows per month (one per vessel category), so its total row count is much larger than the other three series, which are one row per month.

API example

curl -X POST "https://api.apify.com/v2/acts/arman-bd~singapore-port-statistics-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"datasets": ["container_throughput"],
"fromMonth": "2015-01"
}'

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('arman-bd/singapore-port-statistics-scraper').call({
datasets: ['container_throughput', 'vessel_arrivals_total'],
fromMonth: '2020-01',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) console.log(row.month, row.dataset, row.containerThroughputThousandTeu ?? row.numberOfVessels);

Notes

  • Numbers arrive from the source as strings and are cast to numbers here; a value the Actor cannot parse comes through as null rather than a bad number.
  • container_throughput, vessel_arrivals_total and registered_vessels_tonnage are one row per month. vessel_arrivals_by_type is several rows per month, one per vessel category, so maxRecordsPerDataset caps rows, not months, on that series.
  • Datasets are read one at a time with a short delay between them, and a failed fetch is retried automatically before it is recorded as a failure.
  • month has no timezone; it is the calendar month MPA published the figures for, not a timestamp.
  • The latest month available typically lags the calendar by 2-3 months, since MPA needs time to finalise the figures.
  • One bad dataset key or resource id is recorded in RUN_SUMMARY.failures while the rest of the run continues. The run only fails outright if every requested dataset failed.

FAQ

Do I need an API key? No. The Actor supplies no credentials and needs none.

Can I get daily or weekly figures? No. MPA publishes these series monthly; there is no finer granularity at the source.

Why is containerThroughputThousandTeu null on most rows? Each series has its own metric. Container throughput only appears on container_throughput rows; vessel counts and tonnage appear on the other three.

What does "thousand TEU" and "thousand GT" mean? Thousand twenty-foot equivalent units (the standard container-volume measure) and thousand gross tons (a vessel-size measure), which is how MPA reports these figures.

Can I pull a table this Actor doesn't already know about? Yes, if it is a data.gov.sg CKAN datastore resource: pass its resource id in resourceIds. Field names vary by table, so only fields matching the four built-in series' conventions (month, container_throughput, number_of_vessels, gross_tonnage, vessel_type) are recognised; anything else comes through as null.

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.