Skip to Content
helpersWebsocket

Last Updated: 3/7/2026


WebSocket Helper

WebSocket Helper is a helper for server-side WebSockets in Hono applications. Currently Cloudflare Workers / Pages, Deno, and Bun adapters are available.

Import

Cloudflare Workers:

import { Hono } from 'hono' import { upgradeWebSocket } from 'hono/cloudflare-workers'

Deno:

import { Hono } from 'hono' import { upgradeWebSocket } from 'hono/deno'

Bun:

import { Hono } from 'hono' import { upgradeWebSocket, websocket } from 'hono/bun' export default { fetch: app.fetch, websocket, }

If you use Node.js, you can use @hono/node-ws .

upgradeWebSocket()

upgradeWebSocket() returns a handler for handling WebSocket.

const app = new Hono() app.get( '/ws', upgradeWebSocket((c) => { return { onMessage(event, ws) { console.log(`Message from client: ${event.data}`) ws.send('Hello from server!') }, onClose: () => { console.log('Connection closed') }, } }) )

Available events:

  • onOpen - Currently, Cloudflare Workers does not support it.
  • onMessage
  • onClose
  • onError

If you use middleware that modifies headers (e.g., applying CORS) on a route that uses WebSocket Helper, you may encounter an error saying you can’t modify immutable headers. This is because upgradeWebSocket() also changes headers internally.

RPC-mode

Handlers defined with WebSocket Helper support RPC mode.

// server.ts const wsApp = app.get( '/ws', upgradeWebSocket((c) => { //... }) ) export type WebSocketApp = typeof wsApp // client.ts const client = hc<WebSocketApp>('http://localhost:8787') const socket = client.ws.$ws() // A WebSocket object for a client

Examples

Server and Client

// server.ts import { Hono } from 'hono' import { upgradeWebSocket } from 'hono/cloudflare-workers' const app = new Hono().get( '/ws', upgradeWebSocket(() => { return { onMessage: (event) => { console.log(event.data) }, } }) ) export default app
// client.ts import { hc } from 'hono/client' import type app from './server' const client = hc<typeof app>('http://localhost:8787') const ws = client.ws.$ws(0) ws.addEventListener('open', () => { setInterval(() => { ws.send(new Date().toString()) }, 1000) })