Source: https://mokxi.com/libraries/pubsubclient
Updated: 2026-11-02

Libraries / Network
Arduino library · Network

# PubSubClient: MQTT publish and subscribe from an ESP32

PubSubClient is Nick O’Leary’s MQTT client, the one most ESP32 and ESP8266 home automation tutorials use to talk to Mosquitto, HiveMQ or Home Assistant. It does not own the network: you hand it a WiFiClient (or an EthernetClient) and it speaks MQTT 3.1.1 over that TCP connection, so the same sketch works over any network the board has.

Open the example in the editor See the calls

Built in on Mokxi: #include <PubSubClient.h> and it builds, with nothing to install. Free, and no account needed.

## What PubSubClient does

The model is a broker in the middle. The board connects with a client ID, publishes short messages to topics such as home/kitchen/temp, and subscribes to topics it wants to hear about; a message arrives in the callback you registered with setCallback(), but only while loop() keeps getting called, because client.loop() is where incoming packets are read and the keepalive ping is sent.

Two limits catch people. A whole packet (topic plus payload plus a few header bytes) must fit in a 256-byte buffer unless you call setBufferSize(), and anything bigger is dropped without an error. And QoS 1 and 2 are only for subscribing: publish() always sends QoS 0.

Library Manager name | PubSubClient

Author | Nick O’Leary

Include | #include <PubSubClient.h>

Boards | ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32, ESP8266 NodeMCU, Raspberry Pi Pico W, Arduino Uno R4 WiFi

In the simulator | Builds and runs, and says plainly that the hardware behind it is not simulated.

## Install it

It builds on ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32, ESP8266 NodeMCU, Raspberry Pi Pico W, Arduino Uno R4 WiFi.

In Mokxi it is built in: #include <PubSubClient.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "PubSubClient" by Nick O’Leary from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add PubSubClient to lib_deps in PlatformIO. Mokxi follows the calls of release 2.8, so a sketch written here builds there too.

What to know in the simulator: No MQTT broker is reachable: the simulated network carries HTTP only, so connect() fails with state() -2 (connect failed) and prints one line saying why.

ESP32-C3 · ESP32-C6 · Seeed XIAO ESP32-C3 · ESP32-C3 SuperMini · Seeed XIAO ESP32-C6 · ESP32 DevKit · ESP32-DevKitC V4 · LOLIN32 Lite · Wemos D1 R32 · Cheap Yellow Display · TTGO T-Display · ESP32-S3-DevKitC-1 · Seeed XIAO ESP32-S3 · Arduino Nano ESP32 · ESP8266 NodeMCU · Raspberry Pi Pico W · Arduino Uno R4 WiFi

## The calls you will use

In the order a sketch meets them.

### PubSubClient client(espClient)

Creates the MQTT client on top of a network client you declared first, usually WiFiClient espClient.

### client.setServer("broker.hivemq.com", 1883)

Names the broker by host name or IPAddress and port. 1883 is plain MQTT; 8883 needs a WiFiClientSecure underneath.

### client.setCallback(callback)

Registers the function that receives messages: void callback(char* topic, byte* payload, unsigned int length). The payload is not null-terminated, so use length.

### client.connect("kitchen-node", "user", "pass")

Opens the session with a client ID and optional user name and password. Returns true on success; on failure state() says why.

### client.subscribe("home/led")

Asks the broker for every message on a topic. Wildcards work: home/+/temp for one level, home/# for everything below. Subscribe again after each reconnect.

### client.publish("home/temp", "21.5")

Sends a message to a topic and returns false when it is not connected or the packet is too big. A third argument, true, asks the broker to keep it as the retained value.

### client.loop()

Reads incoming messages, runs the callback and keeps the connection alive. Call it on every pass of loop() and keep delay() calls short.

### client.state()

The last result: 0 connected, -1 disconnected, -2 connect failed, -3 connection lost, -4 timeout, and 1 to 5 for a broker that refused (5 is not authorized).

### client.setBufferSize(512)

Grows the packet buffer from 256 bytes, for JSON payloads or long topics. Returns false if the RAM is not there.

## Example: MQTT, and why it cannot connect here

On the ESP32-C3-DevKitM-1. It runs in the browser exactly as printed.

sketch.ino · ESP32-C3-DevKitM-1

Open it in the editor, wired and ready to run

## Common errors and how to fix them

### failed, rc=-2

The TCP connection to the broker never opened. Check the host name and port, that the board really has WiFi (WiFi.status() == WL_CONNECTED), and that the broker accepts plain connections on 1883. In Mokxi this is always the result, since no broker is reachable from the simulated network.

### publish() returns false for a JSON message that looks fine

The packet is over the 256-byte default. Call client.setBufferSize(512) or larger before connect(), or shorten the topic and payload. The library drops oversize messages in both directions without telling you.

### The board connects, then drops every 15 seconds with rc=-4 or -3

client.loop() is not being called often enough to answer the broker’s keepalive, usually because of a long delay() or a blocking sensor read. Replace delay() with a millis() timer and call loop() every pass.

### Two boards keep kicking each other off the broker

They use the same client ID, and a broker allows one session per ID. Give each board its own, for example by adding the chip ID or MAC address to the ID string.

## Questions and answers

### Why does my callback never run?

Either subscribe() was called before connect() succeeded, or client.loop() is not running. Subscribe inside the reconnect code, right after connect() returns true, and call loop() on every pass.

## Keep going

### Learn

- ESP32 Not Connecting to WiFi: Causes and Fixes
- Connect a Board to WiFi and Serve a Page

### More network libraries

- MQTT
- Blynk
- ThingSpeak
- WiFiManager
- WiFi, HTTPClient and WebServer (ESP32 core)

Every built-in library · Open the editor

## Try PubSubClient without installing anything

Open the example, change the sketch, and keep your version in a free account.

Start building free

Open the editor
