Skip to main content

ft8decoder

Ask DeepWiki

ft8decoder is a Python-based tool for decoding, translating, and organizing FT8 digital radio communications in real-time. It listens for UDP packets broadcast by WSJT-X, parses the cryptic messages into human-readable text, sorts them into distinct conversations (QSOs), and provides options to export the captured data into structured JSON files or visualize them on a world map.

This tool is perfect for amateur radio enthusiasts who want to log, understand, and analyze FT8 communications happening on the bands.

Key Features

  • Live Packet Listening: Connects directly to the WSJT-X UDP stream to process radio traffic as it happens.
  • Message Parsing & Translation: Decodes standard FT8 messages, including CQ calls, grid squares, signal reports, and sign-offs, translating them into plain English.
  • Conversation Tracking: Intelligently groups individual transmissions into complete conversations (QSOs) from the initial CQ call to the final "73".
  • Data Exporting: Saves all captured communications, including completed QSOs, unanswered CQs, and miscellaneous messages, into a well-structured JSON file for logging or further analysis.
  • Geographic Visualization: Generates a dynamic HTML map using Folium, plotting the locations of operators (via Maidenhead grid squares) and drawing lines to represent their QSOs.

How It Works

The application is built around two core components:

  1. WsjtxParser: This class is responsible for the low-level networking. It binds to the specified UDP port that WSJT-X uses to broadcast its data. It listens for incoming packets, validates them, and unpacks the binary data into a structured Packet object containing details like SNR, frequency, time delta, and the raw message content.

  2. MessageProcessor: This class handles the logic of understanding the parsed packets. It ingests a stream of Packet objects and organizes them:

    • CQ Calls: Identifies and logs general "CQ" calls.
    • QSO Assembly: When a station responds to a CQ, a new conversation thread is started. The processor tracks each turn of the conversation, from grid square exchange to signal reports and final acknowledgments (RR73, 73).
    • Translation: Each message type is translated into a descriptive sentence (e.g., N5YHF WB7SRC R+05 becomes "WB7SRC says Roger and reports a signal report of +05 to N5YHF.").
    • Grid Square Caching: It caches the grid square of each station heard to resolve their location for mapping, even if they don't repeat it in every transmission.

Installation

Ensure you have Python 3.8+ and a running instance of WSJT-X.

  1. Install from PyPI (recommended):

    pip install ft8decoder
    

    This will install the package and its dependencies (maidenhead and folium).

  2. Install from source:

    git clone https://github.com/ZappatheHackka/ft8decoder.git
    cd ft8decoder
    pip install .
    

    For development, install Poetry and run:

    pip install poetry
    poetry install
    
  3. Configure WSJT-X: In WSJT-X, go to File > Settings > Reporting. Ensure the "UDP Server" is enabled and set to 127.0.0.1:2237, which are the defaults for this tool.

Python API Usage

You can use the core classes directly in your Python code in the following manner:

from ft8decoder import WsjtxParser, MessageProcessor
import time

# Get HOST and PORT from WSJT-X settings
HOST = '127.0.0.1'
PORT = 2237

# Initialize parser with your desired dial frequency
parser = WsjtxParser(dial_frequency=14.074000)

# Initialize processor
processor = MessageProcessor()

# Pass the HOST, PORT, and processor into the parser and begin listening
parser.start_listening(HOST, PORT, processor)

# Start the processor
processor.start()

# Sleep for however long you want to compile data for
time.sleep(180)

# Access the parsed and processed data
print("All captured packets:", processor.master_data)
processor.to_map('map1', all_cqs=True)
processor.to_json(filename="ft8_data")

CLI Usage

The application also includes an easy command-line interface. The primary command is ft8decoder listen.

Basic CLI Usage

To start listening to packets, run the following command. It will listen for 2 minutes (120 seconds) and then print the captured data.

ft8decoder listen

Command-Line Arguments

You can customize the behavior with the following arguments:

  • --host: The host IP to bind to (default: 127.0.0.1).
  • --port: The UDP port to listen on (default: 2237).
  • --dial: Your radio's dial frequency in MHz for accurate frequency calculation (default: 14.074000).
  • --interval: The interval in seconds for processing collected packets (default: 5).
  • --duration: Total listening duration in seconds before the program exits and exports data (default: 120).
  • --export-all <filename>: Export all captured data (QSOs, CQs, Misc.) to a specified JSON file.
  • --export-comms <filename>: Export only conversation data to a JSON file.
  • --export-cqs <filename>: Export only unanswered CQ calls to a JSON file.
  • --export-misc <filename>: Export only miscellaneous messages.
  • --to-map <filename>: Generate an interactive HTML map visualizing the QSOs and CQs.

Example

Listen for 5 minutes, export all data to my_log.json, and create a map named activity_map.html:

ft8decoder listen --duration 300 --export-all my_log.json --to-map activity_map

After running, you will find my_log.json and activity_map.html in your directory.

Sample Output

JSON Data

      "('KF5WCP', 'KT4KB')": [
        {
          "completed": true
        },
        {
          "turn": 1,
          "message": "CQ KT4KB EM94",
          "translated_message": "Station KT4KB is calling for any response from grid EM94.",
          "packet": {
            "snr": 1,
            "delta_time": 0.5,
            "frequency_offset": 831,
            "frequency": 14.074831,
            "band": "20m",
            "message": "CQ KT4KB EM94",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:17:56.951461",
            "packet_type": 2
          },
          "type": "CQ Call."
        },
        {
          "turn": 2,
          "message": "KT4KB KF5WCP EM25",
          "translated_message": "KF5WCP sends a grid square location of EM25 to KT4KB.",
          "packet": {
            "snr": -5,
            "delta_time": 0.30000001192092896,
            "frequency_offset": 710,
            "frequency": 14.07471,
            "band": "20m",
            "message": "KT4KB KF5WCP EM25",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:18:11.935844",
            "packet_type": 2
          },
          "type": "Grid Square Report"
        },
        {
          "turn": 3,
          "message": "KF5WCP KT4KB -16",
          "translated_message": "KT4KB sends a signal report of -16 to KF5WCP.",
          "packet": {
            "snr": 8,
            "delta_time": 0.5,
            "frequency_offset": 830,
            "frequency": 14.07483,
            "band": "20m",
            "message": "KF5WCP KT4KB -16",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:18:26.962332",
            "packet_type": 2
          },
          "type": "Signal Report"
        },
        {
          "turn": 4,
          "message": "KT4KB KF5WCP R-19",
          "translated_message": "KF5WCP says Roger and reports a signal report of -19 to KT4KB.",
          "packet": {
            "snr": 1,
            "delta_time": 0.30000001192092896,
            "frequency_offset": 710,
            "frequency": 14.07471,
            "band": "20m",
            "message": "KT4KB KF5WCP R-19",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:18:41.909084",
            "packet_type": 2
          },
          "type": "Signal Report"
        },
        {
          "turn": 5,
          "message": "KF5WCP KT4KB RR73",
          "translated_message": "KT4KB sends a Roger Roger to KF5WCP and says goodbye, concluding the connection.",
          "packet": {
            "snr": 3,
            "delta_time": 0.5,
            "frequency_offset": 831,
            "frequency": 14.074831,
            "band": "20m",
            "message": "KF5WCP KT4KB RR73",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:18:56.898584",
            "packet_type": 2
          },
          "type": "RR & Goodbye"
        },
        {
          "turn": 6,
          "message": "KT4KB KF5WCP 73",
          "translated_message": "KF5WCP sends their well wishes to KT4KB, concluding the connection.",
          "packet": {
            "snr": 6,
            "delta_time": 0.30000001192092896,
            "frequency_offset": 711,
            "frequency": 14.074711,
            "band": "20m",
            "message": "KT4KB KF5WCP 73",
            "schema": 2,
            "program": "WSJT-X",
            "time_captured": "2025-08-08 10:19:11.914567",
            "packet_type": 2
          },
          "type": "Goodbye"
        }
      ],

Full JSON file HERE

Folium Map

Sample QSO Map Data

Sample CQ Map Data

Project Structure

  • ft8decoder/: The main source code package.
    • cli.py: Defines the command-line interface using argparse.
    • parser.py: Contains the WsjtxParser for handling UDP packets.
    • processor.py: Contains the MessageProcessor for logic, translation, and data organization.
    • core.py: Core dataclasses for Packet, MessageTurn, and CQ.
  • tests/: Unit tests for the parser and processor logic.
  • setup.py: Package setup and dependency information.
  • all_comms.json: An example JSON output file containing captured data.
  • map.html: An example map generated by the tool.

Documentation

For the fully comprehensive documentation, click HERE

Metadata

Release files for ft8decoder 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ft8decoder 1.0.0
File Size Uploaded
ft8decoder-1.0.0.tar.gz 23.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ft8decoder 1.0.0
File Interpreter ABI Platform
ft8decoder-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 47.2 kB

Release files / ft8decoder-1.0.0.tar.gz

Download URL ft8decoder-1.0.0.tar.gz
Size 23.8 kB
Tags Source
SHA-256 checksum
How to use checksums
2d19bd4b6e00e7923ca39829cabaef49ab72aaea90ceb43e96651f528f50c03d
BLAKE2b-256 checksum
How to use checksums
5e70f3cdff8b355b38c495e18db4b88cd3f7713e044b19fe0da6fbac5fc282da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.6

Release files / ft8decoder-1.0.0-py3-none-any.whl

Download URL ft8decoder-1.0.0-py3-none-any.whl
Size 23.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8de4288146f1f063121b9b55359c0db083e5576daffb8e9efc9131331b6129d0
BLAKE2b-256 checksum
How to use checksums
f77cec13fc3a3a06ed5dbb1aacd34ef4954a52354f7ab97670ad0354ea859bfc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.6

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page