Skip to main content

vesselapi-python

CI PyPI Python License: MIT

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.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

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

MIT

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)

Source distribution for vessel-api-python 2.0.1
File Size Uploaded
vessel_api_python-2.0.1.tar.gz 26.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vessel-api-python 2.0.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

2.0.1 This release

2 release files

2.0.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page