RTCM Unpacked: The Binary Protocol Your RTK Fix Actually Depends On
On this page
TL;DR
In the conventional OSR RTK workflow covered here, RTCM is the binary correction format that lets a rover difference its own satellite observations against a reference station. A usable stream needs compatible MSM observations, base coordinates such as MT1005 or MT1006, and MT1230 for full GLONASS interoperability in mixed-vendor workflows. MSM4 or MSM5 is the practical default, and a rover stuck in Float often has a correction-stream, configuration, or measurement-quality problem.
RTCM is the correction-data layer behind an RTK fix: NTRIP often transports it, NMEA reports the result, but RTCM is the binary stream that gives the rover the reference observations needed for centimeter-level positioning. If you've built an RTK system, you likely already speak NMEA — the readable ASCII stream telling you where you are. You've probably configured an NTRIP client to pull correction data over the internet. But have you ever looked inside the binary payload NTRIP is actually carrying?
That payload is RTCM. It contains the satellite observations from a reference station, encoded into a compact binary format. Your receiver consumes this data to move from meter-level standalone positioning toward centimeter-level RTK. If NMEA is the final answer your receiver gives you, RTCM is the input it needs to make that answer precise.
This guide covers RTCM observation-space representation (OSR) in a conventional base-to-rover RTK workflow. RTCM also defines state-space representation (SSR) messages, but their service design and receiver behavior are outside this guide.
In this volume of the Kalmix GNSS Handbook, we crack open the RTCM binary stream. We will cover what's inside it, which messages actually matter, how to choose between MSM4 and MSM7, and what to check when your rover stubbornly refuses to reach Fixed.
Need-to-Know Terms
- MSM (Multiple Signal Messages): the modern RTCM 3.2+ message family supporting multiple GNSS constellations and signals.
- OSR (Observation Space Representation): a correction model that sends base-station observations for the rover to difference locally.
- SSR (State Space Representation): a correction model that sends modeled orbit, clock, and atmosphere errors instead of local base observations.
- Rover: the moving GNSS receiver that consumes RTCM corrections and outputs position.
Where RTCM Fits in the RTK Data Chain
Every RTK system relies on two data flows moving in opposite directions:
- RTCM flows in: carrying correction data from the reference station to the rover.
- NMEA flows out: carrying the computed position, status, and fix quality from the receiver to your host controller.
NTRIP is the delivery truck; RTCM is the cargo. Your receiver takes the base station's RTCM observations, differences them against its own, and resolves carrier-phase ambiguities to produce centimeter-level coordinates.
Debug Upstream Before You Debug the Parser
The quality of your RTK solution is fundamentally bounded by the RTCM input. You can parse GGA perfectly, but if the RTCM stream is misconfigured, stale, or dropping packets, your Fix Quality will never reach 4 = RTK Fixed, and every hour spent on the parser is an hour spent on the wrong layer. If you cannot Fix, start debugging upstream.
RTCM vs NMEA: Correction Input vs Position Output
If you read our NMEA 0183 guide, you already know the receiver-output side of the positioning stack. RTCM is the opposite side: compact, binary, and intended for machines rather than humans.
| Property | RTCM 3.x | NMEA 0183 |
|---|---|---|
| Direction | Input: corrections into receiver | Output: position and status from receiver |
| Encoding | Binary, compact | ASCII, human-readable |
| Error check | CRC-24Q, 24-bit | XOR checksum, 8-bit |
| Frame delimiter | Preamble 0xD3 + length field |
$ start, * checksum, <CR><LF> ending |
| Typical role in RTK | Feeds the ambiguity engine | Reports fix status, coordinates, speed, and time |
RTCM's binary encoding is far more compact than ASCII-style data. That matters on constrained serial radio links where every byte counts.
A Brief History of RTCM
Modern RTK work should be built around RTCM 3.x. The older versions explain the standard's origin, but they are not where most current multi-constellation RTK systems should start.
| Year | Release | Why it matters for RTK |
|---|---|---|
| 1985–2001 | RTCM 1–2.x | Early DGPS evolved into RTK: Version 2.1 added RTK messages in 1994, Version 2.2 added GLONASS in 1998, and Version 2.3 followed in 2001. These versions use fixed 30-bit words. |
| 2004 | RTCM 3.0 | Introduced the variable-length frame and CRC-24Q structure designed for higher-rate RTK data. |
| 2006 | RTCM 3.1 (10403.1) | Added Version 3 network-RTK capabilities, including GPS network corrections. |
| 2013 | RTCM 3.2 (10403.2) | Introduced Multiple Signal Messages (MSM), the scalable observation family for modern multi-constellation GNSS. |
| 2016 | RTCM 3.3 (10403.3) | Published the Version 3.3 revision, including accumulated amendments. |
| 2023 | RTCM 3.4 (10403.4) | First published in 2023; Amendment 1 followed in 2024. It is still Version 3, not Version 4. |
RTCM 1–2.x began in the early DGPS era, but Version 2.1 already added RTK messages and Version 2.2 added GLONASS. Their fixed 30-bit-word structure was not well suited to the data volume and extensibility required by modern multi-constellation RTK. For the standards catalog behind the protocol, see the RTCM published standards.
Before MSM, the legacy observation messages were MT1001–1004 for GPS and MT1009–1012 for GLONASS. They were hard-coded for those constellations; MT1005–1008 are separate station and antenna messages. MSM introduced a common, signal-aware structure applied to each constellation block, so the same message family can scale to additional systems and signals.
In practice, using legacy observation messages on a modern receiver caps the receiver's ability to use today's multi-constellation sky.
For the field-level frame and message reference, use the companion document AN-002: RTCM SC-104 v3.3 Frame Structure & Message Type Reference.
RTCM 3 Frame Structure
Every RTCM 3.x frame uses the same envelope: a 0xD3 preamble, a length field, a variable payload, and a CRC-24Q checksum, so a parser must synchronize by bytes rather than by lines.
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ Preamble │ Reserved │ Length │ Payload │ CRC-24Q │
│ 8 bit │ 6 bit │ 10 bit │ Variable │ 24 bit │
│ 0xD3 │ 000000 │ 0–1023 │ (binary) │ │
└──────────┴──────────┴──────────┴──────────┴──────────┘
Unlike NMEA, RTCM frames are not line-delimited. You cannot just "read a line." Synchronize on 0xD3, read the length field, extract exactly that many payload bytes, and verify the CRC.
Here is the canonical pattern in Python:
"""
RTCM 3.x frame sync & extraction from a TCP/serial stream.
CRITICAL:
TCP delivers arbitrary byte chunks. Never assume one recv()
equals one complete RTCM frame. Always buffer.
"""
CRC24Q_POLY = 0x1864CFB
def crc24q(data: bytes) -> int:
crc = 0
for byte in data:
crc ^= byte << 16
for _ in range(8):
crc <<= 1
if crc & 0x1000000:
crc ^= CRC24Q_POLY
return crc & 0xFFFFFF
def extract_frames(buf: bytearray):
frames = []
while True:
# 1. Find preamble
try:
start = buf.index(0xD3)
except ValueError:
buf.clear()
return frames
# Drop noise before preamble
if start > 0:
del buf[:start]
# Need at least 3 header bytes
if len(buf) < 3:
return frames
# 2. Validate reserved bits and parse payload length
if buf[1] & 0xFC:
del buf[0]
continue
length = ((buf[1] & 0x03) << 8) | buf[2]
frame_len = 3 + length + 3
if len(buf) < frame_len:
return frames
frame = bytes(buf[:frame_len])
# 3. Verify CRC-24Q
received_crc = int.from_bytes(frame[-3:], "big")
computed_crc = crc24q(frame[:-3])
if received_crc == computed_crc:
frames.append(frame)
del buf[:frame_len]
else:
# False sync. Advance one byte and rescan.
del buf[0]
Transport Boundaries Are Not Frame Boundaries
The most common RTCM parser bug is assuming transport boundaries match protocol boundaries. They do not. A TCP read may contain half a frame, one frame, or several frames, so a parser that treats one recv() as one message can lose or corrupt corrections. Buffer first, parse second.
The Message Groups and the Two Silent Killers
RTCM 3.x defines many message types, but an RTK rover only needs a practical subset for most field work.
| Group | Typical MTs | Purpose | RTK required? |
|---|---|---|---|
| Observations, MSM | Per-constellation blocks, e.g. 107x GPS, 112x BeiDou | Multi-constellation, multi-signal observation data | Yes |
| Station coordinates | 1005 / 1006 | Base station antenna reference point in ECEF coordinates | Usually required for conventional single-base RTK |
| GLONASS code-phase biases | 1230 | GLONASS L1/L2 code-phase biases for full interoperability | Check first in mixed-vendor workflows |
| Observations, legacy | 1001–1004; 1009–1012 | GPS / GLONASS-only observation messages; 1005–1008 remain station and antenna messages | Legacy only |
| Antenna / ephemeris | 1033 / 1019+ | Receiver info and broadcast ephemeris | Optional, depending on workflow |
While observation messages are obvious, developers often lose time on two missing message types that fail less visibly:
- MT1005/1006, base station identity: in conventional single-base RTK, these carry the base station's physical coordinates. Without station coordinates, the rover cannot compute a baseline vector.
- MT1230, GLONASS code-phase biases: GLONASS uses FDMA, which can create hardware code-phase biases. MT1230 carries the GLONASS L1 and L2 bias values used for full interoperability. Check it first when the base/service and rover use different receiver vendors; without it, a rover may track GLONASS satellites but exclude them from the RTK solution.
Satellite Count Is Not Solution Participation
A rover can show plenty of satellites in GSV while still refusing to use some of them in the actual fix solution, so a healthy-looking satellite count can hide a missing message type for hours. Compare NMEA GSV, GSA, GGA status, correction age, and the incoming RTCM message list rather than trusting satellite count alone.
MSM4, MSM5, or MSM7: Which RTCM Message Type Matters?
MSM, or Multiple Signal Messages, is the RTCM 3.2+ observation-message family introduced in 2013 to replace legacy single-constellation observation messages such as MT1001–1004 and MT1009–1012. Each MSM message ID identifies a constellation block and a prescribed observation-content level.
For live RTK, choose MSM for both receiver requirements and link capacity: a suitable message set still fails if the radio cannot carry it on time. MSM numbers are systematic. The prefix identifies the constellation, such as 107x for GPS and 112x for BeiDou. The last digit, from 1 to 7, identifies the prescribed observation-content level; it is not a universal quality score.
| Scenario | Common starting point | Why |
|---|---|---|
| Constrained radio link (for example, 9600 bps) | MSM4 | Full carrier phase and CNR without Doppler; validate the actual stream rate. |
| Standard 4G / Wi-Fi correction link | MSM5 | Adds phase-range rate (Doppler) when the receiver and link can use it. |
| High-detail RTCM logging on a capable link | MSM7 | High-resolution RTCM observations; use only after confirming link capacity. |
| Sub-meter IoT or extreme bandwidth constraints | MSM1 | Pseudorange only; minimal payload, not ideal for centimeter RTK. |
MSM7 Is Not Automatically Better
MSM4 and MSM5 are practical defaults. MSM7 is not automatically better if your link cannot carry it. Treat four-constellation MSM7 over a 9600 bps serial radio as a capacity test, not a default: satellite count, signals, update rate, and other messages determine whether it will fit.
The Format Landscape: RTCM vs. The Rest
RTCM is the interoperability default for RTK correction streams, but you will encounter other correction or logging formats in the field.
| Format | Representation | Typical use | Interoperability boundary |
|---|---|---|---|
| RTCM 3.2+ MSM | OSR, compact binary | Real-time RTK correction streams | Broad industry default for cross-manufacturer RTK |
| CMRx | Compact proprietary OSR | Real-time RTK where the receiver ecosystem supports it | Trimble proprietary |
| SPARTN | Compact SSR | PPP-RTK over low-bandwidth satellite or IP delivery | Open specification; a different correction model from RTCM OSR |
| RINEX 3/4 | Receiver-independent observation files | Offline post-processing and forensic review | Not normally a live correction stream |
OSR streams send reference-station observations for rover-side differencing; SSR streams send modeled orbit, clock, and atmospheric corrections instead. That representation boundary matters more than the format name: a receiver and service must be designed for the correction model they use. CMRx can reduce bandwidth inside a Trimble workflow, but it trades away the broad cross-manufacturer interoperability of RTCM.
Keep a PPK Fallback
Log rover raw observations: PPK needs them. A rover-side RTCM capture records only periods when corrections reached the rover; it cannot replace rover raw observations or cover a link outage. For an outage interval, obtain matching data from the base station's own log or a CORS archive. Open-source tools such as RTKLIB are often used to inspect, convert, and post-process GNSS logs.
RTCM Debugging Checklist
When your rover refuses to reach Fixed, inspect the incoming stream before assuming the GNSS hardware or parser is wrong. Use a raw capture or a receiver view that exposes the incoming message list, correction age, and solution state.
Common RTK debugging patterns share a single principle: when the rover refuses to Fix, first inspect what it is receiving before assuming the computation is wrong. The five symptoms below point to specific upstream checks.
| Symptom | Likely RTCM issue | Fix |
|---|---|---|
| GGA Fix Quality stuck at 1 | Correction inputs may be missing or incompatible, including MT1005/1006 station coordinates or the observation messages your rover supports. | Confirm station coordinates and compatible observations on the mountpoint; then verify that the rover is actually applying corrections. |
| GLONASS visible in GSV but not used in GSA | A mixed-vendor workflow may be missing MT1230, leaving GLONASS tracked but excluded from the RTK solution. | Use a mountpoint that includes MT1230 and verify that the rover accepts GLONASS corrections before disabling that constellation. |
| Correction Age climbing steadily | The TCP, radio, or cellular correction link is stale or dropped. | Implement reconnection logic and monitor correction age in the host application. |
| Fix is slow, or Correction Age jumps erratically | The link may be bandwidth-choked by full-constellation MSM7 or an overly high update rate. | Drop to MSM4, reduce constellations, raise the baud rate, or lower the correction update rate. |
| Position offset is stable but wrong by meters | This is likely not an RTCM decoding issue; the coordinate frame or datum may be mismatched. | Check coordinate-frame alignment. See Beyond WGS84 for why a precise fix can still land in the wrong map frame. |
Conclusion
RTCM is not a protocol most developers need to hand-write. It is a correction stream your system must route, validate, and monitor correctly.
Verify that your receiver supports RTCM 3.2+ MSM. Select a mountpoint broadcasting compatible MSM observations and MT1005/1006 station coordinates; check MT1230 first for GLONASS in a mixed-vendor base/service-to-rover workflow. Monitor NMEA GGA Fix Quality and Correction Age. If Correction Age climbs, investigate the input chain even if the receiver keeps outputting position sentences.
For a complete field-by-field breakdown of binary frame structure, CRC-24Q, and MSM mask handling, read the companion reference: AN-002: RTCM SC-104 v3.3 Frame Structure & Message Type Reference.
Key Takeaway
For conventional OSR RTK debugging, treat RTCM as the first thing to verify, not the last thing to suspect. A rover cannot produce a reliable RTK Fixed solution without valid observation messages, base station coordinates, compatible constellation data, and a fresh correction stream.
Frequently Asked Questions
What is the difference between RTCM and NMEA in an RTK system?
RTCM and NMEA sit on opposite sides of the receiver workflow. RTCM is a compact binary correction-data input used by the rover to compute an RTK solution. NMEA is a human-readable ASCII output format used by the receiver to report coordinates, time, velocity, and fix status to the host system.
Which RTCM messages are required for RTK Fixed?
A practical conventional OSR RTK stream usually needs compatible MSM observation messages and base station coordinates such as MT1005 or MT1006. For full GLONASS interoperability, check MT1230 first in mixed-vendor base/service-to-rover workflows. Without station coordinates, the rover cannot compute a baseline; without compatible observation messages, it cannot resolve carrier-phase ambiguities reliably.
Should I use legacy RTCM, MSM4, MSM5, or MSM7?
Use RTCM 3.2+ with Multiple Signal Messages (MSM) for modern RTK. For most real-time applications, MSM4 or MSM5 is the practical default. MSM4 reduces bandwidth, while MSM5 adds Doppler for velocity and cycle-slip detection. MSM7 carries higher-resolution data, but it consumes more bandwidth and can overload constrained radio links. Avoid legacy observation messages MT1001–1004 and MT1009–1012 for modern multi-constellation receivers.
What is MT1230 and why does it matter?
MT1230 carries GLONASS L1 and L2 code-phase biases used for full interoperability. Check it first when the base/service and rover use different receiver vendors. Because GLONASS uses FDMA, hardware biases can differ between receivers. Without MT1230, a rover may track GLONASS satellites but exclude them from the RTK solution, reducing satellite count, geometric strength, and fix reliability.
How much bandwidth or baud rate is required for RTCM 3.2+ MSM streams?
There is no universal baud-rate threshold. Measure the actual stream: its rate changes with MSM type, constellation and signal count, update rate, auxiliary messages, and transport overhead. Choose a link with headroom, then watch correction age and buffer behavior. A 9600 bps radio may suit a deliberately small stream, but it is not a guarantee even for GPS/GLONASS MSM4.
Why is my rover stuck in Float even though RTCM is streaming?
Check whether the stream includes compatible MSM observations, MT1005/1006 station coordinates, fresh correction age, and MT1230 for GLONASS in a mixed-vendor workflow. Also verify that the correction stream is not too large for the link, because buffer overflow can make corrections arrive late even when the stream appears connected.
Continue exploring
AN-002: RTCM Frame Reference
The field-level reference for frame parsing, CRC-24Q and MSM message structure.
LateralPosition Before Steering
What this correction stream has to deliver once a tractor is steering on it.
ApplyTRACE for Windows
How to watch the incoming message list, correction age and RTK state on a real link.