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 MQTT

Use MQTT when devices and services need brokered topics, fan-out, QoS, retained state, or session behavior. Native clients normally use MQTT over TLS/TCP.

Choose native WebSocket

Use native WebSocket when one browser and one application server need a custom live channel and the application will own routing, authorization, acknowledgment, and recovery.

Choose MQTT over WSS

Use MQTT over WSS when browser code must participate in the broker's MQTT topics, QoS, identity, and policy model through a browser-compatible secure transport.

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.

  1. Application payload
  2. MQTT topics, QoS, session
  3. TLS → TCP

Native WebSocket

For a custom browser-to-application-server channel.

  1. Application-defined messages and recovery
  2. WebSocket frames
  3. TLS → TCP

MQTT over WSS

For browser MQTT clients that connect to a broker listener.

  1. Application payload
  2. MQTT topics, QoS, session
  3. WebSocket frames
  4. TLS → TCP
Responsibility
ResponsibilityMQTTWebSocketMQTT over WSS
Message semanticsBroker topics, QoS, retained messages, and sessionsThe application defines routing, acknowledgments, replay, and message meaningMQTT semantics remain unchanged inside WebSocket frames
Identity and authorizationBroker client identity and publish/subscribe policyApplication session plus authorization for every custom message actionTLS protects transport; broker identity and topic policy still apply
Disconnect recoveryClient reconnect plus explicit clean or persistent MQTT session behaviorApplication rebuilds state, subscriptions, and missed-message handlingRestore 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.

MQTT.js · fixed WSS endpoint · synthetic data only
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));
The endpoint is fixed; there is no arbitrary broker input.
The topic, Client ID, and JSON payload are synthetic and unique to the page run.
Shared sandbox credentials are for disposable testing, not production deployment.
A random topic reduces accidental collisions but does not create privacy on a shared broker.
Use the no-input browser tester

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.

  1. 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.

  2. 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.

  3. 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
Verification checkResultScope
Browser WSS openChromium 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 tripPublish and subscribe loopbacks completed over plain MQTT 1883, MQTT TLS 8883, and WSS 443.Current shared credentials and synthetic random topics
Relay guardrailThe 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
Repeat the fixed-sandbox check

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
ScenarioPreferReasonProduction boundary
Browser MQTT consoleMQTT over WSSThe 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 clientMQTT over TLS for native apps; MQTT over WSS for browser runtimesChoose 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 telemetryMQTT over TLS/TCPNative 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 downlinkMQTTBroker 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.