Install & Compatibility
Where this runs
tested against v3.0.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.244s · 22.1MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 2.5s · import 0.214s · 23MB
20MB installed
● package 20MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
BleakScanner
✓ from bleak import BleakScanner
BleakClient
✓ from bleak import BleakClient
BleakError
✓ from bleak.exc import BleakError
BleakGATTProtocolError
✓ from bleak.exc import BleakGATTProtocolError
BleakDBusError
✓ from bleak.exc import BleakDBusError
Pre-v3.0.0 specific GATT errors on BlueZ backend; now wrapped by BleakGATTProtocolError.
This quickstart demonstrates how to scan for nearby Bluetooth Low Energy devices using `BleakScanner` and then connect to a specific device using `BleakClient` to read a GATT characteristic, such as the battery level. It highlights the asynchronous nature of Bleak operations, requiring `asyncio` to run. Remember to replace placeholder UUIDs and addresses with those relevant to your device.
import asyncio
from bleak import BleakScanner, BleakClient
# Replace with the actual address of your BLE device
# For macOS, this might be a UUID. For Linux/Windows, a MAC address.
# You can find the address by running the discovery part first.
DEVICE_ADDRESS = "XX:XX:XX:XX:XX:XX" # Example for a generic device
SERVICE_UUID = "0000180f-0000-1000-8000-00805f9b34fb" # Battery Service UUID
BATTERY_LEVEL_CHAR_UUID = "00002a19-0000-1000-8000-00805f9b34fb" # Battery Level Characteristic UUID
async def discover_devices():
print("Scanning for 5 seconds...")
devices = await BleakScanner.discover(timeout=5.0)
for d in devices:
print(f"Device: {d.name} ({d.address})")
print("\nDiscovery complete.")
return devices
async def connect_and_read(address: str):
try:
async with BleakClient(address) as client:
if not client.is_connected:
print(f"Failed to connect to {address}")
return
print(f"Connected to {client.address}")
# Read a characteristic (e.g., Battery Level)
try:
battery_level = await client.read_gatt_char(BATTERY_LEVEL_CHAR_UUID)
print(f"Battery Level: {int.from_bytes(battery_level, 'little')}%")
except Exception as e:
print(f"Could not read battery level characteristic: {e}")
# List all services and characteristics (optional)
print("\nServices and Characteristics:")
for service in client.services:
print(f" Service: {service.uuid} ({service.description})")
for char in service.characteristics:
print(f" Characteristic: {char.uuid} ({char.description}) - Properties: {char.properties}")
for descriptor in char.descriptors:
print(f" Descriptor: {descriptor.uuid}")
except Exception as e:
print(f"An error occurred: {e}")
async def main():
# First, discover devices to find the address
# devices = await discover_devices()
# For direct connection, replace DEVICE_ADDRESS with your target's address
await connect_and_read(DEVICE_ADDRESS)
if __name__ == "__main__":
# Make sure not to name your script 'bleak.py' to avoid circular import errors.
asyncio.run(main())
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'bleak'
The 'bleak' library has not been installed in the Python environment where the script is being executed.
ImportError: cannot import name 'BleakScanner' from partially initialized module 'bleak' (most likely due to a circular import)
The Python script file itself is named 'bleak.py', which creates a naming conflict with the installed 'bleak' library, causing Python to try and import the script instead of the actual library.
fixRename your Python script file to something other than 'bleak.py' (e.g., 'my_ble_app.py' or 'scanner.py').
bleak.exc.BleakError: No Bluetooth adapters found.
No active Bluetooth Low Energy (BLE) adapter is detected on the system, or it is not enabled or accessible to the Python process. This is common in virtualized environments like Docker or WSL, or when Bluetooth is simply turned off.
fixEnsure Bluetooth is enabled and functioning correctly on your operating system. For Linux or Docker environments, verify that the 'bluez' service is running and that the user has appropriate permissions. If running in a Docker container, ensure the Bluetooth device is correctly passed through to the container.
AttributeError: 'NoneType' object has no attribute 'ConnectionStatusChanged'
This error typically occurs on Windows systems, often with certain Python versions (e.g., Python 3.11+) or older Bleak versions, due to issues in how asyncio interacts with underlying WinRT objects, particularly if an IAsyncOperation object unexpectedly resolves to None or lacks expected methods.
fixUpgrade the 'bleak' library to its latest version (e.g., `pip install --upgrade bleak`). If the problem persists on Windows with recent Python versions, ensure 'pywinrt' is up-to-date or consider installing 'bleak' from its development branch for the latest fixes, and verify that `asyncio.run()` is called only once in your application.
bleak.exc.BleakError: Device with address <MAC_ADDRESS> could not be found.
The specified Bluetooth Low Energy (BLE) device is either out of range, powered off, not advertising, or the provided MAC address/UUID is incorrect. Alternatively, an `asyncio.exceptions.TimeoutError` during connection indicates the connection attempt timed out.
fixVerify the device's Bluetooth address/UUID. Ensure the BLE device is powered on, actively advertising, and within close physical range of the computer running the Bleak script. Increase the `timeout` parameter in `BleakScanner.discover()` or `BleakClient.connect()` calls to allow more time for discovery or connection.
Upgrade
Version history
3.0.2latest on PyPI · released May 2, 2026
Audit
Dependencies
No dependency data recorded yet.