pyrtlsdr drives a Realtek RTL2832U dongle from Python
A Python wrapper for librtlsdr (a driver for Realtek RTL2832U based SDR's)
At a glance
- What is it?
- pyrtlsdr is a Python wrapper around librtlsdr that turns certain USB DVB-T dongles into software defined radio receivers, with a Pythonic API, asyncio streaming and a TCP mode for remote hardware. It suits signal processing work on cheap hardware, and its own licence statement is inconsistent.
- Who is it for?
- Adopt pyrtlsdr if you already own an RTL2832U dongle and want to do radio work in Python without writing a C binding yourself, especially if you need to stream samples asynchronously or reach the hardware over the network.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 4 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 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A cheap DVB-T dongle turned into a spectrum receiver
The project exists because of a hardware accident. Certain USB DVB-T dongles employ the Realtek RTL2832U chipset, and the RTL-SDR project showed that this tuner hardware can be reprogrammed to work as a general purpose software defined radio receiver. pyrtlsdr is the Python door into that hardware. The documentation describes it as a simple Python interface to devices supported by the RTL-SDR project, and its own tagline is a Python wrapper for librtlsdr, the driver library. The audience is people doing signal processing, spectrum analysis, radio astronomy or amateur radio work who want to script their receiver rather than click through a GUI, and who would rather not write their own ctypes bindings against a C library. It is worth being clear about the scope, because the name of the library is broader than its reach. It is not a general SDR framework, and it does not support arbitrary tuner hardware. The dependency list is short and specific: librtlsdr itself, Python, and optionally NumPy so that samples arrive in a more convenient form.
Two layers, and the Pythonic one is the one to use
The usage section explains the structure: all functions in librtlsdr are accessible via librtlsdr.py, and a Pythonic interface is available in rtlsdr.py, which the documentation marks as recommended. The practical difference shows up in the examples. The low level layer is a direct mirror of the C library, so it looks like librtlsdr translated line by line. The high level layer turns the same device into an object with attributes you assign to. Configuring a device is four assignments, a sample rate, a center frequency, a frequency correction and a gain, with the gain settable to the string auto rather than a number, and then a call that returns a block of samples:
from rtlsdr import RtlSdr
sdr = RtlSdr()
# configure device
sdr.sample_rate = 2.048e6 # Hz
sdr.center_freq = 70e6 # Hz
sdr.freq_correction = 60 # PPM
sdr.gain = 'auto'
print(sdr.read_samples(512))The frequency correction in parts per million exists because cheap dongles have oscillator offsets that put a known station on the wrong frequency, and the auto gain mode avoids the clipping that comes from a gain set too high. The samples come back as unsigned 8 bit values by default, and the optional NumPy dependency exists to wrap them in a more convenient form. The repository also keeps demo_waterfall.py and test.py at the root as further examples, and the higher level module carries docstrings for the details.
The bundled binary is the difference between easy and painful installs
Installing a Python binding for a C library usually means installing the C library first, and that is where projects like this normally lose people on Windows. pyrtlsdr addresses it directly. The documentation notes that on most platforms the librtlsdr binaries may also be installed with the pyrtlsdrlib package, and describes that feature as new in version 0.3.0, saying it should drastically simplify the installation process, especially for Windows. The normal install is a single pip command:
pip install pyrtlsdrAnd the recommended full installation pulls in the bundled binary as an extra:
pip install pyrtlsdr[lib]If the integration misbehaves during installation or on import, the documented fix is to upgrade both packages at once:
pip install --upgrade pyrtlsdr[lib]The older manual route is still described further down: the librtlsdr binaries, rtlsdr.dll on Windows and librtlsdr.so on Linux, should be in the pyrtlsdr directory or on a system path, and the documentation warns that these binaries may have additional dependencies of their own. The packaging metadata backs the split up with an optional dependency group named lib, and the development, test and documentation groups each include it, so a contributor always builds against the bundled library.
Asyncio streaming and a TCP mode for hardware in another room
Two features are labelled experimental, and both address real practical problems. The first, rtlsdraio, adds native Python 3 asynchronous support. It is imported automatically and adds stream() and stop() methods to the normal RtlSdr class, and it requires the async and await syntax. The usage pattern is a generator that yields blocks of samples and can be stopped from inside the loop:
import asyncio
from rtlsdr import RtlSdr
async def streaming():
sdr = RtlSdr()
async for samples in sdr.stream():
# do something with samples
# ...
# to stop streaming:
await sdr.stop()
# done
sdr.close()The second, rtlsdrtcp, adds a TCP server and client so a device can be reached over the network. The server class is meant to sit physically next to the dongle and talk to a client that tries to behave as closely as possible as the base RtlSdr class, as if a physical dongle were attached. Both classes take the same arguments as the base class plus hostname and port. There is also a client only mode, added in version 0.2.4, for platforms where librtlsdr cannot be installed or compiled: you import only the RtlSdrTcpClient by setting the environment variable RTLSDR_CLIENT_MODE to true, and if it is set no other modules are available. That last detail is a hard switch rather than a preference, so a script written for client mode cannot also use the local device API.
Multiple dongles need the EEPROM serial rewritten first
If you have more than one device, the library can enumerate them and select one by serial number. There is a list of detected device serial addresses, a way to find the device index for a given serial, and a constructor that accepts the serial directly. The catch is stated plainly in the project documentation: most devices by default have the same serial number, 0000001, and the fix is to set a custom value using the rtl_eeprom utility packaged with librtlsdr. That is a real operational step, and it is one people discover late. Until you rewrite the EEPROM on each dongle, the enumeration helpers will return indistinguishable entries and you will have no way to tell your receivers apart. The other half of the multi device story is the driver level, since two dongles plugged into the same host is where USB bandwidth and kernel driver quirks show up, and the project does not discuss that. Treat the serial number rewrite as a prerequisite for any multi receiver setup rather than a convenience.
The licence statement is the one thing to sort out first
There is an inconsistency here that a careful adopter should notice. The package metadata in pyproject.toml declares the licence as GPL-3.0-or-later, and the classifiers call the project Beta. The repository's own license field is reported as unknown, and there is no LICENSE file among the top level entries, which are the .github directory, the .coveragerc, the documentation folder, demo_waterfall.py, test.py, smoke_test.py, the rtlsdr package directory, the tools directory, pyproject.toml, renovate.json and a uv.lock. The GPL-3.0-or-later grant in the metadata is the more specific statement and is what a package consumer would rely on, and it is a copyleft licence with an important consequence: linking this into a program you distribute means your program falls under its terms. That is a different arrangement from the permissive licences most Python bindings carry, and it is worth reading the actual terms rather than assuming the intent. None of this is legal advice, and the point is narrow: know which grant you are relying on before you ship something built on it. On the code side, the project is honest about what is missing. The todo section says a few functions in librtlsdr have not been wrapped yet, and that adding one is a simple process with a pull request welcome.
Editorial conclusion
Adopt pyrtlsdr if you already own an RTL2832U dongle and want to do radio work in Python without writing a C binding yourself, especially if you need to stream samples asynchronously or reach the hardware over the network. Do not adopt it as a general SDR framework, since it covers one chipset family and a few librtlsdr functions remain unwrapped, and do not build on it until you have resolved the licence question, since the package metadata says GPL-3.0-or-later while the repository itself declares no licence. Before you install, check whether the pyrtlsdrlib bundled binary works on your platform, and confirm that the dongle you own actually uses the RTL2832U chipset.
Frequently asked questions
How do I install pyrtlsdr?
The basic install is `pip install pyrtlsdr`. The recommended full installation is `pip install pyrtlsdr[lib]`, which pulls in the pyrtlsdrlib package so the librtlsdr binaries are installed for you on most platforms, a feature described as new in version 0.3.0 that should simplify setup especially on Windows.
Do I need NumPy to use pyrtlsdr?
NumPy is optional. It is listed as an optional dependency that wraps samples in a more convenient form, and matplotlib is described as useful for plotting data. The core requirements are librtlsdr and Python 3.8 or newer, with the package metadata requiring Python 3.10 or above.
Can I use pyrtlsdr with more than one SDR dongle?
Yes. You can list detected device serial addresses, find the device index for a given serial, or pass the serial directly to the constructor. The documentation notes that most devices share the same default serial number, 0000001, so you need to set a custom value with the rtl_eeprom utility packaged with librtlsdr.
What is the TCP client mode in pyrtlsdr for?
It lets you use a dongle attached to another machine. The RtlSdrTcpServer sits next to the hardware and the RtlSdrTcpClient aims to behave like a local device, and on platforms where librtlsdr cannot be installed or compiled you can import only the client by setting the RTLSDR_CLIENT_MODE environment variable to true, in which case no other modules are available.
What licence does pyrtlsdr use?
The package metadata in pyproject.toml declares the licence as GPL-3.0-or-later, while the repository itself declares no licence and has no LICENSE file at the top level. If you are building on it, confirm which grant applies to your use.
Official sources
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.
[](https://hysenlabs.com/projects/pyrtlsdr-pyrtlsdr)Was this useful?