Using the retained message flag in MQTT with Python

This script subscribes to an MQTT topic and prints the retained flag for each received message, demonstrating how to distinguish retained messages from normal ones.

Easy Python 3.9+ Aug 9, 2026 Streaming & messaging 14 views 0 copies

Requires third-party packages — install first
pip install paho-mqtt

Python code

32 lines
Python 3.9+
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    # Subscribe to a topic and check retained flag
    client.subscribe("test/retained")
    print("Subscribed to test/retained")

def on_message(client, userdata, msg):
    # msg.retain is the MQTT retained flag (True if retained, False if normal)
    print(f"Topic: {msg.topic}")
    print(f"Payload: {msg.payload.decode()}")
    print(f"Retained flag: {msg.retain}")
    print("-" * 30)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("test.mosquitto.org", 1883, 60)
client.loop_start()

# Publish a normal message (retained=False)
client.publish("test/retained", "normal message", retain=False)

# Publish a retained message (retained=True)
client.publish("test/retained", "retained message", retain=True)

import time
time.sleep(2)
client.loop_stop()
client.disconnect()

Output

stdout
Connected with result code 0
Subscribed to test/retained
Topic: test/retained
Payload: normal message
Retained flag: False
------------------------------
Topic: test/retained
Payload: retained message
Retained flag: True
------------------------------

How it works

The on_connect callback is triggered when a connection is established; here we subscribe to the topic. The on_message callback receives each message, and msg.retain indicates whether it is a retained message (True) or a normal one (False). Retained messages are stored by the broker and sent to new subscribers, so the flag is crucial for handling stateful data. The script briefly sleeps to allow time for messages to be delivered before disconnecting.

Common mistakes

  • Forgetting to call `loop_start()` or `loop_forever()` to process incoming messages
  • Checking `msg.retain` on the publish side instead of the receive side
  • Assuming retained messages are resent to existing subscribers when updated — they are not

Variations

  1. Use `client.loop_forever()` in a blocking script instead of `loop_start()` with a sleep
  2. Publish with `retain=True` to set a last known good value for a sensor topic

Real-world use cases

  • An IoT device publishes its latest status with a retained flag so new subscribers instantly get the current state.
  • A home automation hub sends retained configuration topics that devices read upon connecting.
  • A monitoring service checks the retained flag to differentiate between stale cached data and live updates.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Streaming & messaging

Related tutorials and quizzes for this topic.