vesselapi-python
Python client for the Vessel Tracking API: maritime vessel tracking, port events, emissions, and nautical infrastructure.
Resources: Documentation | API Explorer | Dashboard | Contact Support
Install
pip install vessel-api-python
Requires Python 3.9+.
Quick Start
from vessel_api_python import VesselClient
client = VesselClient(api_key="your-api-key")
# Search for a vessel by name.
result = client.search.vessels(filter_name="Ever Given")
for v in result.vessels or []:
print(f"{v.name} (IMO {v.imo})")
# Get a port by UN/LOCODE.
port = client.ports.get("NLRTM")
print(port.port.name)
# Auto-paginate through port events.
for event in client.port_events.list_all(pagination_limit=10):
print(f"{event.event} at {event.timestamp}")
Async
import asyncio
from vessel_api_python import AsyncVesselClient
async def main():
async with AsyncVesselClient(api_key="your-api-key") as client:
result = await client.search.vessels(filter_name="Ever Given")
async for event in client.port_events.list_all(pagination_limit=10):
print(f"{event.event} at {event.timestamp}")
asyncio.run(main())
Available Services
| Service | Methods | Description |
|---|---|---|
vessels |
get, position, casualties, emissions, eta, positions |
Vessel details, positions, and records |
ports |
get, inbound, inbound_all |
Port lookup by UN/LOCODE and inbound vessels |
port_events |
list, by_port, by_ports, by_vessel, last_by_vessel, by_vessels |
Vessel arrival/departure events |
emissions |
list |
EU MRV emissions data |
search |
vessels, ports, dgps, light_aids, modus, radio_beacons |
Full-text search across entity types |
location |
vessels_bounding_box, vessels_radius, ports_bounding_box, ports_radius, dgps_bounding_box, dgps_radius, light_aids_bounding_box, light_aids_radius, modus_bounding_box, modus_radius, radio_beacons_bounding_box, radio_beacons_radius |
Geo queries by bounding box or radius |
33 methods total, one per API endpoint, plus 28 auto-pagination iterators.
Required Parameters
Parameters the API requires are keyword-only with no default, so leaving one out
raises TypeError at the call instead of returning HTTP 400 from the server:
client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
client.location.vessels_radius(latitude=51.9225) # TypeError: missing longitude, radius
This covers the geo bounds on every location method (lat_min, lat_max,
lon_min, lon_max for bounding boxes; latitude, longitude, radius for
radius queries), filter_name on search.dgps, search.light_aids,
search.modus and search.radio_beacons, filter_port_name on
port_events.by_ports, filter_vessel_name on port_events.by_vessels, and
filter_ids on vessels.positions, along with the matching all_* iterators.
filter_id_type is required by the API but keeps its "imo" default, since the
SDK always sends it.
Vessel Lookup & Location
# Get vessel details by IMO number (defaults to IMO; pass filter_id_type="mmsi" for MMSI).
vessel = client.vessels.get("9811000")
print(f"{vessel.vessel.name} ({vessel.vessel.vessel_type})")
# Get a vessel's latest stored AIS position. A vessel that exists may have no
# stored position, which raises VesselNotFoundError rather than returning empty.
pos = client.vessels.position("232003239", filter_id_type="mmsi")
print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
# filter_sat=True falls back to satellite AIS when no recent terrestrial position is stored.
# ⚠️ Satellite lookups draw on a prepaid balance and are charged per call.
# Omit it unless you need that fallback.
# Find vessels with an AIS position within 10 km of Rotterdam in the last 2 hours
# (the default time window, at most 4 hours).
nearby = client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
for v in nearby.vessels or []:
print(f"{v.vessel_name} at {v.latitude}, {v.longitude}")
Search
search.vessels accepts q, a unified search across IMO, MMSI, ENI, callsign and
name. One value can return several vessels, and _meta.matched_on maps each result's
index to the fields it matched on.
res = client.search.vessels(q="4606770")
print(res.meta.matched_on) # {"0": ["eni"]}
Filters the API declares as repeatable take either one value or a list. A list is sent as a repeated query parameter, so the values are OR-ed:
# ?filter.flag=PA&filter.flag=LR&filter.vesselType=Container%20Ship
client.search.vessels(filter_flag=["PA", "LR"], filter_vessel_type="Container Ship")
client.search.ports(filter_country=["NL", "BE"], filter_size=["LARGE", "MEDIUM"])
These are filter_flag and filter_vessel_type on search.vessels;
filter_country, filter_port_type, filter_size, filter_harbor_size and
filter_harbor_use on search.ports; and filter_ids on vessels.positions,
which also accepts the comma-separated single-string form.
Error Handling
All methods raise specific exception types on non-2xx responses:
from vessel_api_python import VesselAPIError
try:
client.ports.get("ZZZZZ")
except VesselAPIError as err:
if err.is_not_found:
print("Port not found")
elif err.is_rate_limited:
print("Rate limited, backing off")
elif err.is_auth_error:
print("Check API key")
print(err.status_code, err.message)
Auto-Pagination
Every list endpoint has an all_* / list_all variant returning an iterator:
# Sync
for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
print(vessel.name)
# Async
async for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
print(vessel.name)
# Collect every match at once. pagination_limit is the page size, not a total:
# .collect() walks to the end, so this is one request per page until exhausted.
vessels = client.search.all_vessels(filter_vessel_type="Tanker", pagination_limit=50).collect()
# To take a fixed number, stop the iterator yourself.
from itertools import islice
first_50 = list(islice(client.search.all_vessels(filter_vessel_type="Tanker"), 50))
Configuration
client = VesselClient(
api_key="your-api-key",
base_url="https://custom-endpoint.example.com/v1",
timeout=60.0,
max_retries=5, # default: 3
user_agent="my-app/1.0",
)
Retries use exponential backoff with jitter on 429 and 5xx responses. The Retry-After header is respected.
Documentation
- API Documentation: endpoint guides, request/response schemas, and usage examples
- API Explorer: interactive API reference
- Dashboard: manage API keys and monitor usage
Contributing & Support
Found a bug, have a feature request, or need help? You're welcome to open an issue. For API-level bugs and feature requests, please use the main VesselAPI repository.
For security vulnerabilities, do not open a public issue. Email security@vesselapi.com instead. See SECURITY.md.
Data Sources & Attribution
Emissions and casualty data: © European Union. Source: European Maritime Safety Agency (EMSA): THETIS-MRV (EU MRV, Regulation (EU) 2015/757) and the European Marine Casualty Information Platform (EMCIP). Reused under the European Commission reuse notice (Commission Decision 2011/833/EU), which authorises reuse for commercial and non-commercial purposes with acknowledgement of the source. Data may be transformed and combined; EMSA does not endorse this service.
License
Metadata
Release files for vessel-api-python 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vessel_api_python-2.0.1.tar.gz | 26.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vessel_api_python-2.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.5 kB
Release files / vessel_api_python-2.0.1.tar.gz
| Download URL | vessel_api_python-2.0.1.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
79bc5a561594088a1bda617f6e535b7975e44414521be083e74ad74640442f2f
|
|
BLAKE2b-256 checksum How to use checksums |
8cf0adee1fe314adde4a02a513463cac4c0699c24a3a31064af878fa2bd086ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / vessel_api_python-2.0.1-py3-none-any.whl
| Download URL | vessel_api_python-2.0.1-py3-none-any.whl |
|---|---|
| Size | 25.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
261c5db0c36135bc5b347345fcc4f3d8c1cb2177daf51cfa1034a72a0011c04b
|
|
BLAKE2b-256 checksum How to use checksums |
827a49f239c602ee09fe9cc13c4b275936e013b6b977eda8831daed51dff414c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency log