Moving a chemical cargo safely and on time means your team needs to see where each tanker is right now, where it’s headed, when it will berth, and whether a port is becoming a bottleneck. By the end of this guide you’ll be able to wire up live AIS tracking, fleet-wide snapshots, congestion checks, and CII emissions scoring for chemical tankers using vessels-api.com — with production-ready cURL and Python you can paste into your service today.
Why chemical tanker tracking needs precise, developer-first data
Chemical tankers operate under tight safety, berthing, and product-handling constraints. An hour of delay at anchorage can ripple across discharge windows and shore tank schedules. Developers building transportation systems for these fleets need:
- Live positions and recent tracks, with consistent units (NM, knots) and UTC timestamps.
- Route intelligence: last port, destination, and predicted ETAs where available.
- Operational rollups across multiple MMSIs to drive control-tower dashboards.
- Port congestion snapshots to anticipate anchorage and berth delays.
- Regulatory metrics like IMO CII to support ESG and charter-party reporting.
vessels-api.com provides 18 REST endpoints under one base URL with a single X-API-Key header and a consistent JSON response envelope: {status, success, message, data}. You get global AIS coverage with near real-time refresh rates and endpoints that map cleanly to transportation workflows.
Endpoints we’ll use for chemical tankers
- GET /vessels/track — live position, history, route, predicted ETA, weather.
- POST /vessels/fleet — batch positions/routes for a control-tower view.
- GET /ports/congestion — anchorage/berth snapshot and wait-time statistics.
- GET /vessels/search — find tankers by name, IMO, MMSI, or filters.
- GET /vessels/green — IMO CII scoring for ESG/compliance.
All endpoints live under https://vessels-api.com/api/V1 and use the X-API-Key header for authentication.
Live chemical tanker tracking with /vessels/track
Use this when you need the exact current position of a single tanker, its recent 24–168 hour history, route context (last port, destination), and optional predicted ETA and weather. It’s the building block for arrival boards, shipment pages, and geofencing alerts.
Official cURL you can run now
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Official JSON response (copy-paste)
{
"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:06+00:00",
"age_minutes": 5142140,
"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": null,
"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
}
}
Fields you’ll actually use in chemical tanker flows:
- data.current_position.latitude/longitude — WGS84 coordinates for plotting and geofencing (decimal degrees).
- data.current_position.speed_knots, course_degrees — speed over ground and course (knots, degrees).
- data.current_position.timestamp_utc — ISO 8601 UTC. Normalize your storage to UTC to avoid port-local confusion.
- data.route.departure_port, destination_port — use to correlate with berth windows and pre-advices.
- data.last_port_visits — for vetting and operational history. Times are in UTC; durations are hours.
Parameters that matter
- imo or mmsi — one is required. For tankers, MMSI is often easiest for live tracking.
- hours — 24 by default; up to 168 hours for a 7-day track. Useful to validate speed profiles against charter-party clauses.
- include_route, include_predicted_eta, include_weather — set to true to enrich the response when you need it.
Python example: consume /vessels/track and derive ETA fallback
This script requests the official MMSI track, extracts the last known position, and demonstrates a simple ETA fallback using the route ETA when predicted_eta is null.
import os
import requests
from datetime import datetime, timezone
API_KEY = os.getenv("VESSELS_API_KEY", "YOUR_API_KEY")
URL = "https://vessels-api.com/api/V1/vessels/track"
params = {
"mmsi": "258785000",
"hours": "48"
}
headers = {"X-API-Key": API_KEY}
r = requests.get(URL, headers=headers, params=params, timeout=20)
r.raise_for_status()
resp = r.json()
if not resp.get("success"):
raise SystemExit(f"API error: {resp.get('message')}")
data = resp["data"]
v = data["vessel"]
pos = data.get("current_position", {}) or {}
print(f"MMSI: {v.get('mmsi')} IMO: {v.get('imo')}")
print(f"Lat/Lon: {pos.get('latitude')}, {pos.get('longitude')}")
print(f"Speed: {pos.get('speed_knots')} kn Course: {pos.get('course_degrees')}°")
print(f"Timestamp (UTC): {pos.get('timestamp_utc')}")
# Prefer predicted_eta if available, else route.eta
pred_eta = data.get("predicted_eta")
route = data.get("route", {}) or {}
eta = pred_eta or route.get("eta")
if eta:
print(f"ETA (UTC): {eta}")
else:
print("ETA: unavailable")
# Example: age sanity check for alerting
age_min = pos.get("age_minutes")
if age_min is not None and age_min > 60:
print(f"Warning: AIS position older than 60 minutes (age: {age_min} min)")
Implementation notes:
- Always check success and handle message for actionable errors.
- Use timeout and backoff where appropriate; 429 indicates rate limit exceeded.
- All times are UTC. Convert to port-local only for UI rendering.
Fleet control tower for chemical tankers with /vessels/fleet
When coordinating multiple chemical tankers, calling /vessels/track per ship adds latency. Use the batch endpoint to pull positions and routes for many hulls in a single request. This drives fleet maps, exception dashboards, and daily situation reports.
cURL: batch two vessels
What to expect in the response:
- data.fleet — summary counts: total_vessels, vessels_at_sea, vessels_in_port.
- data.vessels[] — each record includes imo, mmsi, name, position, and optionally route.
Tips for fleet dashboards:
- Cache for 30–90 seconds to smooth map redraws without losing operational fidelity.
- Highlight exceptions: position.age_minutes >= threshold, speed_knots = 0 while near anchorage polygon, or ETA slipping vs laycan.
- Persist route.departure_port/destination_port to power filters like “bound to ARBUE.”
Port congestion to protect berth windows
Anchorage buildup can jeopardize product integrity and terminal slots for chemical tankers. The congestion endpoint gives you a 24h/3d/7d snapshot with wait-time statistics so ops can adjust speed, fuel plans, or nominate alternates early.
cURL: real-time congestion snapshot
Response highlights you’ll use:
- data.snapshot.vessels_in_anchorage, data.snapshot.vessels_at_berth — current load indicators.
- data.statistics.avg_wait_time_hours_last_7d, max_wait_time_hours_last_7d — planning inputs for speed/ETA margins.
- data.statistics.port_calls_count — demand proxy.
Combine this with /vessels/nearby around terminal coordinates to isolate chemical tankers within a fixed NM radius if you want a commodity-specific cut of the anchorage.
Find and validate chemical tankers with /vessels/search
Start by normalizing identifiers from manifests and fixtures. Search supports fuzzy name matches, IMO, MMSI, and filters like ship_type, flag, deadweight, and build year.
cURL: fuzzy name + flag filter
Response structure:
- data.vessels[] — each item includes imo, mmsi, name, flag, vessel_type, gross_tonnage, deadweight_tonnage, year_built, length_m, width_m.
- data.pagination — current_page, per_page, total, last_page. Iterate until current_page == last_page.
Tips:
- Persist MMSI/IMO pairs after the first search and query by identifier going forward.
- Set per_page up to 100 to minimize pagination overhead for backfills.
ESG and compliance for chemical tankers with /vessels/green
For emissions reporting and chartering considerations, pull the IMO CII score and underlying distance/emission estimates over standard periods.
cURL: 30-day CII
Key fields:
- data.estimated_emissions.co2_tons, co2_per_nm — absolute and intensity metrics.
- data.cii.score, data.cii.rating — rating A (best) → E (worst), with data.cii.year and regulation_reference.
- data.distance_nm — distance basis for the estimate; reconcile with voyage plans for accuracy checks.
Build an end-to-end chemical tanker workflow
1) Normalize hull IDs
Use /vessels/search to find the exact tanker by fuzzy name from a fixture sheet. Persist IMO and MMSI pairs in your DB.
2) Power the control tower
Query /vessels/fleet every 30–60 seconds with include_positions to render the map and status widgets. Use position.age_minutes to gray out stale targets.
3) Predict schedule risk
For each active voyage, call /vessels/track with hours=48 and include_route. If predicted_eta is present, compare it to terminal windows. If missing, fall back to route.eta and your own model. Flag slippage.
4) Watch chokepoints
Call /ports/congestion daily for your top discharge/load ports. If avg_wait_time_hours_last_7d is trending up, raise early warnings and adjust speed to manage fuel and arrival time.
5) Report emissions
Pull /vessels/green for the last 30d and 1y. Archive score, rating, and inputs to support audits and sustainability dashboards.
JavaScript fetch example: fleet snapshot for a dashboard widget
async function fetchFleetSnapshot() {
const res = await fetch("https://vessels-api.com/api/V1/vessels/fleet", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
vessels: [{ mmsi: "258785000" }, { imo: "9122556" }],
include_positions: true,
include_routes: true
})
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const json = await res.json();
if (!json.success) throw new Error(json.message);
const { fleet, vessels } = json.data;
console.log(`Fleet: ${fleet.total_vessels} total, ${fleet.vessels_at_sea} at sea`);
// Example: compute how many are within 10 NM of destination
const closeToDest = vessels.filter(v => {
const pos = v.position || {};
const dest = (v.route || {}).destination_port;
return Boolean(pos.latitude && pos.longitude && dest); // replace with your distance check
});
console.log(`Approaching destination: ${closeToDest.length}`);
}
fetchFleetSnapshot().catch(console.error);
Operational details that save time
- Authentication: add X-API-Key: YOUR_API_KEY to every request; no OAuth or per-endpoint differences.
- Response envelope: always parse status, success, message, then data.
- Units: distances are nautical miles (nm); speeds are knots; all timestamps are UTC ISO 8601.
- History: /vessels/track hours max is 168 (7 days). Default is 24.
- Pagination: /vessels/search supports per_page up to 100. Use data.pagination to iterate.
- Error handling: 400 missing/invalid parameter; 401 invalid/missing key; 404 not found; 422 out of range; 429 rate limit; 500 server error.
- Caching: cache control-tower reads for ~30–90 seconds; use longer cache for /vessels/green unless a voyage just ended.
Port intelligence add-ons for chemical tankers
Round out your transportation stack with these optional lookups when you need more context:
- GET /ports — list of 248 ports with identifiers and coordinates; seed your UI dropdowns and geofences.
- GET /ports/data — live vessel counts in a specific port for quick reality checks.
- GET /port/expected-arrivals — use to pre-allocate terminal resources for inbound chemical tankers.
For complete parameter references, see the Documentation. To explore endpoints interactively, try the MCP.
Security and data hygiene for transportation systems
- Key management: store your X-API-Key in your secrets manager; never ship it in mobile builds.
- Input validation: accept either IMO or MMSI per request; don’t forward both unless your logic requires redundancy.
- Staleness checks: use current_position.age_minutes to prevent acting on old AIS messages.
- Graceful degradation: if predicted_eta is null, fall back to route.eta or your own ETA function.
- Idempotency on batch updates: persist last-seen timestamp_utc per MMSI to avoid regressing map markers.
FAQ
Q: Can I track multiple chemical tankers in one call?
A: Yes. Use POST /vessels/fleet with a vessels array of IMO/MMSI objects. Set include_positions and include_routes to enrich each record.
Q: What timezone do timestamps use?
A: All timestamps are UTC in ISO 8601 format. Convert to display-timezone in the UI, but keep storage and comparisons in UTC.
Q: How far back can I fetch position history?
A: /vessels/track supports the hours parameter up to 168 (7 days). The default is 24 hours.
Q: How do I filter for chemical tankers only?
A: Use GET /vessels/search with ship_type=Chemical%20Tanker. You can combine with flag, DWT ranges, and build years.
Q: How is the CII rating represented?
A: GET /vessels/green returns data.cii.score and data.cii.rating (A to E), plus year and regulation_reference (IMO MEPC.339(76)).
Ready to add reliable chemical tanker tracking to your transportation stack? Start building in minutes with a single API key and consistent JSON across endpoints. Register, read the Documentation, and explore interactively in the MCP.


