Developer documentation

Build with AIS Stream

Connect, subscribe, operate reliably, and inspect every serialized AIS message model from one workspace.

wss://stream.aisstream.io/v0/stream

01 · Start

Open your first stream

Create a WebSocket connection with permessage-deflate, then send one complete JSON subscription within three seconds. The API key belongs in a server-side environment variable. Check SubscriptionConfirmation.Message.CompressionEnabled to confirm that compression was negotiated.

JavaScript
const WebSocket = require("ws");
const socket = new WebSocket("wss://stream.aisstream.io/v0/stream", {
  perMessageDeflate: true
});

socket.on("open", () => socket.send(JSON.stringify({
  APIKey: process.env.AISSTREAM_API_KEY,
  BoundingBoxes: [[[25.835, -80.208], [25.603, -79.879]]],
  FilterMessageTypes: ["PositionReport"]
})));

socket.on("message", data => console.log(JSON.parse(data.toString())));

02 · Authenticate

Keep credentials on your backend

Use WSS and server-side secrets. Create and rotate keys from Account. Existing keys are masked; a newly generated key is shown once. Disable a key before permanently deleting it. Direct browser connections are not permitted; proxy only the information your clients need from your own server.

03 · Subscribe

Select the area or vessels you want to track

Bounding boxes are required. MMSI and message-type filters are optional. Resending a subscription replaces the active configuration. Each accepted subscription or replacement returns a SubscriptionConfirmation; invalid subscriptions do not.

FieldRequiredMeaning
APIKeyYesAccount API key
BoundingBoxesYesPairs of latitude/longitude corners
FiltersShipMMSINoUp to 200 nine-character MMSIs
FilterMessageTypesNoSupported message type names
Subscription · JSON
{
  "APIKey": "<YOUR_API_KEY>",
  "BoundingBoxes": [
    [
      [
        25.835,
        -80.208
      ],
      [
        25.603,
        -79.879
      ]
    ]
  ],
  "FiltersShipMMSI": [
    "368207620"
  ],
  "FilterMessageTypes": [
    "PositionReport"
  ]
}
Supported message types (25)
PositionReportUnknownMessageAddressedSafetyMessageAddressedBinaryMessageAidsToNavigationReportAssignedModeCommandBaseStationReportBinaryAcknowledgeBinaryBroadcastMessageChannelManagementCoordinatedUTCInquiryDataLinkManagementMessageDataLinkManagementMessageDataExtendedClassBPositionReportGroupAssignmentCommandGnssBroadcastBinaryMessageInterrogationLongRangeAisBroadcastMessageMultiSlotBinaryMessageSafetyBroadcastMessageShipStaticDataSingleSlotBinaryMessageStandardClassBPositionReportStandardSearchAndRescueAircraftReportStaticDataReport

04 · Consume

Monitor messages and connection status

MessageType selects the typed object under Message. MetaData contains normalized AIS context such as MMSI and last known position. A subscription confirmation has no AIS metadata; its CompressionEnabled value reports whether permessage-deflate was negotiated for that connection. The server sends binary WebSocket frames containing UTF-8 JSON.

Position report · JSON
{
  "MessageType": "PositionReport",
  "MetaData": {
    "MMSI": 368207620,
    "ShipName": "EXAMPLE VESSEL",
    "Latitude": 25.7617,
    "Longitude": -80.1918
  },
  "Message": {
    "PositionReport": {
      "MessageID": 1,
      "UserID": 368207620,
      "Sog": 12.4,
      "Cog": 86.7,
      "TrueHeading": 87,
      "Valid": true
    }
  }
}
Subscription confirmation · JSON
{
  "MessageType": "SubscriptionConfirmation",
  "Message": {
    "CompressionEnabled": true
  }
}

05 · Operate

Limits and operational considerations

These limits come directly from the stream service. Build reconnects and observability around them.

ConstraintLimitConsideration
Connections per account3 subscribed connectionsA fourth subscription is rejected.
Connections per originating IP3 open connectionsThe limit applies before authentication.
Initial subscriptionWithin 3 secondsThe connection closes if no valid subscription arrives.
Subscription updates1 per second per connectionA faster update closes the connection. Updates replace, rather than merge with, the previous subscription.
MMSI filters200 per subscriptionEach MMSI must be a nine-character string.
Connection speedRead continuouslyIf you do not consume messages quickly enough and sufficient buffered messages accumulate, the service drops messages.

Uncompressed connections

Beginning in September 2026, uncompressed connections will be subject to per-user bandwidth limits, and messages exceeding those limits will be dropped.

Why are messages slow or missing?+

AIS messages are event-driven rather than emitted on a fixed schedule. Your filters, current vessel activity, upstream source interruptions, network latency, and client processing speed all affect what you observe. If you do not consume messages quickly enough and sufficient buffered messages accumulate, the service drops messages.

How should I handle reconnects?+

Treat the stream as a long-lived but fallible connection. Reconnect with exponential backoff and jitter, then send a complete replacement subscription within three seconds.

Why did my connection close?+

Common causes are a late or malformed subscription, an invalid key, a connection-limit breach, subscription updates faster than once per second, fragmented client messages, missed keepalive activity, or a slow connection.

What WebSocket framing should I expect?+

The service sends binary WebSocket frames whose payload is UTF-8 JSON. Decode the frame bytes before parsing JSON. Client subscription frames may be text or binary, but fragmented messages are not supported.

How can I use fewer bytes?+

Apply MMSI and message-type filters, keep geographic bounding boxes focused on your application, and enable permessage-deflate. Numeric JSON values are emitted without unnecessary trailing zeroes.

Are direct browser connections allowed?+

No. Direct browser connections are not permitted. Connect from your own server and proxy only the information each client needs. This protects the API key and reduces load on the stream service.

What uptime or delivery guarantees are provided?+

The service currently provides no SLA or uptime guarantee, and events are not durably replayed. Plan for interruptions, reconnect with backoff, and persist messages your application cannot afford to lose.

06 · Reference

AIS message schema explorer

28 models

Position

PositionReport

FieldTypeRequiredDescription
MessageIDintegerYesNumeric AIS message identifier.
RepeatIndicatorintegerYesNumber of times the AIS message was repeated.
UserIDintegerYesVessel or station MMSI.
ValidbooleanYesWhether the decoded value passed validation.
NavigationalStatusintegerYesReported navigation status code.
RateOfTurnintegerYesReported rate-of-turn value.
Sognumber<double>YesSpeed over ground in knots.
PositionAccuracybooleanYesReported position-accuracy flag.
Longitudenumber<double>YesLongitude in decimal degrees.
Latitudenumber<double>YesLatitude in decimal degrees.
Cognumber<double>YesCourse over ground in degrees.
TrueHeadingintegerYesTrue heading in degrees.
TimestampintegerYesAIS UTC-second timestamp.
SpecialManoeuvreIndicatorintegerYesAIS SpecialManoeuvreIndicator field.
RaimbooleanYesReceiver autonomous integrity monitoring flag.
PositionReport · schema-shaped JSON
{
  "MessageID": 1,
  "RepeatIndicator": 1,
  "UserID": 1,
  "Valid": true,
  "NavigationalStatus": 1,
  "RateOfTurn": 1,
  "Sog": 12.3,
  "PositionAccuracy": true,
  "Longitude": 12.3,
  "Latitude": 12.3,
  "Cog": 12.3,
  "TrueHeading": 1,
  "Timestamp": 1,
  "SpecialManoeuvreIndicator": 1,
  "Spare": 1,
  "Raim": true,
  "CommunicationState": 1
}