APRS-IS Network Explained — Tier 2 Servers, Filters, and How Packets Propagate Worldwide

When somebody says "APRS shows up on websites in real time", what they actually mean is APRS-IS — the Automatic Packet Reporting System Internet Service. APRS-IS is a worldwide volunteer-run server mesh that takes every APRS packet decoded by every connected iGate on the planet, replicates it to every other server in the mesh, and then makes the combined firehose available to anybody who wants to subscribe — websites, mobile apps, researchers, dashboards, and any other piece of software that asks politely over TCP.

The whole thing is held together by perhaps fifteen people, runs on a handful of donated VPSes, and predates a lot of what you would now consider "modern" distributed systems work by more than a decade. This guide explains how it actually works: the server software, the Tier structure, the filter language, and how to connect a client.

The High-Level Picture

APRS-IS sits between the RF network and every consumer of APRS data. The simplified diagram is:

RF stations ──→ iGates ──→ APRS-IS Tier 2 servers ──→ Clients (web, mobile, apps)
                              ↕ full-mesh replication ↕
                          other Tier 2 servers

Every iGate maintains a TCP connection to one APRS-IS server and uploads every decoded packet. Every Tier 2 server then forwards every packet it receives to every other Tier 2 server it is peered with. The result: every packet uploaded anywhere on the network becomes available on every server within a couple of seconds.

A client — say, aprs.world — connects to one Tier 2 server, optionally applies a filter, and receives the matching subset of the worldwide firehose.

The Server Software: aprsc

Almost every APRS-IS server today runs aprsc, an open-source server written by Heikki Hannikainen (OH7LZB), who is also the creator of aprs.fi. aprsc is a high-performance C implementation that replaced the older Java-based javAPRSSrvr by Pete Loveall (AE5PL) on most public servers between roughly 2008 and 2012. It handles tens of thousands of simultaneous TCP connections per box and routinely passes 1+ Gbps of replication traffic during peak hours.

The protocol aprsc speaks is just text over TCP. There is no compression in the base protocol (some clients negotiate it), no TLS by default on the canonical port, and no authentication beyond the APRS passcode — which itself is not a secret but a deterministic integer derived from your callsign. The simplicity is deliberate: APRS-IS is a public bulletin board, not a confidential channel.

Tier 2: The Backbone You Should Connect To

The public-facing layer is called Tier 2. It is a small set of servers — roughly a dozen at any given time — distributed across continents and peered with each other in a full mesh. The current canonical list lives at aprs2.net. Examples:

These hostnames are DNS round-robin pools. Resolving rotate.aprs2.net from Istanbul will probably give you a European server; resolving it from Mexico City will probably give you a North American server. Always prefer a regional pool for your iGates and clients — it cuts latency and reduces transatlantic bandwidth.

There is no longer a separate "Tier 1" or "core" layer in the modern network. The original Tier 1 / core distinction from the early 2000s was retired when aprsc made it cheap enough for every Tier 2 server to peer directly. Today's network is functionally flat.

Ports and What They Carry

The standard ports on a Tier 2 server are well-defined:

For a new client, the rule of thumb is: connect to rotate.aprs2.net:14580, log in, send a filter, consume the resulting stream.

The Filter Language

The single most important reason to connect on port 14580 is that you can ask the server to do the filtering for you. Without a filter you get the full firehose — easily 30–80 packets per second worldwide. With a filter you get exactly the packets that matter to your application, which is usually a few packets per second at most.

Filters are specified as a single-line command sent immediately after the login. The syntax is documented officially at aprs-is.net/javAPRSFilter.aspx. The most useful filter primitives:

r/latitude/longitude/range — radius filter

r/41.0/29.0/100 returns every packet whose position is within 100 km of (41.0 N, 29.0 E). This is the workhorse filter for any map application — you ask for "everything near my current viewport" and the server does the rest.

b/CALLSIGN[/CALLSIGN...] — budlist (callsign list)

b/TA4OHN-9/TA4OHN-7 returns every packet originating from either callsign. Used by station-tracking pages.

p/PREFIX[/PREFIX...] — prefix filter

p/TA/YM returns every packet originating from any callsign starting with TA or YM (the prefixes for amateur stations in Turkey). Used for country/regional dashboards.

t/PACKET_TYPES — type filter

t/poimqstunw is a sequence of single-character codes:

You omit the letters for types you don't want. t/p returns positions only — perfect for a pure live-map application that doesn't care about telemetry.

a/lat1/lon1/lat2/lon2 — area (bounding box) filter

a/45.0/26.0/35.0/45.0 returns every packet whose position is inside the bounding box. Mathematically faster on the server side than r/ and useful when your viewport is rectangular.

s/SYMBOL — symbol filter

s/-> returns every packet whose APRS symbol is "->" (car). Used by car-only or weather-only maps.

Combining filters

Filters can be combined by space-separating them. r/41/29/100 t/poimqstunw returns positions, objects, items, messages, queries, status, telemetry, user-defined, NWS bulletins, and weather within 100 km of Istanbul. The server applies them as a logical AND.

A typical map application sends a different filter every time the viewport changes — pan the map, the client recomputes the filter, sends the new filter command, and the server starts streaming the new subset.

A Minimal Client Example

You can talk to APRS-IS with raw netcat:

nc rotate.aprs2.net 14580
# server greets you:
# javAPRSSrvr 4.0.0
# now log in (no real auth — passcode is callsign-derived):
user TA4OHN passcode 12345 vers myclient 0.1 filter r/41/29/100
# server starts streaming packets that match the filter

In practice you would use a library: aprslib for Python, node-aprs-fap for Node, the built-in TCP client in any language that has one. The APRS World backend connects to APRS-IS with a Fastify-based gateway worker and fans the packet stream out over Redis, Postgres (TimescaleDB), and a WebSocket.

How Replication Actually Works

When you upload a packet to one Tier 2 server, it has a qAR or qAO or qAS (Q-construct) marker injected into the packet header before being relayed. The Q-construct is documented at aprs-is.net/q.aspx and prevents duplicate replication loops. Other Tier 2 servers see the Q-construct and know not to bounce the packet back to the originator's server.

In practice the round-trip from "iGate in Lisbon uploads a packet" to "every Tier 2 server on the planet has it" is well under one second. The packet then sits in each server's small RAM ring buffer (usually 30–60 seconds of history) so latecomers can briefly look back.

A Note on Q-Constructs

The Q-construct system is worth one bullet point because it explains an oddity you will notice in raw packet dumps:

If you read packets and see ,qAR,TA1IGATE, you are reading "this packet came in over the air, was decoded by TA1IGATE, and is now being relayed." It is a very compact piece of provenance information.

Tier 2 vs Tier 1 — A Historical Note

Old documentation talks about Tier 1 (the "core") and Tier 2 (the "user-facing layer"). The split made sense when aprsc was less efficient and there was operational benefit to separating "the backbone" from "the access edge". With modern hardware that distinction has collapsed. There is just Tier 2 now, and every Tier 2 server is both an access point and a peer.

What APRS-IS Is Not

A few things APRS-IS deliberately does not provide:

Connecting from a Browser

You cannot connect directly to APRS-IS from a web browser, because browsers do not speak raw TCP. The pattern is:

  1. A backend process (Node, Python, Go, etc.) connects to APRS-IS over TCP and consumes packets.
  2. The backend stores them (Postgres + TimescaleDB on aprs.world, MySQL historically on aprs.fi), de-duplicates them, geo-indexes them, and exposes a REST + WebSocket API.
  3. The browser talks to the backend's API, not to APRS-IS directly.

This is why every public APRS visualizer is "really" two systems: an APRS-IS consumer and a user-facing app.

Further Reading

APRS-IS is the quiet workhorse of the modern APRS experience. Most operators never think about it; that it is invisible is its greatest virtue.