AIS-catcher reads ship positions off an SDR instead of a marine receiver
AIS receiver for RTL SDR dongles, Airspy R2, Airspy Mini, Airspy HF+, HackRF, SDRplay and SoapySDR
At a glance
- What is it?
- AIS-catcher is a GPL-3.0 command line receiver that decodes AIS on cheap RTL-SDR dongles, Airspy, HackRF and other SDRs, then serves NMEA and a web viewer. It fits hobbyists and researchers, but the authors call it a hobby project and warn against relying on it for navigation.
- Who is it for?
- AIS-catcher suits people who already own an SDR dongle and want ship traffic in NMEA, JSON or a database without buying marine hardware. It does not suit anyone who needs certified reliability, and the project's own disclaimer excludes navigation and safety use.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why decode AIS on a general purpose radio
AIS-catcher turns a software defined radio into a dual channel AIS receiver, which matters because most people who want ship positions do not own dedicated marine hardware. The project description calls it a versatile dual-channel AIS receiver compatible with a wide range of software defined radios, and the README describes it as a lightweight command line utility with a built-in web server for internal use within secure networks. That combination puts the tool within reach of radio hobbyists, maritime data tinkerers and small vessel operators who already own a cheap RTL-SDR dongle.
Two constraints travel with the tool. The README calls it a hobby project that has not been tested and designed for reliability and correctness, and says explicitly not to rely upon it for navigation or safety of life or property purposes. It also notes that radio reception law differs between administrations, so checking local rules is the user's own responsibility rather than something the software handles for you.
One binary with a source file for every radio backend
The device list is long, and the source layout confirms that each radio has its own translation unit rather than a shared abstraction. Under the Device directory there are AIRSPY.cpp, AIRSPYHF.cpp, RTLSDR.cpp, HACKRF.cpp, HYDRASDR.cpp, SDRPLAY.cpp and SoapySDR.cpp, alongside the less usual inputs: FileRAW.cpp, FileWAV.cpp, RTLTCP.cpp, SpyServer.cpp, UDP.cpp and ZMQ.cpp. Serial.cpp handles the serial link used by the dAISy-catcher hardware, and N2KsktCAN.cpp points at NMEA 2000 traffic arriving over a CAN socket.
That file naming tells you the radio is a pluggable layer, but it also means a new radio usually means new build work. The repository also carries Aviation/ADSB.cpp and Marine/N2K.cpp, so the decoder is not limited to AIS and can pick up ADS-B and NMEA 2000 sentences in the same run. Topics listed for the project include aprs, gnuradio, zeromq and spyserver, matching the input and output paths visible in the tree.
The web viewer ships inside the receiver, not beside it
Many projects of this type ship a separate viewer or a separate plotting stack. AIS-catcher folds the interface into the receiver binary, which is why the flag in every configuration example is -N 8100, the port the built-in server listens on. The web frontend lives in the frontend/ directory, and the server side pieces appear as Web/WebViewer.cpp, Web/MapTiles.cpp, Web/Prometheus.cpp and Web/WebDB.cpp, so map tiles, Prometheus metrics and a web-facing database are all part of the same build rather than add-on tools.
The configuration is edited as JSON, and the same file carries keys such as the error exclusion list, which the README gives as "exclude_errors": "undersized,checksum". The practical consequence is a single process to deploy: one binary reads the radio, writes the database and serves the map to anyone on the trusted network.
Error flags, validation and the message filter are three layers
The most confusing part of AIS-catcher for newcomers is that a message can be flagged as bad without being excluded, and the two behaviours are controlled by different options. The exclusion list and the only-errors switch are shown in the README as four variants of the same command:
AIS-catcher -N 8100 FILTER on EXCLUDE_ERRORS undersized,checksum # exclude undersized and bad-checksum reports
AIS-catcher -N 8100 FILTER on EXCLUDE_ERRORS all # also exclude oversized
AIS-catcher -N 8100 FILTER on EXCLUDE_ERRORS none # include flagged messages
AIS-catcher -N 8100 FILTER on ONLY_ERRORS on EXCLUDE_ERRORS none # only flagged messagesThese options apply to map, file, network and database outputs, but they take effect only with FILTER on. With filtering off, quality flags alone never remove messages, and the default EXCLUDE_ERRORS none means that switching the filter on by itself still excludes nothing. Statistics keep counting messages rejected by EXCLUDE_ERRORS, while messages rejected by ONLY_ERRORS are not counted at all.
Underneath the filter sits a validation stage that works on message length and type rather than on fuzzy heuristics. The documentation states that exact-length checks cover fixed-length types 1 to 5, 9, 11, 18, 19, 23, 27 and 28, and that messages below the per-type minimum are rejected while zero-length messages stay valid. Unparsable sentences, unknown types and payloads too short to identify a sender are rejected as well, and MMSI zero is now rejected at validation for every output rather than only by the map. A separate CRC_CHECK on option rejects messages at ingress, and messages dropped there never reach the viewer statistics, so leaving it off is how you keep checksum failures visible in the counters. For feeds that append nonstandard trailers, the documented combination is to exclude undersized and checksum reports while retaining oversized ones.
A GeoJSON catalogue turns coordinates into named places
Ships in a harbour are only interesting if you can say where they are, and AIS-catcher keeps that knowledge outside the binary in an editable catalogue of GeoJSON files. Ports, terminals, berths, anchorages, waters and custom areas all live in that directory, and ships in a place, visits and port-bound traffic are derived from it. The standalone viewer is pointed at a catalogue with -N 8100 PLACES /path/to/places, while a managed installation keeps a places directory beside its configuration and edits it from the Places tab.
Because the format is plain GeoJSON, the catalogue can be versioned with the rest of your configuration or generated by an external script. The documentation on places covers the file format and the rules that decide which ships count as being in a place.
Building from source, or running the shipped container image
The repository carries both a plain Makefile and a CMakeLists.txt, so a build does not require a full CMake workflow. The Makefile is explicit about its toolchain and flags:
CC = clang
override CFLAGS += -O3 -ffast-math -std=c++11 -g -pg -Wno-sign-compare $(INCLUDE)The source list in the Makefile names every translation unit, which makes it easy to see what a build covers. For container use, the Dockerfile starts from debian:trixie-slim and runs the project's own install script:
FROM debian:trixie-slim
RUN apt-get update && apt-get upgrade -y && \
apt-get install -y --no-install-recommends curl ca-certificates && \
bash -c "$(curl -fsSL https://raw.githubusercontent.com/jvde-github/AIS-catcher/main/scripts/aiscatcher-install)" _ --package --no-systemd --no-user && \
apt-get remove -y curl && apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/usr/bin/AIS-catcher"]There is also a Python binding named aiscat, published on PyPI with its source and documentation in the python/ directory, which is the shortest path if you want to consume messages from Python rather than parse NMEA yourself.
Sharing a station with the community hub
Stations can contribute raw AIS data to a public map. The procedure is documented in three steps: get onto the latest version, add your station at aiscatcher.org, and use the personal sharing key you receive in return. The key is passed on the command line with -X, and that activates a Community Feed layer inside your own station's web viewer, reachable under map layers and a few other features.
Sharing a key is a deliberate act rather than a default, since it publishes raw ship traffic from your antenna. The station must be on the latest version to be added, which in practice means running a recent release rather than whatever binary an image happens to ship. The project homepage also carries several realtime examples of the receiver in use.
Where AIS-catcher is the wrong tool
Three situations argue against it. The first is any use where a wrong position could hurt someone. The disclaimer is unambiguous that the software is not designed for reliability and correctness and must not be relied on for navigation or for the safety of life or property, which rules out feeding it into a live bridge system even as an auxiliary source.
The second is a low-power or unattended install on a small boat. The README points readers who prefer a traditional AIS receiver but want the same software advantages to the dAISy-catcher, a dedicated dual-channel receiver developed with Wegmatt that offers plug-and-play operation, low power consumption and precise signal processing, and that connects to AIS-catcher over serial, as a USB device or as a Raspberry Pi HAT. The third is deployment where you want hardware guarantees from a turnkey device, since the software side is explicitly hobby grade. The README does not document a rollback procedure for a bad upgrade, and there is no migration path described for an existing installation, so pin a release and keep a copy of your configuration.
Editorial conclusion
AIS-catcher suits people who already own an SDR dongle and want ship traffic in NMEA, JSON or a database without buying marine hardware. It does not suit anyone who needs certified reliability, and the project's own disclaimer excludes navigation and safety use. Before committing, start a session with -N 8100, confirm your radio backend loads on your platform, and read the changelog for the v0.70 release from 2026-06-19 before upgrading past the last push on 2026-10-19.
Frequently asked questions
What radio hardware does AIS-catcher need to receive AIS messages?
It works with RTL-SDR dongles such as the ShipXplorer AIS dongle and the RTL SDR Blog v4, AirSpy Mini, R2 and HF+, HackRF, HydraSDR, SDRPlay and SoapySDR. It can also read from file and network sources over ZMQ, RTL-TCP or SpyServer, so recorded captures can be replayed without a radio.
How do I start AIS-catcher with its built-in web viewer?
Run it with -N 8100, which is the port used in every configuration example for the built-in web server. The README describes that server as intended for internal use within secure networks, so it is not a hardened public endpoint.
Can I use AIS-catcher for navigation or safety of life at sea?
No. The README states that the software is a hobby project that has not been tested and designed for reliability and correctness, and says not to rely upon it for navigation or safety of life or property purposes. Use it for research, education and personal data collection only.
How do I share my station's AIS data with the aiscatcher.org community hub?
Add your station at aiscatcher.org to receive a personal sharing key, then run AIS-catcher with -X followed by that key. The station must be on the latest version, and sharing enables a Community Feed in your own web viewer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jvde-github-ais-catcher)Was this useful?