Open Waters AIS
All the ships at sea,
instantaneously.
A real-time stream of marine AIS traffic. Open source, and free for personal use.
- Vessels
- –
- Msg / s
- –
- Stations
- –
Real-time API
Get every AIS message as it is heard over WebSocket, SSE, or NMEA. Fetch a GeoJSON snapshot of what is in a box right now, plus stations and live stats.
API reference →Open source, open data
An open AIS network powered by MIT-licensed code, and data re-served under each source's own terms, with the source named on every event.
GitHub →Free for personal use
Read without an account; a one-click token covers a boat, a dashboard, or a side project. Contributing AIS data earns more.
See tiers and limits →
Stream vessel data in your favorite language.
Open a WebSocket, send one subscribe frame, and every message inside the box arrives as JSON with its source, station, raw sentence, and decoded fields.
Coming from aisstream.io? Point your client at wss://ais.openwaters.io/v0/stream with a token as APIKey and it keeps working. Stream gone quiet? Check whether aisstream.io is down.
Talking to Claude or ChatGPT instead? Add https://ais.openwaters.io/mcp as an MCP server and ask what is in the port.
const ws = new WebSocket("wss://ais.openwaters.io/v1/stream");
ws.onopen = () =>
ws.send(JSON.stringify({
type: "subscribe",
bbox: [[59, 10, 60, 11]]
}));
ws.onmessage = ({ data }) => {
const ev = JSON.parse(data);
if (ev.type !== "event") return; // welcome, ack, error
console.log(ev.mmsi, ev.msg_type, ev.lat, ev.lon);
};import asyncio, json, websockets
URL = "wss://ais.openwaters.io/v1/stream"
SUB = {"type": "subscribe", "bbox": [[59, 10, 60, 11]]}
async def main():
async with websockets.connect(URL) as ws:
await ws.send(json.dumps(SUB))
async for frame in ws:
ev = json.loads(frame)
if ev["type"] != "event": # welcome, ack, error
continue
print(ev["mmsi"], ev["msg_type"],
ev.get("lat"), ev.get("lon"))
asyncio.run(main())url := "wss://ais.openwaters.io/v1/stream"
c, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatal(err)
}
c.WriteJSON(map[string]any{
"type": "subscribe",
"bbox": [][]float64{{59, 10, 60, 11}},
})
for {
var ev struct {
Type string `json:"type"`
MMSI int `json:"mmsi"`
MsgType string `json:"msg_type"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
}
if err := c.ReadJSON(&ev); err != nil {
log.Fatal(err)
}
if ev.Type != "event" { // welcome, ack, error
continue
}
fmt.Println(ev.MMSI, ev.MsgType, ev.Lat, ev.Lon)
}use futures_util::{SinkExt, StreamExt};
use tokio_tungstenite::{connect_async, tungstenite::Message};
#[tokio::main]
async fn main() {
let url = "wss://ais.openwaters.io/v1/stream";
let (mut ws, _) = connect_async(url).await.unwrap();
let sub = r#"{"type":"subscribe","bbox":[[59,10,60,11]]}"#;
ws.send(Message::text(sub)).await.unwrap();
while let Some(Ok(msg)) = ws.next().await {
let Message::Text(frame) = msg else { continue };
let ev: serde_json::Value =
serde_json::from_str(&frame).unwrap();
if ev["type"] != "event" { continue } // welcome, ack, error
println!("{} {} {} {}",
ev["mmsi"], ev["msg_type"], ev["lat"], ev["lon"]);
}
}# live stream
SUB='{"type":"subscribe","bbox":[[59,10,60,11]]}'
echo "$SUB" | websocat -n wss://ais.openwaters.io/v1/stream
# snapshot of what is in the box right now
curl "https://ais.openwaters.io/v1/vessels?bbox=59,10,60,11"Limits, but only to keep the lights on.
The stream combines community networks, open government feeds, and volunteer receptions, with terms documented per source. These limits exist to keep the service healthy and reward the people who contribute to it.
| AnonymousFor trying things out. | PersonalFor a boat, a hobby project, or a developer’s laptop. | ContributorAwarded to a station that contributes data. | CommercialFor products, fleets, or those who need support. | |
|---|---|---|---|---|
| Cost | Free | Free | Free | Paid |
| Connections/IP Address | 2 | 2 | 5 | 10 or more |
| Messages/sec | 20 | 50 | 200 | Unlimited |
| Subscribed area | ~10°×10° | ~20°×20° | Unlimited | Unlimited |
| Vessels followed by MMSI | 10 | 50 | 200 | As agreed |
| Sending data | — | |||
| Raw NMEA feed | — | — | ||
| Get a token | Start contributing | Contact us |
Limits apply per token and per network address: at most 8 concurrent streams from one address, however many tokens are behind it. Over a per-second rate the stream thins and stays up; over a connection, area, or MMSI-list limit you are refused with a message that says so. Following vessels by MMSI is bounded by the list, not by area, so a world-wide MMSI subscription is allowed in every tier. Need more, or unsure which tier you are? hello@openwaters.io.
A network you can contribute to. Data you can take with you.
Your receiver fills in part of the coast. Other receivers fill in theirs. aiscast, the Open Waters AIS network, brings those receptions together with public feeds so everyone can see more.
Share what you hear without giving Open Waters exclusive control. Keep feeding other networks, keep a copy, and build on the data yourself.
Connect your receiverNo receiver yet? Get started from shore with a USB receiver, an antenna, and the computer you already own.
Your receiver
And other volunteers
Public feeds
Each with its own license
Open Waters
Combine receptions. Remove duplicates. Keep the source.
You and everyone else
Live map, apps, research, and your own saved feed
Federation between independent nodes
Your receptions: CC0
Individual volunteer receptions enter the public domain under CC0. You can copy, reuse, and share them, including commercially. We have the same rights as everyone else.
The volunteer database: ODbL
The combined volunteer database stays open under ODbL. Reuse and redistribute it with attribution; publicly used adapted databases must also be offered under ODbL. Partner feeds retain their own terms.
Built to outlive one operator
Save the live feed today, within your access limits. Public archive downloads are coming, so you will be able to retrieve historical data too. Federation already lets independently operated nodes exchange data; the open licenses let others build on it and continue operating the network.
You can stop contributing whenever you want. Receptions already released remain open; Open Waters gets no exclusive license, even if the project changes hands. Read the contributor agreement for the commitment behind this.
Every event names its source.
AISHub and its contributors make much of our worldwide terrestrial coverage possible. We contribute volunteer receptions in return.
Vessels are distinct MMSIs heard in the last 30 minutes;unique counts the ones no other source heard.
| Source | Vessels | Unique | Events / 24h | Last heard |
|---|---|---|---|---|
| KystverketNorwegian coast, 40–60 nm out | – | – | – | – |
| BarentsWatchNorwegian EEZ and Svalbard, incl. satellite | – | – | – | – |
| Fintraffic DigitrafficFinnish waters | – | – | – | – |
| Volunteer receiversGlobal, wherever they are | – | – | – | – |
| AISHubworldwide terrestrial; about a minute behind | – | – | – | – |
| aisstream.ioworldwide (when it is up) | – | – | – | – |
License
Licensing is per source, and the aggregate is not relicensed: each event is re-served under the terms of the source it came from, which is why source is on every event and every vessel. If you display or redistribute the data, carry the source's attribution through.
| Source | License | What you must do |
|---|---|---|
| Kystverket | NLOD 2.0 | Credit: “Contains data under the Norwegian licence for Open Government data (NLOD) distributed by the Norwegian Coastal Administration.” NLOD is not sublicensable: you are bound by it directly. |
| BarentsWatch | NLOD 2.0 | Credit: “Data delivered by BarentsWatch”. NLOD is not sublicensable: you are bound by it directly. |
| Fintraffic Digitraffic | CC BY 4.0 | Credit: “Source: Fintraffic / digitraffic.fi, license CC 4.0 BY.” |
| Volunteer receivers | CC0 1.0 | Receptions are dedicated to the public domain under the contributor agreement; no attribution required. The aggregate database is published under ODbL. |
| AISHub | AISHub membership | Credit AISHub contributors with a link to aishub.net; every event carries source: aishub. Reuse and redistribution follow AISHub’s terms and any applicable written agreement. |
| aisstream.io | no published terms | Best effort, frequently offline. source: aisstream. |
The server, viewer, and plugin are MIT. The full position on licensing, privacy, and how the project funds itself without relicensing data is in the GitHub repository.
Start with one WebSocket.
No account, no key. Get a token later if you outgrow the anonymous limits.