Um MQTT über WebSockets zu testen, prüfst du die Verbindung in zwei Stufen: zuerst das HTTP-Upgrade (richtige URL, richtiger Pfad, Subprotokoll mqtt, 101 Switching Protocols), dann eine echte MQTT-Sitzung im Socket (CONNECT, CONNACK, Publish, Subscribe). Die meisten WebSocket-Probleme — 404, geschlossene Sockets, Mixed-Content-Blockaden — passieren in der ersten Stufe, bevor MQTT überhaupt ins Spiel kommt.
Die Beispiele nutzen broker.connectmq.com: ws:// auf Port 8083 und wss:// auf Port 8084, jeweils mit dem Pfad /mqtt.
So sieht eine funktionierende MQTT-WebSocket-Verbindung aus
Eine MQTT-WebSocket-URL besteht aus vier Teilen, und jeder davon kann falsch sein:
| Teil | Beispiel | Typischer Fehler |
|---|---|---|
| Schema | wss:// | ws:// aus einer HTTPS-Seite (als Mixed Content blockiert) |
| Host | broker.connectmq.com | IP-Adresse mit wss — Zertifikat passt nicht |
| Port | 8084 | TCP-Port 1883 oder TLS-Port 8883 verwendet |
| Pfad | /mqtt | Fehlender oder falscher Pfad — 404 Not Found |
Der Client sendet außerdem den Header Sec-WebSocket-Protocol: mqtt. Der Broker muss mit HTTP/1.1 101 Switching Protocols antworten und Sec-WebSocket-Protocol: mqtt zurückgeben. Danach transportiert der Socket ganz normale binäre MQTT-Pakete — dasselbe CONNECT und CONNACK wie über TCP. Hintergründe findest du unter MQTT über WebSockets.
Stufe 1: den Handshake testen
Mit curl
curl kann den Upgrade-Request von Hand senden und die rohe Antwort anzeigen. So trennst du den HTTP-Teil von jeder MQTT-Bibliothek:
curl -i --http1.1 --max-time 5 \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Protocol: mqtt" \
https://broker.connectmq.com:8084/mqttMit http://...:8083/mqtt testest du den unverschlüsselten Listener. Ein gesunder Endpunkt antwortet:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: mqttAnschließend wartet curl bis --max-time, weil der Socket offen bleibt — das ist so gewollt. Andere Antworten zeigen dir, was zu reparieren ist:
| Antwort | Bedeutung |
|---|---|
101 ohne Sec-WebSocket-Protocol: mqtt | Broker oder Proxy verwirft das Subprotokoll; Browser schließen den Socket |
404 Not Found | Falscher Pfad — probiere /mqtt, / oder den dokumentierten Pfad deines Brokers (Details) |
400 Bad Request / 426 Upgrade Required | Upgrade-Header fehlen — oft ein Proxy, der sie nicht weiterreicht |
502 Bad Gateway | Der Reverse Proxy erreicht den WebSocket-Listener des Brokers nicht |
Empty reply from server oder Reset | Der Port spricht normales MQTT/TLS, kein WebSocket |
| SSL-Zertifikatsfehler | Dieselben TLS-Probleme wie auf 8883 — das Zertifikat muss zum Hostnamen passen |
Steht der Broker hinter Nginx oder einem anderen Proxy, bedeuten ein 400 oder ein fehlendes Subprotokoll fast immer, dass die Header Upgrade und Connection nicht durchgereicht werden — siehe MQTT hinter einem Nginx-Proxy.
Mit wscat
wscat ist ein kleiner WebSocket-Client, der das Subprotokoll korrekt aushandelt:
npx wscat -c wss://broker.connectmq.com:8084/mqtt -s mqttConnected (press CTRL+C to quit) bedeutet: Handshake und Subprotokoll sind in Ordnung. Nach ein paar Sekunden schließt der Broker den Socket, weil kein MQTT-CONNECT-Paket kam — das ist normal und bestätigt sogar, dass dort ein MQTT-Broker lauscht. Ohne -s mqtt lehnen viele Broker das Upgrade ab, was sich gut als Negativtest eignet.
Stufe 2: eine echte MQTT-Sitzung testen
Die mosquitto-Kommandozeilen-Clients können sich nicht über WebSockets verbinden, also brauchst du einen WebSocket-fähigen Client. Am schnellsten geht es mit dem Online-MQTT-Client: wss://-URL eingeben, verbinden, ein Test-Topic abonnieren und darauf publishen. Klappt das, ist die Broker-Seite korrekt und jedes verbleibende Problem liegt in deiner Anwendung.
Für einen automatisierten Check läuft dieses MQTT.js-5-Skript in Node.js oder fast unverändert im Browser:
import mqtt from "mqtt";
const url = "wss://broker.connectmq.com:8084/mqtt";
const topic = `testmqtt/ws/${Math.random().toString(16).slice(2, 10)}`;
const client = mqtt.connect(url, {
protocolVersion: 5,
username: process.env.MQTT_USER,
password: process.env.MQTT_PASS,
connectTimeout: 5000,
reconnectPeriod: 0, // beim Testen schnell fehlschlagen
});
const started = Date.now();
client.on("connect", (connack) => {
console.log(`CONNACK reason ${connack.reasonCode ?? 0} after ${Date.now() - started} ms`);
client.subscribe(topic, { qos: 1 }, () => client.publish(topic, "ping over websocket", { qos: 1 }));
});
client.on("message", (t, payload) => {
console.log(`round trip ok on ${t}: ${payload}`);
client.end();
});
client.on("error", (err) => { console.error("error:", err.message); process.exit(1); });
client.on("close", () => console.log("socket closed"));MQTT.js setzt das Subprotokoll mqtt automatisch. Python geht genauso — paho-mqtt 2.x mit transport="websockets":
import os
import paho.mqtt.client as mqtt
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, transport="websockets", protocol=mqtt.MQTTv5)
c.ws_set_options(path="/mqtt")
c.tls_set() # für ws:// auf Port 8083 entfernen
c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect = lambda cl, u, f, rc, p: print("CONNACK:", rc)
c.connect("broker.connectmq.com", 8084)
c.loop_forever()Der Standard-WebSocket-Pfad von paho ist bereits /mqtt, ws_set_options ist hier also optional — Broker mit / oder einem eigenen Pfad antworten aber mit 404, bis du ihn explizit setzt.
Debugging mit den Browser-DevTools
Wenn sich eine Web-App nicht verbinden kann, zeigt dir der Browser jedes Detail des Handshakes:
- Öffne die DevTools → Network, filtere nach WS (Chrome) bzw. wähle WS im Typfilter (Firefox) und lade die Seite neu.
- Klick auf den Socket-Request. Prüfe unter Headers den Status (
101), URL und Pfad sowie, ob Request und ResponseSec-WebSocket-Protocol: mqttenthalten. - Öffne den Tab Messages (Chrome) bzw. Response (Firefox). Der erste ausgehende Frame ist das binäre MQTT-CONNECT, der erste eingehende das CONNACK. Geht das CONNECT raus und der Socket schließt ohne CONNACK, hat der Broker die MQTT-Sitzung abgelehnt (Zugangsdaten, Client-ID) — nicht den WebSocket.
- Such in der Console nach Fehlern wie diesen:
WebSocket connection to 'wss://broker.example.com:8084/mqtt' failed:
Mixed Content: The page at 'https://app.example.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://broker.example.com:8083/mqtt'. This request has been blocked; this endpoint must be available over WSS.Der erste, ohne Text nach dem Doppelpunkt, ist der generische Browserfehler — meist falscher Port, Pfad oder ein Zertifikatsproblem; schau in den Network-Tab. Der zweite lässt sich nur durch den Wechsel auf wss:// beheben (Mixed Content). Ein Close-Code 1006 bedeutet, dass die Verbindung ohne ordentlichen Close-Frame abgebrochen ist — oft ein Proxy-Timeout oder ein Broker, der die Verbindung ablehnt. Die vollständige Liste der Ursachen findest du unter MQTT WebSocket connection failed.
WebSocket-Test-Checkliste
- curl auf die
wss://-URL liefert101und gibtSec-WebSocket-Protocol: mqttzurück. - wscat mit
-s mqttverbindet sich; ohne lehnt der Broker ab oder schließt. - Ein echter Client erhält ein CONNACK und schafft einen Publish/Subscribe-Roundtrip.
- Der Browser verbindet sich von einer HTTPS-Seite mit
wss://, ohne Konsolenfehler. - Über deinen Proxy oder Load Balancer überleben inaktive Verbindungen länger als das Keep-Alive-Intervall.
- Zugangsdaten und ACLs verhalten sich auf dem WebSocket-Listener genauso wie auf TCP.
WebSocket-Endpunkt im Browser testen
WebSocket-Probleme wirken nur so lange mysteriös, bis du sie in zwei Teile zerlegst. Beweise das HTTP-Upgrade mit curl oder wscat, dann die MQTT-Sitzung mit einem echten Client — und du weißt in Minuten, ob URL, Proxy oder MQTT-Zugangsdaten zu korrigieren sind.
Häufig gestellte Fragen
Welchen WebSocket-Pfad nutzt MQTT?
Es gibt keinen einheitlichen Standard. /mqtt ist am verbreitetsten (EMQX, HiveMQ und ConnectMQ nutzen ihn, Proxys vor Mosquitto leiten ihn meist weiter), manche Broker lauschen aber auf / oder einem eigenen Pfad. Ein falscher Pfad liefert beim Handshake meist HTTP 404.
Welches WebSocket-Subprotokoll verwendet MQTT?
mqtt, sowohl für MQTT 3.1.1 als auch für MQTT 5. Alte MQTT-3.1-Clients nutzten mqttv3.1. Der Client sendet es in Sec-WebSocket-Protocol, und der Broker muss es in der 101-Antwort zurückgeben — sonst trennen Browser die Verbindung.
Kann sich mosquitto_pub über WebSockets verbinden?
Nein. Die mosquitto-Kommandozeilen-Clients sprechen MQTT nur über TCP und TLS. Zum Testen eines WebSocket-Listeners nimmst du einen Browser-Client, MQTT.js, paho-mqtt mit transport="websockets" oder einen Desktop-Client wie MQTTX.


