You need reliable oil tanker positions, voyage context, and ETAs you can wire straight into dispatch boards, demurrage workflows, and ESG reports. By the end of this guide, you’ll be able to track a single tanker in real time, monitor a fleet, surface port congestion risk, and compute IMO CII ratings using the Vessels API.
Why developers track oil tankers with Vessels API
Oil tanker operations live and die by timely AIS data and unambiguous fields. Vessels API provides:
- 18 REST endpoints that cover search, live tracking, fleet ops, port intelligence, CII emissions, and a premium real-time AIS feed.
- One API key, one base URL, no OAuth: X-API-Key header to authenticate every request.
- A consistent JSON envelope on every response: {status, success, message, data}.
- Global AIS coverage with near real-time refresh.
- A 7-day free trial that scales from indie projects to enterprise fleets.
Base URL: https://vessels-api.com/api/V1. Authentication: X-API-Key: YOUR_API_KEY.
Core endpoints for oil tanker tracking
- GET /vessels/track — live AIS fix, up to 168 hours of history, active route, predicted ETA, and recent port calls.
- POST /vessels/fleet — batch positions and routes for multiple tankers in one request.
- GET /vessels/analytics — voyage statistics like total distance, speed profile, and port-call counts.
- GET /ports/congestion — real-time congestion snapshot and wait-time stats for a given port.
- GET /port/expected-arrivals — upcoming arrivals with ETAs and origin ports.
Live AIS: track a single oil tanker
Use GET /vessels/track when you need the latest fix on a tanker, plus optional route context and predicted ETA. You can query by IMO or MMSI. Time ranges up to 168 hours are supported via the hours parameter.
Official sample: track MMSI 258785000 (48 hours)
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
{
"status": 200,
"success": true,
"message": "OK",
"data": {
"vessel": {
"imo": "9122556",
"mmsi": "258785000",
"name": null
},
"current_position": {
"latitude": 53.33708,
"longitude": 7.17993,
"speed_knots": 0,
"course_degrees": 212,
"heading_degrees": null,
"navigational_status": 5,
"timestamp_utc": "2017-01-24T04:07:59+00:00",
"age_minutes": 5123360,
"destination": null,
"eta": null
},
"predicted_eta": null,
"position_history": [],
"route": {
"departure_port": "HERACLIO",
"departure_time": "2026-04-27T21:35:36+00:00",
"destination_port": "HERACLIO",
"eta": "2026-04-30T09:00:00+00:00",
"distance_nm": null,
"avg_speed_knots": 17.1
},
"last_port_visits": [
{
"port_id": "156",
"port_name": "EMDEN",
"arrival_time": "2026-07-30T13:00:10+00:00",
"departure_time": null,
"duration_hours": null
},
{
"port_id": "10",
"port_name": "HERACLIO",
"arrival_time": "2026-04-20T12:00:00+00:00",
"departure_time": "2026-04-23T08:00:00+00:00",
"duration_hours": 68
}
],
"weather": null
}
}
Key fields you’ll typically bind into a dashboard:
- data.current_position.latitude, longitude — float degrees; plot as a point on your map.
- speed_knots, course_degrees, heading_degrees — speed and course over ground in knots/degrees.
- navigational_status — integer AIS nav status (e.g., 5 is moored). Use it to flag laden vs. idle risks.
- timestamp_utc — ISO 8601 UTC. Use it to age your fix and backfill stale positions.
- route.departure_port, route.destination_port, route.eta — string IDs/labels for voyage context and ETA.
- last_port_visits[] — helps infer ballast/laden cycles and customs windows.
Python: get a tanker’s live fix and route
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://vessels-api.com/api/V1"
params = {
"mmsi": "258785000",
"hours": 48,
"include_route": "true",
"include_predicted_eta": "true",
"include_weather": "false"
}
resp = requests.get(f"{BASE}/vessels/track", headers={"X-API-Key": API_KEY}, params=params, timeout=20)
resp.raise_for_status()
payload = resp.json() # consistent envelope: {status, success, message, data}
data = payload["data"]
pos = data["current_position"]
vessel = data["vessel"]
route = data.get("route") or {}
pred_eta = data.get("predicted_eta")
print({
"imo": vessel.get("imo"),
"mmsi": vessel.get("mmsi"),
"lat": pos.get("latitude"),
"lon": pos.get("longitude"),
"speed_kn": pos.get("speed_knots"),
"course_deg": pos.get("course_degrees"),
"nav_status": pos.get("navigational_status"),
"fix_time_utc": pos.get("timestamp_utc"),
"destination": pos.get("destination") or route.get("destination_port"),
"eta": pos.get("eta") or (pred_eta or route or {}).get("eta")
})
Notes:
- Units are in nautical miles and knots where applicable.
- Timestamps are UTC; store as UTC and convert on the client if needed.
- position_history is empty in the sample; when present, it’s a list of historical fixes within hours.
Fleet operations: monitor multiple oil tankers in one call
POST /vessels/fleet lets you request multiple tankers’ positions and routes in a single request. This is ideal for control towers that refresh a wallboard at fixed intervals.
cURL: batch two tankers with positions
Response highlights you’ll use:
- data.fleet — high-level counters (total_vessels, vessels_at_sea, vessels_in_port).
- data.vessels[] — per-vessel objects with imo, mmsi, name, position, route.
JavaScript: render a fleet ticker
async function fetchFleet() {
const url = "https://vessels-api.com/api/V1/vessels/fleet";
const body = {
vessels: [{ imo: "9122556" }, { mmsi: "309374000" }],
include_positions: true,
include_routes: true
};
const res = await fetch(url, {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify(body)
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const payload = await res.json(); // {status, success, message, data}
const { fleet, vessels } = payload.data;
console.log(`Fleet: ${fleet.total_vessels} vessels; at sea: ${fleet.vessels_at_sea}; in port: ${fleet.vessels_in_port}`);
for (const v of vessels) {
const p = v.position || {};
console.log(`${v.name || v.imo || v.mmsi}: ${p.latitude?.toFixed(4)}, ${p.longitude?.toFixed(4)} @ ${p.speed_knots || 0} kn`);
}
}
fetchFleet().catch(console.error);
Voyage analytics: utilization and port-call trends
GET /vessels/analytics aggregates voyage statistics for a single tanker, a port, or a fleet. For oil tankers, the vessel mode helps you quantify ballast vs. laden distance and port-call cadence over recent windows.
cURL: 7-day analytics for a tanker by MMSI
Response fields to wire into KPI tiles:
- data.statistics.total_distance_nm — total nautical miles sailed in the period.
- avg_speed_knots and max_speed_knots — distribution of speeds for operational profiles.
- port_calls_count and total_time_in_port_hours — port intensity and potential demurrage triggers.
- ports_visited — list of ports in the window; filter for crude export vs. refinery terminals.
Port intelligence: congestion and expected arrivals
Oil tankers are highly sensitive to anchorage queues and berth availability. Two endpoints give you forward- and now-casts:
- GET /ports/congestion — pass a port_id (UNLOCODE in title parentheses, e.g., ARBUE) and optional period (24h, 3d, 7d). The response returns a snapshot (vessels_in_anchorage, vessels_at_berth) and statistics (e.g., avg_wait_time_hours_last_7d).
- GET /port/expected-arrivals — shows upcoming arrivals with ETA and origin; bind this to scheduling boards and STS planning.
cURL: congestion snapshot for Buenos Aires (ARBUE)
When you draw port dashboards, use:
- data.snapshot.vessels_in_anchorage and vessels_at_berth — headline congestion signal.
- data.statistics.avg_wait_time_hours_last_7d — leading indicator for demurrage exposure.
- data.statistics.port_calls_count — operational throughput to calibrate planner expectations.
cURL: expected arrivals for scheduling
Map the fields as follows:
- expected_arrivals[].mmsi/imo/name — ship identity for matching against nominations.
- vessel_type — filter for crude vs. product tankers in multi-commodity workflows.
- eta — ISO 8601 UTC ETA; consider showing both API ETA and your own model if available.
- departure_port — origin context for customs and layday logic.
ESG and compliance: compute CII for oil tankers
GET /vessels/green provides an IMO CII emissions snapshot that you can drop into ESG dashboards or compliance reporting. Ratings follow IMO MEPC.339(76) with A (best) → E (worst).
cURL: 30-day CII for a tanker
Response mapping:
- data.estimated_emissions.co2_tons and co2_per_nm — totals and intensity figures for trend charts.
- data.cii.score and rating — bind directly into color-coded widgets.
- period and year — ensure the reporting window matches your compliance cycle.
Implementation notes that save time
- Authentication: pass X-API-Key: YOUR_API_KEY on every call. No OAuth rotation required.
- Envelope: every response includes {status, success, message, data}. Always check success and fall back to message on error.
- Units and time: distances are nautical miles; speeds in knots; timestamps are UTC ISO 8601.
- Pagination: search endpoints return a pagination block; page and per_page are supported (per_page up to 100).
- Backoff: honor 429 (Rate limit exceeded). Implement exponential backoff or queue refreshes where you poll every N seconds.
- Bounds: /vessels/track supports hours up to 168. /vessels/nearby radius defaults to 50 NM and caps at 200 NM.
- Errors: common statuses — 400 (parameter), 401 (auth), 404 (not found), 422 (out of range), 500 (server).
Putting it together: a tanker operations flow
- Identify vessels of interest via GET /vessels/search (filter by ship_type and flag if needed).
- Pin live positions via GET /vessels/track; persist the latest fix and route for context.
- Batch-refresh wallboards via POST /vessels/fleet on an interval (e.g., every 60–120 seconds).
- Alert on port risk using GET /ports/congestion. If anchorage rises or avg_wait_time spikes, notify stakeholders.
- Forecast port timing with GET /port/expected-arrivals; reconcile with terminal nominations.
- Report emissions monthly via GET /vessels/green; surface rating deltas A→E for compliance teams.
- Summarize utilization through GET /vessels/analytics for weekly performance recaps.
Links you’ll need
FAQ
How fresh is the AIS data?
Coverage is global with near real-time refresh. Always check data.current_position.timestamp_utc and age it on the client to handle stale fixes.
Should I use IMO or MMSI for tanker tracking?
Both are supported. MMSI is tied to the radio; IMO is vessel-identity stable across equipment changes. For ongoing systems, store both and prefer IMO as the canonical key.
What does navigational_status mean on /vessels/track?
It’s the AIS nav status integer (e.g., 5 for moored). Use it to infer in-port vs. underway and to improve demurrage logic alongside speed_knots.
Can I pull multiple tankers in one call?
Yes. Use POST /vessels/fleet with a vessels array of {imo} and/or {mmsi}, and set include_positions/include_routes as needed.
How do I detect congestion changes at a port?
Poll GET /ports/congestion with a stable period (e.g., 24h). Diff snapshot.vessels_in_anchorage and statistics.avg_wait_time_hours_last_7d between polls and alert on thresholds.
Ready to wire oil tanker tracking into your stack? Start with the official Documentation, explore live methods in the MCP, and get your key via Register. With a single API key and consistent responses, you can ship a production-grade tanker dashboard in an afternoon.

