POCSAG pager decoding

How to catch POCSAG pager traffic

Tools
multimon-ng, rtl_fm, SDR++, Raspberry Pi OS bookworm or any Linux
Skill / setup
beginner · 1–2 hours (includes frequency hunting) · ~$55–$65 (RTL-SDR Blog v4 ~$40 + wideband antenna)
See how it compares to Squelch Deck

Pagers are not dead — they're alive and busy in hospitals, fire departments, IT on-call rotations, and a surprising amount of industrial telemetry. Most of that traffic is still POCSAG, an analog FSK protocol that's been in production since the 1980s. With an RTL-SDR and multimon-ng, you can listen in on the same channels and watch dispatch messages, alphanumeric pages, and beepers as they go out across your area. This guide gets a clean POCSAG decode going on a Linux box, then layers on FLEX (the successor protocol) and per-channel logging.

What you'll have at the end

A terminal window where multimon-ng prints each decoded pager message as it comes off the air — capcode (the pager's address), protocol (POCSAG512 / POCSAG1200 / POCSAG2400 / FLEX), and the alphanumeric or numeric content. Behind the scenes, rtl_fm is tuning your RTL-SDR to a pager channel, demodulating the FSK to audio, and piping it into multimon-ng which does the protocol decode. Output looks something like:

POCSAG1200: Address:  0123456  Function: 3  Alpha:   STAT 12 - rm 4218 - chest pain
POCSAG1200: Address:  0987654  Function: 0  Numeric: 8675309
FLEX|2026-05-22 14:32:18|1600/2/A|003|001.001.001|0987654321|Pls call IT, ticket #4471

Most pager networks are unencrypted; some carry sensitive content (medical dispatch in particular). Receiving is generally legal in the US for personal use under §47 USC 605 carve-outs for unencrypted broadcasts, but redistributing the content — especially anything identifying patients, employees, or specific incidents — is a different question. This guide assumes you're listening, not publishing.

What you need

Hardware. An RTL-SDR Blog v4 (~$40) is the standard. The cheaper R820T2 dongles also work fine for pagers — the audio bandwidth needed (~10 kHz) is well within what any RTL-SDR handles. A discone or wideband VHF/UHF antenna covers both common pager bands; for testing, even a $5 telescopic whip set to ~50 cm gets you on the VHF pager band (152–158 MHz). Wired or Wi-Fi connection — doesn't matter; the decoder runs locally and uses almost no bandwidth.

Software. Linux is the path of least resistance: rtl-sdr (for rtl_fm), multimon-ng (for the protocol decode), and optionally sox if you want to record audio to disk. All available from apt/dnf/pacman on every common distro. Raspberry Pi OS bookworm, Ubuntu 22.04+, and Debian 12 have all been confirmed working. On Windows, the analog is pdw (Pager Decoder Win) or pocsagdec — both work, but the CLI Linux pipeline below is simpler to script and log from.

Time. See the frontmatter at the top of this page. Skill level. Comfortable opening a terminal, running apt install, and reading man rtl_fm. The actual decode is one shell pipeline.

Step-by-step setup

1. Identify the active pager band in your area

The US has two main pager bands: VHF 152–158 MHz (most common in hospitals, fire/EMS, older industrial paging) and UHF 929–932 MHz (newer commercial paging, common in IT on-call). You want to find a channel that's actually busy — an empty channel will give you a beautiful clean decode of nothing.

The fastest scan: open SDR++ or Gqrx, set the source to your RTL-SDR, tune to 152 MHz with a wide span (10 MHz or so), and watch the waterfall for 5–10 minutes. POCSAG bursts look like short, narrow vertical streaks 12–25 kHz wide, lasting 0.3–2 seconds. If you see them clustering at specific frequencies, those are your candidate channels.

Some commonly-active frequencies in the US (your mileage will vary by city):

  • 152.840 MHz, 152.480 MHz — hospital / medical paging in many metros
  • 157.450 MHz, 158.700 MHz — commercial / business paging
  • 929.6125 MHz, 931.4375 MHz — Spok / American Messaging
  • 462.475 MHz, 462.500 MHz — some industrial on-site paging

Check SignalIdent's signal wiki and your area's RadioReference frequency database for what's specifically active near you.

2. Install rtl-sdr and multimon-ng

On Raspberry Pi OS, Ubuntu, or Debian:

sudo apt update
sudo apt install -y rtl-sdr multimon-ng sox

That's it — both packages are in the default repos. Confirm versions:

rtl_fm --help 2>&1 | head -1
multimon-ng --help 2>&1 | head -5

If the RTL-SDR kernel DVB driver is in the way (the kernel's TV-tuner module that grabs the same USB ID), blacklist it:

echo 'blacklist dvb_usb_rtl28xxu' | sudo tee /etc/modprobe.d/blacklist-rtl.conf
sudo modprobe -r dvb_usb_rtl28xxu

3. First decode (one-line pipeline)

Tune to a known-active POCSAG channel and pipe rtl_fm audio into multimon-ng:

rtl_fm -f 152.840M -M fm -s 22050 -g 35 -p 0 - | multimon-ng -t raw -a POCSAG512 -a POCSAG1200 -a POCSAG2400 -f alpha /dev/stdin

Breakdown of the rtl_fm flags:

  • -f 152.840M — center frequency (set to whatever channel you identified in step 1)
  • -M fm — narrow FM demodulation (correct for POCSAG)
  • -s 22050 — sample rate of 22.05 kHz, the rate multimon-ng wants
  • -g 35 — RF gain in dB (start at 30–40, tune in step 5)
  • -p 0 — PPM frequency correction; leave at 0 to start

And multimon-ng's flags:

  • -t raw — read raw mono audio from stdin
  • -a POCSAG512 -a POCSAG1200 -a POCSAG2400 — try all three POCSAG baud rates (most US traffic is 1200; some legacy systems are 512; a few are 2400)
  • -f alpha — also attempt alphanumeric decode for each message (not just numeric)
  • /dev/stdin — input from the pipe

If everything's working, you'll see decoded messages start scrolling within a minute or two. If nothing decodes, see step 4.

4. Debug a silent decode

If multimon-ng is running but no messages appear, work through this in order:

Is there audio at all? Pipe rtl_fm to aplay instead and listen for the characteristic POCSAG / FLEX FSK tone (sounds like an old modem dialing — a fast warbling "wee-aw-wee-aw"):

rtl_fm -f 152.840M -M fm -s 22050 -g 35 - | aplay -r 22050 -f S16_LE -t raw -

If you hear silence, your gain is too low, the antenna is wrong for the band, or you picked an inactive channel.

Is the FSK centered? Open SDR++ on the same frequency. The POCSAG FSK should be visually centered in the waterfall. If it's offset by a few kHz, your RTL-SDR has frequency drift — measure the offset and set -p <ppm> accordingly (typical RTL-SDR Blog v4 needs -p 1 to -p 5; older cheap dongles can need -p 30 or more).

Is the bandwidth right? Some POCSAG channels run wider FSK than others. If the decode is partial — some messages come through but the long ones fail — try increasing rtl_fm's -s to 24000 or 48000 (multimon-ng accepts a few rates; the man page lists them).

5. Tune gain for clean decode

rtl_fm's -g flag is the receiver's RF gain. Too low and weak distant pagers don't make it through; too high and strong nearby pagers overload the front-end and produce IMD products that corrupt other channels.

Start at -g 30, watch how many decodes you get over 5 minutes, then try -g 35, -g 40, -g 45. The right setting maximizes decoded messages, not signal strength. For most installs in suburban areas, 35–42 dB is the sweet spot.

If you have a strong nearby pager transmitter (you'll see it as a tall steady carrier in SDR++), you may need to drop gain to 25 to avoid having it desensitize the dongle.

6. Add FLEX decoding

FLEX is Motorola's successor to POCSAG — higher data rate (1600–6400 bps), better error correction, longer alphanumeric messages. Most modern US commercial paging is FLEX; medical and fire/EMS are split between FLEX and POCSAG1200.

multimon-ng decodes both in the same invocation:

rtl_fm -f 929.6125M -M fm -s 22050 -g 38 - | multimon-ng -t raw -a POCSAG1200 -a FLEX -f alpha /dev/stdin

FLEX output has a different format (timestamp + capcode + protocol + content); both POCSAG and FLEX lines print to the same stream so you'll see them mixed. Note that FLEX channels live primarily in the UHF 929–932 MHz band in the US — switching protocol usually means switching frequency.

7. Log decoded messages to a file

Once a decode is reliable, log it to disk for later analysis:

rtl_fm -f 152.840M -M fm -s 22050 -g 35 - | multimon-ng -t raw -a POCSAG1200 -a FLEX -f alpha /dev/stdin | tee -a ~/pager-log-$(date +%F).txt

tee -a writes to both the terminal (so you can watch it live) and to a daily log file. The same approach works wrapped in nohup or a systemd unit if you want it running headlessly:

[Unit]
Description=POCSAG/FLEX pager monitor
After=network-online.target

[Service]
Type=simple
User=pi
ExecStart=/bin/bash -c '/usr/bin/rtl_fm -f 152.840M -M fm -s 22050 -g 35 - | /usr/bin/multimon-ng -t raw -a POCSAG1200 -a FLEX -f alpha /dev/stdin >> /home/pi/pager-log.txt 2>&1'
Restart=on-failure

[Install]
WantedBy=multi-user.target

Drop that at /etc/systemd/system/pager-monitor.service, then sudo systemctl enable --now pager-monitor. journalctl -u pager-monitor -f tails the live decode.

8. (Optional) Monitor multiple channels with one SDR

A single RTL-SDR can only tune one center frequency at a time. If you want to monitor several pager channels simultaneously, you have two clean options:

  • A second RTL-SDR — run a second rtl_fm | multimon-ng pipeline with -d 1 (device index 1) pointing at a different channel.
  • Wider sample rate + DSP demux — set rtl_fm to 1.8 MS/s and demodulate multiple channels in parallel with gnuradio or rtlsdr-airband (which despite the name handles any narrowband FM channel set). This is more work to set up and outside the scope of this guide.

For most enthusiasts, two RTL-SDRs at $40 each is the lower-friction path.

Common gotchas

Message rate is reasonable but the alphanumeric text is gibberish. Almost always a baud-rate mismatch. The same capcode might use POCSAG512 some messages and POCSAG1200 others depending on which terminal sent the page. Always pass -a POCSAG512 -a POCSAG1200 -a POCSAG2400 to let multimon-ng pick the right one per message.

Decodes work for the first few minutes then stop. USB power dropout on the RTL-SDR, especially on a Pi 4 with bus-powered dongles. Use a powered USB hub. Confirm with dmesg | tail -20 — you'll see "USB disconnect" / "USB reset" events lining up with the moment the decode died.

multimon-ng reports couldn't open audio device or similar. You piped the wrong format. rtl_fm outputs raw signed 16-bit little-endian mono PCM by default; multimon-ng reads that with -t raw and treats /dev/stdin as the source. Don't add -a flags that don't match POCSAG (e.g., -a SCOPE will produce noise; -a AFSK1200 is for APRS, not pagers).

FLEX decode is mostly empty but POCSAG works fine. FLEX uses ~25 kHz FSK deviation vs POCSAG's ~4.5 kHz — rtl_fm's default narrow-FM filter might be too tight. Add -r 22050 (resample after filter) explicitly, or widen sample rate to 48000 and retest.

Privacy-sensitive content shows up. Hospital pagers carry patient room numbers, condition codes, and sometimes names. This is a real ethical / legal issue (HIPAA does not apply to you listening, but it does apply to the originating organization — and publishing the content can create liability). Pause and think before recording, sharing, or even discussing specifics. The point of this guide is the technical decode; what you do with the content is on you.

What to do next

For a visual-first approach to the same protocol, SDR++ has an experimental multimon-ng integration where you tune visually and the decoded messages appear in a side panel. Pair this guide with the airband guide for fire/EMS dispatch cross-reference — many fire departments use both VHF voice and pagers during the same incident, and watching them simultaneously builds a much richer mental model. The SignalIdent wiki POCSAG entry is the best reference for protocol internals and is worth reading once if you want to understand the framing. To extend into other narrowband digital protocols (ACARS for aircraft, AIS for ships, APRS for ham radio), multimon-ng is the gateway tool — most of the recipes follow the same rtl_fm | multimon-ng pattern with a different -a mode.

Local DIY vs. Squelch Deck

DimensionLocal DIYSquelch Deck
Setup time1–2 hours~1 minute (tap the app)
Hardware cost~$55–$65One device
Ongoing maintenanceOS updates, dependency drift, debugging when it breaksApp updates roll through the Squelch Deck catalog
Customization ceilingTotal — you own the stackBounded by what apps support; you can build new apps
Skill requiredLinux CLI, basic understanding of FM demodulationTouchscreen
Best forHobbyists who want to script logging and post-process pager contentPeople who want it to work on a dedicated box
Join the list

Sources we drew from