A Mido message is a Python object with methods and attributes. The attributes will vary depending on message type.

To create a new message:

>>> mido.Message('note_on')
Message('note_on', channel=0, note=0, velocity=64, time=0)

You can pass attributes as keyword arguments:

>>> mido.Message('note_on', note=100, velocity=3, time=6.2)
Message('note_on', channel=0, note=100, velocity=3, time=6.2)

All attributes will default to 0. The exceptions are velocity, which defaults to 64 (middle velocity) and data which defaults to ().

You can set and get attributes as you would expect:

>>> msg = mido.Message('note_on')
>>> msg.note

The type attribute can be used to determine message type:

>>> msg.type

Attributes are also settable but it’s always better to use msg.copy():

>>> msg.copy(note=99, time=100.0)
Message('note_on', channel=0, note=99, velocity=64, time=100.0)


Mido always makes a copy of messages instead of modifying them so if you do the same you have immutable messages in practice. (Third party libraries may not follow the same rule.)


Frozen Messages are a variant of messages that are hashable and can be used as dictionary keys. They are also safe from tampering by third party libraries. You can freely convert between the two and use frozen messages wherever normal messages are allowed.

Mido supports all message types defined by the MIDI standard. For a full list of messages and their attributes, see Message Types.

Control Changes

if msg.is_cc():
    print('Control change message received')

if msg.is_cc(7):
    print('Volume changed to', msg.value)

Converting To Bytes

You can convert a message to MIDI bytes with one of these methods:

>>> msg = mido.Message('note_on')
>>> msg
Message('note_on', channel=0, note=0, velocity=64, time=0)
>>> msg.bytes()
[144, 0, 64]
>>> msg.bin()
>>> msg.hex()
'90 00 40'

Converting From Bytes

You can turn bytes back into messages with the /parser.

You can also create a message from bytes using class methods (new in 1.2):

msg1 = mido.Message.from_bytes([0x90, 0x40, 0x60])
msg2 = mido.Message.from_hex('90, 40 60')

The bytes must contain exactly one complete message. If not ValueError is raised.

The Time Attribute

Each message has a time attribute, which can be set to any value of type int or float (and in Python 2 also long).

Some parts of Mido use the attribute for special purposes. In MIDI file tracks, it is used as delta time (in ticks), and it must be a non-negative integer.

In other parts of Mido, this value is ignored.


Before 1.1.18 the time attribute was not included in comparisons. If you want the old behavior the easies way is msg1.bytes() == msg2.bytes().

To sort messages on time you can do:

messages.sort(key=lambda message: message.time)


import operator


System Exclusive Messages

System Exclusive (SysEx) messages are used to send device specific data. The data attribute is a tuple of data bytes which serves as the payload of the message:

>>> msg = Message('sysex', data=[1, 2, 3])
>>> msg
Message('sysex', data=(1, 2, 3), time=0)
>>> msg.hex()
'F0 01 02 03 F7'

You can also extend the existing data:

>>> msg = Message('sysex', data=[1, 2, 3])
>>> += [4, 5]
>>> += [6, 7, 8]
>>> msg
Message('sysex', data=(1, 2, 3, 4, 5, 6, 7, 8), time=0)

Any sequence of integers is allowed, and type and range checking is applied to each data byte. These are all valid:

(65, 66, 67)
[65, 66, 67]
(i + 65 for i in range(3))
(ord(c) for c in 'ABC')
b'ABC'  # Python 3 only.

For example:

>>> msg = Message('sysex', data=bytearray(b'ABC'))
>>> += bytearray(b'DEF')
>>> msg
Message('sysex', data=(65, 66, 67, 68, 69, 70), time=0)