BROWSER MQTT GUIDE
MQTT, WebSocket, or MQTT over WSS? Choose by responsibility
Choose MQTT when clients need brokered topics, QoS, and session behavior. Choose native WebSocket for one custom browser-to-server channel whose semantics your application owns. Choose MQTT over WSS when a browser must join the same MQTT topic and policy model as devices.
Choose the smallest complete model
Decide from the messaging responsibility the product needs, not from the fact that every option can keep a connection open.
Choose native WebSocket
Choose MQTT over WSS
Keep protocol layers and owners explicit
MQTT over WSS combines protocols; it does not replace MQTT with WebSocket or transfer application responsibilities to the transport.
MQTT over TLS/TCP
For native devices and services that can open TCP sockets.
- Application payload
- MQTT topics, QoS, session
- TLS → TCP
Native WebSocket
For a custom browser-to-application-server channel.
- Application-defined messages and recovery
- WebSocket frames
- TLS → TCP
MQTT over WSS
For browser MQTT clients that connect to a broker listener.
- Application payload
- MQTT topics, QoS, session
- WebSocket frames
- TLS → TCP
| Responsibility | MQTT | WebSocket | MQTT over WSS |
|---|---|---|---|
| Message semantics | Broker topics, QoS, retained messages, and sessions | The application defines routing, acknowledgments, replay, and message meaning | MQTT semantics remain unchanged inside WebSocket frames |
| Identity and authorization | Broker client identity and publish/subscribe policy | Application session plus authorization for every custom message action | TLS protects transport; broker identity and topic policy still apply |
| Disconnect recovery | Client reconnect plus explicit clean or persistent MQTT session behavior | Application rebuilds state, subscriptions, and missed-message handling | Restore WSS first, then reconnect MQTT and resume or recreate subscriptions |
Run a fixed-sandbox MQTT.js loopback
This example is intentionally locked to the RunMQTT public sandbox. Replace only the two public-sandbox placeholders with the current shared test credentials shown on the Public Broker page.
import mqtt from "mqtt";
const endpoint = "wss://public.runmqtt.com/mqtt";
const suffix = crypto.randomUUID().replaceAll("-", "");
const topic = `runmqtt/sandbox/${suffix}/loopback`;
const payload = JSON.stringify({
source: "runmqtt-wss-guide",
value: 42,
});
const client = mqtt.connect(endpoint, {
clientId: `runmqtt-guide-${suffix}`,
username: "<PUBLIC_SANDBOX_USERNAME>",
password: "<PUBLIC_SANDBOX_PASSWORD>",
clean: true,
connectTimeout: 10_000,
reconnectPeriod: 3_000,
protocolVersion: 4,
});
client.on("connect", async () => {
await client.subscribeAsync(topic, { qos: 1 });
await client.publishAsync(topic, payload, { qos: 1 });
});
client.on("message", (_topic, _payload) => {
console.info("Synthetic QoS 1 loopback received");
});
client.on("reconnect", () => console.info("Reconnecting"));
client.on("close", () => console.info("Disconnected"));
client.on("error", () => console.error("MQTT connection failed"));
export async function disconnect() {
await client.endAsync();
}
window.addEventListener("pagehide", () => client.end(true));Treat connection, reconnect, and MQTT state separately
A successful WebSocket upgrade is only the transport prerequisite. The client still completes MQTT CONNECT and restores the intended subscription state.
- 01
Connect WSS, then MQTT
Validate the public TLS certificate, upgrade /mqtt to WebSocket, authenticate MQTT, and wait for the MQTT connect event before subscribing or publishing.
- 02
Reconnect and restore intent
After an unexpected close, MQTT.js opens a new WSS channel and sends MQTT CONNECT again. With clean: true, subscribe again from the connect handler.
- 03
Disconnect deliberately
End the MQTT client when the page is leaving or the user stops the session. Do not leave reconnect timers or hidden subscriptions running.
Reproducible RunMQTT sandbox evidence
Verified on 2026-08-10 with MQTT.js 5.15.2 using MQTT 3.1.1 and certificate validation enabled. These checks establish compatibility for the documented sandbox; they are not a performance result or SLA.
| Verification check | Result | Scope |
|---|---|---|
| Browser WSS open | Chromium 142, Firefox 150, and WebKit 26.4 opened the fixed WSS endpoint without bypassing TLS validation. | wss://public.runmqtt.com/mqtt |
| MQTT QoS 1 round trip | Publish and subscribe loopbacks completed over plain MQTT 1883, MQTT TLS 8883, and WSS 443. | Current shared credentials and synthetic random topics |
| Relay guardrail | The five-minute health check requires Cloudflare and Google DoH to resolve the public hostname to the relay IP, then validates certificate names, relay listeners, hostname matching, and a real /mqtt WebSocket upgrade. | Deployment check every five minutes |
Choose transport by runtime and message contract
The same product may use MQTT over TLS for devices, MQTT over WSS for a browser console, and native WebSocket for a separate application-specific live UI.
| Scenario | Prefer | Reason | Production boundary |
|---|---|---|---|
| Browser MQTT console | MQTT over WSS | The browser joins the same topics, QoS, and broker policy model as MQTT clients. | Use user-scoped or short-lived credentials; never ship a shared production secret in frontend code. |
| Mobile network client | MQTT over TLS for native apps; MQTT over WSS for browser runtimes | Choose the transport the runtime supports while preserving MQTT reconnect and topic behavior. | Test real network transitions and define backoff, session, and duplicate handling explicitly. |
| Device telemetry | MQTT over TLS/TCP | Native devices normally do not need the WebSocket framing layer to publish broker-routed telemetry. | Give every device a unique identity and least-privilege publish policy. |
| Command downlink | MQTT | Broker subscriptions, QoS, and session choices express device command delivery more directly than a custom socket channel. | Authorize command topics separately and design idempotent command handling. |
MQTT vs WebSocket FAQ
Are MQTT and WebSocket the same type of protocol?
No. MQTT defines application-level messaging semantics. WebSocket provides a persistent bidirectional channel. MQTT can use WebSocket as one of its transports.
Can a browser connect directly to MQTT?
A browser cannot open an arbitrary raw TCP socket. A browser MQTT client connects to a broker WebSocket listener, normally over WSS, and exchanges MQTT packets inside WebSocket frames.
Does WSS reconnect restore MQTT subscriptions automatically?
Not by itself. WebSocket only restores the channel. The MQTT client must reconnect, then rely on a resumed MQTT session or subscribe again. The sandbox example uses a clean session and subscribes on every connect.
Is WebSocket faster than MQTT?
There is no responsible universal answer. Compare the complete application path, including routing, authorization, delivery, recovery, and the network in which it will run; this guide makes no performance or SLA claim.
Implement the next boundary
Try the fixed sandbox, then deepen MQTT fundamentals, production security, and the backend event-streaming boundary.
Public broker WSS tester
Run a no-input synthetic loopback against the verified fixed endpoint.
MQTT tutorial
Build a complete publish-subscribe flow with QoS and topics.
MQTT security
Protect TCP and WSS clients with TLS, unique identity, and topic policy.
MQTT vs Kafka
Separate device messaging from durable backend event streaming.