NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #5168 most downloaded on PyPI
Python API for interacting with ESPHome devices.
Last release 9 days ago
25 Sep 2026
Ships fairly regularly
a new release about every 1 weeks
Nearly every release is documented
notes for 58 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
8 years old
426 releases · first in 2018
Add missing_state to switch, climate and water heater states ( #1910 ) @tronikos , @bdraco
USB serial proxying and metadata subscription APIs ( #1901 ) @puddly
One column per quarter.
Pace IR/RF transmits on the device's completion response ( #1898 ) @bdraco
Add support for device-initiated outgoing connections ( #1893 ) @bdraco
Add description and example metadata to user service args ( #1890 ) @bharvey88
Mark media player supports_pause as deprecated in api.proto ( #1888 ) @bdraco
Add EntityState.with_device_id ( #1887 ) @bdraco
Add acknowledgements for proxy subscribe and configuration requests ( #1865 ) @kbx81
ConnectionClosedEvent for API consumers ( #1853 ) @puddly , @bdraco
Force re-release due to PyPI error ( #1879 ) @bdraco
Nothing published for this version
Add public bluetooth_device_disconnect_no_wait ( #1876 ) @bdraco
Add public noise module with sync handshake primitives ( #1874 ) @bdraco
Defer zeroconf loading until the mDNS wake listener is needed (#1870) @bdraco
Avoid loading uuid and timezone modules at import time (#1868) @bdraco
Add support for feeding newly discovered addresses into a running client (#1866) @bdraco
Sync api.proto bluetooth connection guards with esphome (#1863) @bdraco
Add workflow to open esphome bump PR on release (#1862) @bdraco
Avoid blocking connection setup on timezone resolution (#1857) @bdraco
<details> <summary>17 changes</summary>
Filter unspecified addresses from getaddrinfo results (#1834) @bdraco
<details> <summary>7 changes</summary>
Add deep_sleep param to async_run (#1828) @bdraco
Clarify deep_sleep is a bootstrap hint superseded by device_info (#1827) @bdraco
Support provisioning the encryption key over a zero-PSK noise connection (#1822) @bdraco
<details> <summary>11 changes</summary>
Revert tzlocal floor bump to stay compatible with pyicloud (#1803) @bdraco
Remove obsolete cibuildwheel free-threading enable group (#1802) @bdraco
Replace flag based cleanup in bluetooth_device_connect with per branch cleanup (#1764) @bdraco
Isolate user-callback exceptions in process_packet (#1762) @esphbot
<details> <summary>8 changes</summary>
Surface allocated connection slots in BluetoothConnectionsFree (#1741) @bluetoothbot
Add flag to suppress time updates by client by @clydebarrow in https://github.com/esphome/aioesphomeapi/pull/1733
Full Changelog: https://github.com/esphome/aioesphomeapi/compare/v45.2.0...v45.2.1
Surface configured_mode in BluetoothScannerStateResponse (#1740) @bluetoothbot
Add exhaustiveness guards for entity dispatch tables (#1735) @bluetoothbot
<details> <summary>5 changes</summary>
Sanitize peer-supplied mDNS labels in discover CLI (#1689) @bdraco
<details> <summary>3 changes</summary>
Sanitize peer DeviceInfo.name before storing as log_name (#1661) @bluetoothbot
This release adds two more defensive fixes around the unauthenticated portion of the Noise handshake. Both are low-severity hardening rather than expl
This release adds two more defensive fixes around the unauthenticated portion of the Noise handshake. Both are low-severity hardening rather than exploitable RCE-style bugs, but worth upgrading for if you log to anything you'd rather not poison or leak.
server_name, mac_address, and handshake-failure explanation before logging. These three fields ride on the wire before the PSK-authenticated handshake completes, so an on-path attacker (ARP spoof, compromised VLAN device, MITM during plaintext-mode hello) can put anything in them. The previous code interpolated them unescaped into log/error messages and stashed them on self for reuse by every later error path — letting an attacker inject CRLF + ANSI escape sequences into operator-visible logs (HA UI, syslog, monitoring webhooks), forge fake log lines, hijack terminals via CSI sequences, or impersonate a different device's identity in alert messages. The fix decodes once with errors="replace", strips non-printable characters, length-caps to the firmware's actual wire-format limits (32/16/64 bytes), and compares the raw decoded value (not the sanitized one) against expected_name / expected_mac so sanitization can't be used to bypass the identity check. Fixed in #1656.Malformed PSK error messages. _decode_noise_psk() previously embedded the raw PSK string in InvalidEncryptionKeyAPIError on both failure paths (invalid base64, wrong byte length). The exception is logged at WARNING level by the connection layer, so the raw PSK landed in every sink (file logs, journald, log aggregators, Sentry, HA diagnostics bundles). Even a malformed PSK is highly sensitive — typos are nearly identical to the real key, clipboard pastes can carry stray characters, and the pasted value may simply be the real PSK of a sibling device. The fix replaces the value with its character length, which is enough to diagnose paste/encoding errors without exposing the secret. Fixed in #1657.Threat model is "configuration-time / pre-handshake exposure," not a remote unauthenticated attack — same shape as v45.0.1's fixes.
This release adds bounds checks for several DoS vectors that a misbehaving or compromised ESPHome device could use to OOM the client process (typicall
This release adds bounds checks for several DoS vectors that a misbehaving or compromised ESPHome device could use to OOM the client process (typically Home Assistant). All three require an established API session — i.e. a device the user has already adopted — but a malicious or buggy peer in that session was previously able to:
CameraImageResponse chunks indefinitely or rotate cam_msg.key across ~4 billion values to grow the per-subscription reassembly buffer without bound. Affects every install that has an ESPHome camera. Fixed in #1648.length varuint of arbitrary size in plaintext mode (no noise_psk), causing the client to buffer up to that many bytes — easy multi-GiB allocation — or stream \x80\x80… indefinitely with no terminator, growing the receive buffer and forcing repeated O(N²) bigint shifts on every data_received. The noise path was incidentally protected by its fixed 16-bit length header; plaintext had no equivalent cap. Fixed in #1651.msg_type=0, which silently routed the payload to the last registered protobuf class instead of dropping it as an unknown message type. Low impact in practice (the connection drops anyway when the parse fails) but a footgun for future code. Fixed in #1645.Threat model is "adopted device misbehaves," not a remote unauthenticated attack. Plaintext-mode users should upgrade preferentially since #1651 lowers the bar to "anyone who can reach the device on the LAN" (no noise_psk means no auth on the wire and a network attacker can MITM).
<details> <summary>3 changes</summary>
Add second audio channel for voice (#1625) @synesthesiam
Suppress unretrieved Future exception warning in singleton (#1636) @bdraco
Lower cryptography requirement to 47+ (#1634) @bdraco
Add missing mapping for water_heater in COMPONENT_TYPE_TO_INFO (#1632) @tronikos
<details> <summary>8 changes</summary>
Mark high-volume proxy messages as speed_optimized (#1620) @bdraco
<details> <summary>5 changes</summary>
Add 48-bit MAC address varint fast path for BLE advertisements (#1614) @bdraco
<details> <summary>4 changes</summary>
Add opt-in plaintext fallback for log streams in ReconnectLogic (#1607) @bdraco
[radio_frequency] Add radio_frequency entity type support (#1564) @kbx81
<details> <summary>4 changes</summary>
Add opening and open lock states to protobuf (#1599) @egormanga
LockState::UNLOCKED duplicate value (#1601) @egormangaAdd temperature unit to climate and water_heater (#1600) @jhenkens
Expose the bound APIClient event loop with .loop (#1598) @puddly
APIClient event loop with .loop (#1598) @puddlySilence log_runner warning for CameraState (#1593) @bdraco
Fix log_runner info lookup colliding across entity types (#1590) @bdraco
<details> <summary>6 changes</summary>
Add speed_optimized to SubscribeLogsResponse (#1579) @bdraco
Add speed_optimized message option to api_options.proto (#1578) @bdraco
Stop mDNS records from thrashing an in-flight connect attempt (#1576) @bdraco
Preserve parent task cancellation state in connect exception handling (#1573) @bdraco
<details> <summary>2 changes</summary>
Revert "Bump pypa/gh-action-pypi-publish from 1.13.0 to 1.14.0" (#1568) @bdraco
Sync api.proto with esphome max_data_length and force annotations (#1563) @bdraco
Add missing max_data_length to number api.proto (#1561) @bdraco
Bump mypy from 1.19.1 to 1.20.0 (#1552) @[dependabot[bot]]
Nothing published for this version
Add max_value proto field option (#1559) @bdraco
<details> <summary>5 changes</summary>
[logging] Fix climate state (#1550) @kbx81
<details> <summary>2 changes</summary>
Add client-side entity state change logging to log runner (#1547) @bdraco
Your coding agent can read these notes before it upgrades. Set up the MCP server →