MIDI, standardized in 1983, is still how keyboards, drum pads and synthesizers talk: three-byte messages such as [0x90, 60, 100] (note on, middle C, velocity 100). navigator.requestMIDIAccess() asks permission and resolves to a MIDIAccess whose inputs and outputs maps hold the connected ports. Set input.onmidimessage = (e) => output.send(e.data) to loop a keyboard through, or schedule a note-off with output.send([0x80, 60, 0], performance.now() + 500); statechange reports devices being plugged in. Test on a desktop with a USB instrument; headless Chrome 1 denies the permission, and Safari 10 lacks the API. WEBMIDI.js 1,715 (https://github.com/djipco/webmidi 1,715 ) (npm 2,036 i webmidi, Apache-2.0) hides the raw bytes behind methods such as playNote().