This is the unpublished documentation of wasm-bindgen, the published documentation is available on the main Rust and WebAssembly documentation site . Features documented here may not be available in released versions of wasm-bindgen.

WebSockets Example

View full source code or view the compiled example online

This example connects to an echo server on wss://, sends a ping message, and receives the response.


The Cargo.toml enables features necessary to create a WebSocket object and to access events such as MessageEvent or ErrorEvent.

name = "websockets"
version = "0.1.0"
authors = ["The wasm-bindgen Developers"]
edition = "2018"

crate-type = ["cdylib"]

wasm-bindgen = "0.2.68"
js-sys = "0.3"

version = "0.3.22"
features = [


This code shows the basic steps required to work with a WebSocket. At first it opens the connection, then subscribes to events onmessage, onerror, onopen. After the socket is opened it sends a ping message, receives an echoed response and prints it to the browser console.

# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{ErrorEvent, MessageEvent, WebSocket};

macro_rules! console_log {
    ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))

extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);

pub fn start_websocket() -> Result<(), JsValue> {
    // Connect to an echo server
    let ws = WebSocket::new("wss://")?;
    // For small binary messages, like CBOR, Arraybuffer is more efficient than Blob handling
    // create callback
    let cloned_ws = ws.clone();
    let onmessage_callback = Closure::wrap(Box::new(move |e: MessageEvent| {
        // Handle difference Text/Binary,...
        if let Ok(abuf) =<js_sys::ArrayBuffer>() {
            console_log!("message event, received arraybuffer: {:?}", abuf);
            let array = js_sys::Uint8Array::new(&abuf);
            let len = array.byte_length() as usize;
            console_log!("Arraybuffer received {}bytes: {:?}", len, array.to_vec());
            // here you can for example use Serde Deserialize decode the message
            // for demo purposes we switch back to Blob-type and send off another binary message
            match cloned_ws.send_with_u8_array(&vec![5, 6, 7, 8]) {
                Ok(_) => console_log!("binary message successfully sent"),
                Err(err) => console_log!("error sending message: {:?}", err),
        } else if let Ok(blob) =<web_sys::Blob>() {
            console_log!("message event, received blob: {:?}", blob);
            // better alternative to juggling with FileReader is to use
            let fr = web_sys::FileReader::new().unwrap();
            let fr_c = fr.clone();
            // create onLoadEnd callback
            let onloadend_cb = Closure::wrap(Box::new(move |_e: web_sys::ProgressEvent| {
                let array = js_sys::Uint8Array::new(&fr_c.result().unwrap());
                let len = array.byte_length() as usize;
                console_log!("Blob received {}bytes: {:?}", len, array.to_vec());
                // here you can for example use the received image/png data
                as Box<dyn FnMut(web_sys::ProgressEvent)>);
            fr.read_as_array_buffer(&blob).expect("blob not readable");
        } else if let Ok(txt) =<js_sys::JsString>() {
            console_log!("message event, received Text: {:?}", txt);
        } else {
            console_log!("message event, received Unknown: {:?}",;
    }) as Box<dyn FnMut(MessageEvent)>);
    // set message event handler on WebSocket
    // forget the callback to keep it alive

    let onerror_callback = Closure::wrap(Box::new(move |e: ErrorEvent| {
        console_log!("error event: {:?}", e);
    }) as Box<dyn FnMut(ErrorEvent)>);

    let cloned_ws = ws.clone();
    let onopen_callback = Closure::wrap(Box::new(move |_| {
        console_log!("socket opened");
        match cloned_ws.send_with_str("ping") {
            Ok(_) => console_log!("message successfully sent"),
            Err(err) => console_log!("error sending message: {:?}", err),
        // send off binary message
        match cloned_ws.send_with_u8_array(&vec![0, 1, 2, 3]) {
            Ok(_) => console_log!("binary message successfully sent"),
            Err(err) => console_log!("error sending message: {:?}", err),
    }) as Box<dyn FnMut(JsValue)>);