# AIS Vessel Tracking API - Finland & Baltic Ships, Port Calls (`atlasdata/finland-ais-vessel-tracker-reliable`) Actor

AIS vessel tracking: live AIS ship positions, vessel details (IMO, type, destination, ETA, size) and Finnish port calls from the official Fintraffic Digitraffic open API (CC BY 4.0). Northern Baltic Sea, Gulf of Finland and Bothnia. From $0.50 per 1,000 vessels.

- **URL**: https://apify.com/atlasdata/finland-ais-vessel-tracker-reliable.md
- **Developed by:** [Christian Machon](https://apify.com/atlasdata) (community)
- **Categories:** Travel, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 vessel positions

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## AIS Vessel Tracking API - Finland & Baltic Ships, Port Calls

**AIS vessel tracking API for Finnish and northern Baltic waters: live AIS ship positions with vessel details, plus port calls at Finnish ports, as clean JSON.**

Get **live AIS ship positions** with ship details, plus **port calls at Finnish ports**, as clean JSON. The data comes from the official **Fintraffic Digitraffic** open marine API. It covers the northern Baltic Sea, the Gulf of Finland, the Gulf of Bothnia, the Archipelago Sea, the Åland Sea and Lake Saimaa.

- 🚢 **Vessels mode:** the latest AIS position of every vessel the Finnish coastal stations hear. Each record has lat/lon, speed, course, heading and navigational status. It is joined with **name, IMO, call sign, ship type, destination, ETA, draught, length and beam**.
- ⚓ **Port calls mode:** arrivals and departures that ships report to Portnet for Finnish ports (Helsinki, Kotka, HaminaKotka, Turku, Rauma, Oulu, Kokkola, Pori, Hanko, Naantali, Mariehamn and more). Each call includes **ETA/ETD/ATA/ATD**, berth, previous and next port, voyage, crew count, draught and ship agent.
- ✅ **Official, licensed open data** (CC BY 4.0, commercial use allowed). There is no scraping of tracking websites, no login and no proxies.
- ⚡ **Fast and cheap.** A typical run takes 1–3 seconds and makes 1–3 API requests. It costs **$0.50 per 1,000 vessel positions** and **$1 per 1,000 port calls**.

### Use cases

- **AI agents and chatbots:** "Which tankers are moving in the Gulf of Finland right now?" or "When does the Finnsirius arrive in Helsinki?"
- **Logistics and freight forwarding:** watch ETAs of inbound vessels at Finnish ports and see berths and agents.
- **Port and terminal operations:** list expected, arrived and departed calls per port for the next days.
- **Commodity and energy analysts:** count tankers and bulk carriers in the area, and watch draught changes and destinations.
- **Maritime security, insurance and research:** find vessels near a point (an area circle sorted by distance) and check navigational status and position age.

### How it works

1. Choose **mode**: `vessels` or `portCalls`.
2. Add filters. Use MMSI, IMO or vessel name in both modes. In vessels mode you can also set an area circle, ship categories, max position age and moving only. In port calls mode you can set ports, an ETA window and a status.
3. Set **maxItems** and run. You get one dataset item per vessel or per port call. A run summary with the attribution is saved as `OUTPUT` in the key-value store.

The actor calls `meri.digitraffic.fi` politely. It identifies itself with the `Digitraffic-User` header, uses gzip, sends requests one at a time at least 1 s apart, and retries with backoff on errors. Digitraffic caches responses for about one minute, so polling more often than once a minute gives you nothing new.

### Input examples

Vessels within 15 km of Helsinki, nearest first:

```json
{ "mode": "vessels", "latitude": 60.15, "longitude": 24.95, "radiusKm": 15, "maxItems": 25 }
```

Moving tankers and cargo ships anywhere in the coverage area:

```json
{ "mode": "vessels", "shipCategories": ["tanker", "cargo"], "movingOnly": true, "maxAgeMinutes": 30, "maxItems": 50 }
```

Track specific ships:

```json
{ "mode": "vessels", "mmsi": ["230985490", "273121120"], "maxAgeMinutes": 1440 }
```

Port calls at Helsinki and Kotka in the next 3 days:

```json
{ "mode": "portCalls", "ports": ["FIHEL", "FIKTK"], "from": "now", "to": "+3 days", "status": ["expected"], "maxItems": 50 }
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | string | `vessels` | `vessels` or `portCalls` |
| `mmsi` | string\[] | – | 9-digit MMSI numbers (both modes) |
| `imo` | string\[] | – | 7-digit IMO numbers (both modes) |
| `vesselName` | string | – | Case-insensitive partial name match |
| `latitude`, `longitude` | number | – | Centre of an area circle (vessels mode) |
| `radiusKm` | number | 20 | Circle radius, up to 1000 km |
| `shipCategories` | string\[] | all | cargo, tanker, passenger, fishing, tug, pilot, search-and-rescue, law-enforcement, military, dredging, sailing, pleasure, high-speed-craft, towing, service, other, unknown |
| `maxAgeMinutes` | integer | 60 | Only positions newer than this (max 1440) |
| `movingOnly` | boolean | false | Skip vessels slower than 0.5 kn |
| `ports` | string\[] | all | UN/LOCODEs such as FIHEL, FIKTK, FIHMN, FITKU, FIRAU, FIOUL |
| `from`, `to` | string | `-1 day`, `+7 days` | ETA window: ISO dates or relative values (`now`, `+48 hours`, `3 days ago`) |
| `status` | string\[] | all | expected, arrived, departed |
| `maxItems` | integer | 100 | Max records returned and charged (up to 5000) |

### Output examples

A vessel record (vessels mode):

```json
{
  "mmsi": 273121120, "imo": 9439383, "name": "ONIKS", "callSign": "UAFG4",
  "shipType": 80, "shipTypeLabel": "Tanker", "shipCategory": "tanker",
  "latitude": 60.105878, "longitude": 27.436067, "speedKnots": 9.2, "courseDegrees": 237.1, "headingDegrees": 239,
  "rateOfTurn": 0, "navStatus": 0, "navStatusLabel": "under way using engine", "positionAccuracyHigh": true,
  "positionTime": "2026-10-29T19:40:01.157Z", "positionAgeMinutes": 0,
  "destination": "FOR ORDER", "eta": "2026-12-03T08:00:00.000Z", "etaText": "12-03 08:00 UTC",
  "draughtMeters": 15, "lengthMeters": 243, "beamMeters": 42,
  "metadataTime": "2026-10-29T19:35:34.141Z", "hasMetadata": true,
  "source": "Source: Fintraffic / digitraffic.fi, license CC 4.0 BY (https://creativecommons.org/licenses/by/4.0/). Data reformatted by Atlas Data."
}
```

A port call record (port calls mode):

```json
{
  "portCallId": 3408150, "port": "FIKTK", "portName": "Kotka", "portAreaCode": "MUSKU", "portAreaName": "MUSSALO (KUIVA)",
  "berthCode": "A2", "berthName": "MUSA2", "status": "departed",
  "eta": "2026-10-29T04:15:00.000Z", "etd": "2026-10-29T16:30:00.000Z", "ata": "2026-10-29T04:20:00.000Z", "atd": "2026-10-29T14:45:00.000Z",
  "vesselName": "Prima Viking", "imo": 9195810, "mmsi": 230011000, "callSign": "OJOX", "flag": "FI",
  "vesselTypeCode": 70, "vesselType": "dry cargo vessel",
  "prevPort": "PLGDY", "prevPortName": "Gdynia", "nextPort": "NLAMS", "nextPortName": "Amsterdam", "voyage": "Gdynia-Kotka-Amsterdam",
  "crewOnArrival": 9, "arrivalDraughtMeters": 3.8, "departureDraughtMeters": 5.6, "arrivalWithCargo": true,
  "agents": [{ "name": "Prima Logistics Oy Ab Ltd", "role": "ship agent", "direction": "Arrival or whole PortCall" }],
  "updatedAt": "2026-10-29T15:51:25.000Z",
  "source": "Source: Fintraffic / digitraffic.fi, license CC 4.0 BY (https://creativecommons.org/licenses/by/4.0/). Data reformatted by Atlas Data."
}
```

The tables are available as dataset views **Vessel positions** and **Port calls**. Export them as JSON, CSV or Excel, or read them through the API.

### Pricing

Pay per event. You only pay for records you receive.

| Event | Price |
|---|---|
| Actor start | $0.00005 per run |
| Vessel position (vessels mode) | $0.0005 per vessel ($0.50 / 1,000) |
| Port call (port calls mode) | $0.001 per call ($1 / 1,000) |

For example, 25 vessels near a port cost $0.0126, and 20 port calls cost $0.0201. Set a **maximum charge per run** and the actor stops exactly at that limit.

### Data quality notes

- **Coverage** is where Finnish AIS base stations receive signals: roughly latitude 57–66°N and longitude 17–35°E. This is not global AIS.
- **Ship details** come from AIS static messages heard in the last 24 hours. A few vessels have none (`hasMetadata: false`). In that case name, type and size are null.
- **AIS ETA has no year.** `etaText` is the raw value and `eta` is the nearest plausible date. Destination and ETA are typed in by the crew and can be stale.
- **Port call `status`** is derived from the actual times (ATA/ATD). Portnet sometimes carries over old actual times from previous calls. Times more than 30 days away from the planned ETA/ETD are dropped and listed in `dataNotes`.
- Ship masters' names are never output.

### FAQ

**Is this legal to use commercially?** Yes. Fintraffic publishes Digitraffic data under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), which allows commercial use and redistribution with attribution. Every record carries the required attribution in the `source` field. If you republish the data, keep the credit: *"Source: Fintraffic / digitraffic.fi, license CC 4.0 BY"*. See the [Digitraffic terms of service](https://www.digitraffic.fi/en/terms-of-service/). Atlas Data reformats the data (it renames fields, decodes codes, derives status, size and distance). The data is provided as is, without warranty, and is not for navigation.

**Is this MarineTraffic / VesselFinder data?** No. It comes only from the Finnish authority's open API.

**How fresh is it?** Positions are near real time, usually under 1 minute old. The API caches responses for about 1 minute.

**Can I track ships worldwide?** No. Coverage is the Finnish sea area and nearby parts of the Baltic Sea.

**Does it work in AI agents and MCP?** Yes. The input is small and flat, the output is consistent JSON, and runs finish in seconds. It is well suited to the run-sync API and pay-per-call gateways.

# Actor input Schema

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

`vessels`: latest AIS position of each vessel seen by Finnish coastal stations (northern Baltic, Gulf of Finland, Gulf of Bothnia, Archipelago Sea, Saimaa) joined with name, IMO, type, destination, ETA and size. `portCalls`: port calls reported to Portnet for Finnish ports.

## `mmsi` (type: `array`):

Optional. 9-digit MMSI numbers to track (both modes). Up to 200 in vessels mode, 20 in portCalls mode.

## `imo` (type: `array`):

Optional. 7-digit IMO numbers (both modes).

## `vesselName` (type: `string`):

Optional, case-insensitive partial match on the vessel name (e.g. VIKING).

## `latitude` (type: `number`):

Vessels mode. Decimal degrees, e.g. 60.15 for Helsinki. Use with longitude and radius to get only vessels in a circle.

## `longitude` (type: `number`):

Vessels mode. Decimal degrees, e.g. 24.95.

## `radiusKm` (type: `number`):

Vessels mode. Radius of the search circle around the centre point. Results are sorted by distance.

## `shipCategories` (type: `array`):

Vessels mode. Keep only these AIS ship categories. Empty = all.

## `maxAgeMinutes` (type: `integer`):

Vessels mode. Only vessels whose latest position is at most this old (1-1440).

## `movingOnly` (type: `boolean`):

Vessels mode. Skip vessels with speed under 0.5 knots (moored/anchored).

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

PortCalls mode. Finnish port codes, e.g. FIHEL Helsinki, FIKTK Kotka, FIHMN Hamina, FITKU Turku, FIRAU Rauma, FIOUL Oulu, FIKOK Kokkola, FIPOR Pori, FIHKO Hanko, FINLI Naantali, FIMHQ Mariehamn. Empty = all ports.

## `from` (type: `string`):

PortCalls mode. Port calls with ETA on or after this time: 2026-10-29, 2026-10-29T12:00Z, now, today, -1 day, -12 hours.

## `to` (type: `string`):

PortCalls mode. Port calls with ETA before this time: 2026-11-05, tomorrow, +7 days, +48 hours.

## `status` (type: `array`):

PortCalls mode. Keep only calls with this status (derived from actual arrival/departure times). Empty = all.

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

Maximum number of records to return (and be charged for).

## Actor input object example

```json
{
  "mode": "vessels",
  "radiusKm": 20,
  "maxAgeMinutes": 60,
  "movingOnly": false,
  "ports": [
    "FIHEL"
  ],
  "from": "-1 day",
  "to": "+7 days",
  "maxItems": 100
}
```

# Actor output Schema

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

No description

## `vessels` (type: `string`):

No description

## `portCalls` (type: `string`):

No description

## `summary` (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 = {
    "ports": [
        "FIHEL"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("atlasdata/finland-ais-vessel-tracker-reliable").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 = { "ports": ["FIHEL"] }

# Run the Actor and wait for it to finish
run = client.actor("atlasdata/finland-ais-vessel-tracker-reliable").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 '{
  "ports": [
    "FIHEL"
  ]
}' |
apify call atlasdata/finland-ais-vessel-tracker-reliable --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atlasdata/finland-ais-vessel-tracker-reliable"
        }
    }
}
```

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/AM47fT8hrDYyC7gJE/builds/INHhXB9QvDbTF3Fb2/openapi.json
