pyroute2: a pure Python netlink and PF_ROUTE library
Python Netlink and PF_ROUTE library — network configuration and monitoring
At a glance
- What is it?
- pyroute2 is a pure Python networking framework whose core needs nothing but the standard library. It began as an RTNL implementation and grew to cover netfilter, generic netlink families and even protocols that are not netlink at all, with three levels of API: a synchronous one, an asyncio one and a transactional high level layer.
- Who is it for?
- Adopt pyroute2 if you need to configure or observe Linux networking from Python without shelling out to ip, tc or iptables, and if you want the same code to work against a namespace, a container or a remote system. Do not adopt it for a non-Linux host, because the README says other platforms are not supported and BSD is covered only by a limited emulation of the RTNL API.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 2 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 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A networking framework with no dependencies
Pyroute2 is a pure Python networking framework, and the first constraint it advertises is that the core requires only the Python standard library, with no third party libraries.
That is the whole pitch. A network configuration tool in Python has two obvious routes: call the iproute2 binary and parse its output, or implement the kernel protocol yourself. The first is fragile and slow, the second is what this library is.
The name explains the history. The library was started as an RTNL protocol implementation, which is where the name pyroute2 comes from, but it now supports several protocols, including non-netlink ones.
The licence is dual and the project says so in the file header: the pyroute2 project is dual licensed, with the details in the readme about the licence. The package metadata records it as GPL-2.0-or-later OR Apache-2.0, and the repository root holds a LICENSE file alongside LICENSE.Apache-2.0 and LICENSE.GPL-2.0-or-later, with a license-files entry of LICENSE*.
A dual licence like that is a deliberate choice rather than indecision. It lets the library be used in a proprietary product under Apache-2.0 while remaining usable inside a GPL project, and the choice is the user's, made at the import site rather than in a negotiation.
The primary language is Python, the site is pyroute2.org, and the last push was on 2026-10-13.
The protocol families it speaks
The list of supported families is long, and it is the best way to see the scope of the project.
There are two protocols that are not netlink at all. dhcp is the dynamic host configuration protocol for IPv4, and 9p2000 is the Plan 9 file system protocol, which is the one people rarely expect to find in a network configuration library.
The netlink families are rtnl for network settings, meaning addresses, routes and traffic controls, nfnetlink for the netfilter API, ipq which is described as the simplest userspace packet filtering and the iptables QUEUE target, devlink for managing and monitoring devlink-enabled hardware, generic for generic netlink families, and uevent for the same uevent messages as in udev.
The netfilter API coverage is ipset for IP sets, nftables for packet filtering and nfct for connection tracking.
The generic netlink families are the most varied. ethtool for low-level network interface setup, wireguard for VPN setup, nl80211 for the wireless functions API with basic support, taskstats for extended process statistics, acpi_events for ACPI events monitoring, thermal_events for thermal events monitoring and VFS_DQUOT for disk quota events monitoring.
Under all of that, the library provides socket objects with an extended API. The additional functionality aims to help open and bind netlink sockets, to discover generic netlink protocols and multicast groups, and to construct, encode and decode netlink and PF_ROUTE messages.
The low-level work of finding the protocol family and its multicast group, which is the part every netlink program has to do by hand, is what that extended socket API is for.
IPRoute, and the promise of no implicit lookups
IPRoute is the low-level utility, a Linux network configuration class that is almost a one to one RTNL mapping, with the important property that there are no implicit interface lookups and so on.
That sentence is the design statement of the whole library. A lot of network tooling quietly resolves a name to an index for you, which is convenient until the name resolves to something else at the moment you are reconfiguring it. Pyroute2 makes you pass the index.
The monitoring example is the smallest one:
from pyroute2 import IPRoute
with IPRoute() as ipr:
ipr.bind() # <--- start listening for RTNL broadcasts
for message in ipr.get(): # receive the broadcasts
print(message)And the configuration example shows the whole cycle, creating a veth pair, waiting for the devices to appear, moving one into a namespace, bringing the other up with an address, and closing the socket:
from pyroute2 import IPRoute
ipr = IPRoute()
# print interfaces
for link in ipr.get_links():
print(link)
# create VETH pair and move v0p1 to netns 'test'
ipr.link('add', ifname='v0p0', peer='v0p1', kind='veth')
# wait for the devices:
peer, veth = ipr.poll(
ipr.link, 'dump', timeout=5, ifname=lambda x: x in ('v0p0', 'v0p1')
)
ipr.link('set', index=peer['index'], net_ns_fd='test')
# bring v0p0 up and add an address
ipr.link('set', index=veth['index'], state='up')
ipr.addr('add', index=veth['index'], address='10.0.0.1', prefixlen=24)
# release Netlink socket
ipr.close()The poll call with a predicate and a timeout is worth noting, because it solves a race that a shell script usually solves with a sleep.
The async layer and network namespace management
While IPRoute provides a synchronous RTNL API, the README says it is actually built around the asyncio-based core, and AsyncIPRoute is the same example in asynchronous form.
The shape is the same with awaits in the right places, including the poll that waits for the veth devices and the link call that moves a peer into a namespace.
There is a small detail that catches people out and the README calls it out. Please notice that .close() is synchronous in any case.
The network namespace management is a separate module, netns, with the obvious three operations:
from pyroute2 import netns
# create netns
netns.create('test')
# list
print(netns.listnetns())
# remove netns
netns.remove('test')And you can point the main class at a namespace directly, which is how you configure a container's interface from outside it:
from pyroute2 import IPRoute
with IPRoute(netns='test') as ipr:
for link in ipr.get_links():
print(link)On platform support the README is equally clear. Pyroute2 runs natively on Linux and emulates some limited subset of the RTNL netlink API on BSD systems on top of PF_ROUTE notifications and standard system tools. Other platforms are not supported.
That BSD story is honest about its limits. PF_ROUTE gives you notifications and a different API shape, so a partial emulation is the best that can be done, and a program that relies on netlink specifics will not simply work there.
NDB and the transactional layer
NDB is the high level RTNL API, and its key features are listed as four items: data integrity, transactions with commit and rollback changes, state synchronization, and multiple sources, including netns and remote systems.
The hello world example shows what transactions mean in practice:
from pyroute2 import NDB
with NDB() as ndb:
with ndb.interfaces['eth0'] as eth0:
# set one parameter
eth0.set(state='down')
eth0.commit() # make sure that the interface is down
# or multiple parameters at once
eth0.set(ifname='hello_world!', state='up')
eth0.commit() # rename, bring up and wait for success
# --> <-- here you can be sure that the interface is up & renamedThe difference from the low level API is the commit. A set is a proposal and a commit applies it, and the comment at the end says that after the block you can be sure the interface is up and renamed. Without a commit, the low level API has the same property, but with NDB you get it as a pattern rather than as a sequence of individual calls, and several parameters can be set and applied in one commit.
The multiple sources feature is the other headline. NDB can talk to a namespace or to a remote system, which means the same transaction code can configure a local interface or one on a machine across the network, and the state synchronisation keeps the view of the interface in step with the kernel rather than with your last write.
Installing it, and the packaging details
There are three install routes, and the third one needs more than pip.
From PyPI it is:
pip install pyroute2From git:
pip install git+https://github.com/svinota/pyroute2.gitAnd from source, which requires make and nox:
git clone https://github.com/svinota/pyroute2.git
cd pyroute2
make installThe requirements say Python 3.10 or later, and the package metadata agrees on 3.9 as the floor with classifiers for 3.9 through 3.14, and a development status of Beta.
The packaging is setuptools with the wheel build backend, and the version is dynamic rather than written in the file, which means it is derived from the repository at build time. There is exactly one runtime dependency, win_inet_pton, and it is conditional on platform_system being Windows, which is the practical shape of the BSD and Windows support: a small shim rather than a different implementation.
The optional dependency groups are the interesting part for a contributor. The dev group carries the test and lint tooling, including pytest with pytest-asyncio, pytest-timeout, pytest-cov and pytest-profiling, plus pre-commit and flake8. The docs group adds Sphinx with the code include extension. The repo group adds nox, pytest-html and setuptools, and the noxfile.py at the root is what those sessions are driven from.
There is also a pyproject.minimal.toml next to the main one, and a README.minimal.rst, which is a second, stripped-down distribution for people who want the core without the rest.
The repository, the examples and the release state
The repository is a full project rather than a single module, and the root files describe the workflow.
The Makefile has the releaseTag and releaseDescription variables derived from git describe and the git tag listing, and a noxboot target that creates a bootstrap virtual environment with nox in it if nox is not already installed. The selftest target exits with a specific code when no suitable Python is found, and the clean target is thorough enough to remove the generated docs, the test databases and the test JSON files, and to delete any leftover virtual interfaces the tests created.
The examples/ directory is the documentation of what the library can do, with directories for devlink, ethtool, generic, iproute, ndb, policy, processes and wifi, plus standalone scripts for ipq, ipset, nftables, nftables sets and a kobject uevent example.
The rest of the root is the set of READMEs a project accumulates: README.rst, README.contribute.rst, README.license.rst, README.minimal.rst and README.report.rst, alongside CHANGELOG.rst, the VERSION file, the noxfile.py, the util/ directory with the find_python script the Makefile calls, .mypy-check-paths, .flake8 and a pre-commit configuration.
The release history is regular. Version 0.9.4 came on 2025-07-29, 0.9.5 on 2025-11-02 and 0.9.6 on 2026-04-15, with the last push on 2026-10-13, so the tree is ahead of the last tag by about half a year. The project is not archived, and the version numbering below 1.0 with a Beta development status is consistent with an API that is still settling.
Editorial conclusion
Adopt pyroute2 if you need to configure or observe Linux networking from Python without shelling out to ip, tc or iptables, and if you want the same code to work against a namespace, a container or a remote system. Do not adopt it for a non-Linux host, because the README says other platforms are not supported and BSD is covered only by a limited emulation of the RTNL API. Before you start, pick the API layer that matches your program, the synchronous IPRoute for a script, AsyncIPRoute inside an existing event loop, or NDB when you want transactions, and read the licence note, because the project is dual licensed and the choice of GPL or Apache has to be made deliberately.
Frequently asked questions
What does pyroute2 do?
It is a pure Python networking framework whose core needs only the Python standard library. It started as an RTNL implementation and now supports several protocols, including non-netlink ones, and at the low level it provides socket objects with an extended API for opening and binding netlink sockets, discovering generic netlink protocols and multicast groups, and encoding and decoding netlink and PF_ROUTE messages.
Which pyroute2 API should I use?
IPRoute is the low-level synchronous API that is almost a one to one RTNL mapping with no implicit interface lookups, AsyncIPRoute is the same in asyncio form for an existing event loop, and NDB is the high level API with data integrity, transactions with commit and rollback, state synchronisation and multiple sources including namespaces and remote systems.
Does pyroute2 work outside Linux?
It runs natively on Linux. On BSD systems it emulates some limited subset of the RTNL netlink API on top of PF_ROUTE notifications and standard system tools, and the README states that other platforms are not supported.
How do I install pyroute2?
From PyPI with pip install pyroute2, from git with pip install git+https://github.com/svinota/pyroute2.git, or from source with git clone, cd pyroute2 and make install, which requires make and nox. The requirements are Python 3.10 or later, and the only runtime dependency is win_inet_pton on Windows.
What licence is pyroute2 under?
It is dual licensed as GPL-2.0-or-later OR Apache-2.0, with the licence files in the repository root and the details in the readme about the licence, so the choice of terms is yours to make at the import site rather than something negotiated per 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/svinota-pyroute2)Was this useful?