Library / SDK
hbldh/bleak avatar
hbldh/bleak

bleak: never name your script bleak.py

A cross platform Bluetooth Low Energy Client for Python using asyncio

2,535 stars371 forksPythonMIT

At a glance

What is it?
An asyncio GATT client for Bluetooth Low Energy with four platform backends, each pulling in its own set of system bindings from the manifest. The readme spends one line in capitals on a naming mistake and the rest of the substance is in the dependency conditions and the platform floors.
Who is it for?
Use bleak when you need to talk to a BLE peripheral from Python and want one API across the four platforms rather than four code paths. Three things to know before you start.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The one thing in capitals is a filename

The usage section ends with a warning written entirely in capitals: do not name your script bleak.py, because it will cause a circular import error. That is the only imperative in the document, and it is there because the package and the module share a name. A file of that name in the working directory shadows the package during import, and the failure surfaces as a circular import rather than as anything that points at the filename. It is worth knowing because the two worked examples in the readme are otherwise complete: one discovers devices with a scanner and prints them, the other connects to a device address, reads the model number characteristic by its short UUID and decodes the bytes it gets back.

Four backends, four dependency sets

The manifest declares its system dependencies by platform rather than listing them flat. Windows pulls in a run of winrt packages, ten of them, covering the runtime, the Bluetooth device namespace, advertisement, the Generic Attribute Profile, device enumeration, radios, foundation, foundation collections and storage streams. macOS pulls in three pyobjc packages: the core, a CoreBluetooth framework binding and a libdispatch framework binding. Linux pulls in a single package, dbus-fast, which is the D-Bus client used to talk to BlueZ. Android has no conditional dependency at all in the visible part of the file, because it is reached through the python-for-android toolchain rather than through wheels. So an install resolves a different dependency tree on each operating system.

Python 3.10 is the floor and the backports are conditional

The project requires Python 3.10 or later, and the classifier list names the framework as AsyncIO plus the four operating system families. Two dependencies are gated on the interpreter version rather than the platform. async-timeout is required below Python 3.11, which is what an asyncio timeout needs on the versions that did not ship the context manager in the standard library. typing-extensions is required below Python 3.12. Both are pinned with a lower bound rather than an upper one, so a newer interpreter simply drops them. That pattern is what lets one release number cover three interpreter versions without pinning the whole tree.

Minimum platforms are stated as build numbers

The feature list gives four support statements and each one is a version rather than a product name. Windows is supported from Windows 11 version 22000 and greater, which is a build number rather than a marketing name. Linux support is conditional on BlueZ 5.55 or later, so the real requirement is the Bluetooth stack version on the distribution rather than the distribution itself. macOS is supported through the Core Bluetooth API from OS X 10.15. Android support is a backend compatible with python-for-android, which is a build-toolchain statement rather than an operating system version. The readme still writes OS X in two places, matching the older classifier name for macOS in the manifest.

The default branch is develop and the changelog link points at it

The repository's default branch is develop rather than master or main, and the project metadata follows that choice: the changelog URL points at the CHANGELOG file on the develop branch rather than at a tag, so a link copied from the manifest tracks the branch head. Support is routed to discussions rather than to the issue tracker, with issues having their own entry that is cut off in the visible text. The releases are three tags in quick succession: 3.0.0 on 2026-03-22, 3.0.1 on 2026-03-25 and 3.0.2 on 2026-05-02. The manifest version matches the newest of them, so the package on an index and the branch can differ by only a few days of commits.

A testbed directory ships with the library

The tree holds a directory called testbed next to tests, and that is unusual for a hardware client library: it means the repository carries the hardware setup used to exercise the library rather than only mocks. Alongside it are a typings directory for type stubs, and an examples directory with more than a dozen scripts. They cover the obvious paths such as discovery, service exploration, a UART service and enabling notifications, and the less obvious ones such as negotiating an MTU size, a scan iterator, a Philips Hue example, a Texas Instruments SensorTag CC2650 example that the readme links to, and two devices talking to each other. There is also a Kivy subdirectory, which is the GUI angle.

Two analysis configs exist for the Android path only

The root carries a mypy configuration and a pyright configuration, and both filenames carry an android suffix. That is a deliberate split: the Android backend is type checked separately from the rest of the tree, presumably because it reaches into a different set of stubs than the Windows and macOS paths do. Alongside them sit a setup.cfg next to the pyproject file, which is the older configuration file still in the tree, and a uv lock file, which points at uv as the tool used to produce a reproducible environment. Two logo images sit at the root as well, with the readme embedding the second of them through a container directive.

Editorial conclusion

Use bleak when you need to talk to a BLE peripheral from Python and want one API across the four platforms rather than four code paths. Three things to know before you start. Each platform's bindings are installed from the manifest based on the platform system, so a locked environment built on one operating system will not transfer cleanly to another. The minimum platform versions are specific: Windows 11 build 22000, BlueZ 5.55 on Linux, and macOS 10.15. And a script called bleak.py breaks the import, which is the one failure the readme singles out.

Frequently asked questions

How do I install bleak for Python?

Run pip install bleak. The package requires Python 3.10 or later and resolves platform specific dependencies automatically, including winrt packages on Windows, pyobjc packages on macOS and dbus-fast on Linux.

Which platforms does bleak support?

Windows 11 version 22000 and greater, Linux distributions with BlueZ 5.55 or later, macOS from OS X 10.15 through the Core Bluetooth API, and an Android backend compatible with python-for-android.

What can bleak do with a Bluetooth Low Energy device?

It is a GATT client, so it connects to devices acting as GATT servers and can read characteristics, write to them and subscribe to notifications, as well as discover nearby devices.

Why does my bleak script fail with a circular import error?

Because the file is named bleak.py. The README states in capitals that a script must not be given that name, since it shadows the package and causes a circular import.

What does bleak depend on for each platform?

Windows uses a set of winrt packages for the Bluetooth, advertisement, enumeration, foundation and storage namespaces, macOS uses pyobjc-core with CoreBluetooth and libdispatch framework bindings, and Linux uses dbus-fast.

Where is the bleak changelog and documentation?

The changelog is CHANGELOG.rst in the repository, linked from the project metadata on the develop branch, and the documentation is published at bleak.readthedocs.io. Support questions go to GitHub discussions.

Official sources

  1. hbldh/bleak on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hbldh-bleak.svg)](https://hysenlabs.com/projects/hbldh-bleak)