If you’ve spent any time in the Python network automation world, you’ll have bumped into both Scrapli and Nornir. They come up in the same conversations, the same blog posts and the same job specs, so it’s natural to line them up and ask: which one should I use?
It’s a fair question, but it’s built on a slightly wrong assumption. Scrapli and Nornir aren’t really competitors. They solve different problems at different layers of the automation stack, and the most interesting answer isn’t “pick one” — it’s “use them together with scrapli-nornir.”
Let’s break down what each tool actually does, where they differ, and how they combine.
What is Scrapli?
Scrapli, the name is just “scrape cli” squished together is a Python library written by Carl Montanari for connecting to network devices (routers, switches, firewalls and the like) over SSH, Telnet or NETCONF.
https://github.com/carlmontanari/scrapli
At its heart, Scrapli is a connection driver. It’s job is to open a session to a single device, send commands or configuration, read the output back reliably, and hand it to you as a clean response object. If you’ve used Netmiko, it lives in the same conceptual space but Scrapli was built later with a few deliberate design choices:
- Speed and multiple transports. By default Scrapli uses your system’s own SSH binary rather than Paramiko, which tends to be faster and behaves exactly like the SSH you already know. You can also swap in other transports such as
ssh2,paramikoorasyncsshdepending on your needs. - Sync and async. Scrapli supports both synchronous and asynchronous (
asyncio) operation from the same library, which makes it a strong choice if you want to fan out to many devices concurrently in your own code. - A clean, fully-typed API. It’s well documented and heavily tested, which matters when you’re building something you have to maintain.
- Structured data. Output can be parsed into structured data using TextFSM (via ntc-templates) or Cisco Genie, so you get dictionaries instead of screen-scraped strings.
Here’s the “hello world”:
from scrapli.driver.core import IOSXEDriver
device = {
"host": "192.0.2.1",
"auth_username": "admin",
"auth_password": "password",
"auth_strict_key": False,
}
with IOSXEDriver(**device) as conn:
response = conn.send_command("show version")
print(response.result)
# ...or get it back as structured data
print(response.textfsm_parse_output())
Scrapli also has a wider ecosystem: scrapli_netconf for NETCONF, scrapli_cfg for full config-replace/merge workflows, and scrapli_community a set of YAML-defined platform definitions that extends support well beyond the core Cisco/Juniper/Arista drivers to the likes of Nokia SR OS, Huawei VRP, Palo Alto PAN-OS, Mikrotik and many more.
The key thing to hold onto: Scrapli talks to devices. One connection, one device. It doesn’t know or care about your inventory of 500 switches, and it won’t loop over them or manage concurrency for you unless you write that code yourself.
A quick note on Scrapli in 2026
Scrapli is currently going through its biggest change since launch. Carl has been rebuilding the core as libscrapli, a unified engine written in Zig, so that the Python and Go versions can share the same battle-tested core. The Python binding of that effort ships as scrapli2 (currently in release-candidate stages 2.0.0rc at the time of writing), and the Go flavour is scrapligo.
For most people running production automation today, the classic pure-Python scrapli is still the sensible choice. But it’s worth knowing the direction of travel: one shared core, consistent behaviour across languages, and a small dependency footprint.
What is Nornir?
Nornir is a completely different animal. It’s a pure-Python automation framework, created by David Barroso the same person behind NAPALM. Where Ansible asks you to express your automation in YAML playbooks and a domain-specific language, Nornir hands you plain Python and gets out of the way.
https://github.com/nornir-automation/nornir
Nornir doesn’t connect to devices at all. Instead, it gives you the two things that are genuinely tedious to build yourself:
- Inventory management. A structured, pluggable way to define your hosts, groups and defaults — data, credentials, platform, roles and any custom attributes you like. The default is YAML files, but the inventory is pluggable, so you can pull hosts straight from NetBox, an Ansible inventory, or your own source of truth.
- Concurrency. Nornir runs your tasks across the whole inventory with multithreading built in. You write a function that operates on one host; Nornir runs it against all of them in parallel and collects the results.
Because Nornir itself has no idea how to talk to a router, you plug a connection library into it. That’s where plugins like nornir_netmiko, nornir_napalm and the subject of this article nornir_scrapli come in.
A minimal Nornir example, here using the Netmiko plugin to make the point that Nornir needs a driver:
from nornir import InitNornir from nornir_utils.plugins.functions import print_result from nornir_netmiko.tasks import netmiko_send_command nr = InitNornir(config_file="config.yaml") results = nr.run(task=netmiko_send_command, command_string="show version") print_result(results)
That single nr.run() call fans the task out across every host in your inventory, concurrently, and gives you back a results object keyed by hostname. You didn’t write a loop, a thread pool or any inventory-parsing code that’s the value Nornir provides.
The thing to hold onto here: Nornir manages many devices and runs tasks against them at scale. It orchestrates — but it borrows something else to do the actual talking.
One recent development worth knowing about: in 2026, OpsMill became the steward of the Nornir project. OpsMill is the company behind Infrahub, an automation-first source of truth, and their involvement is a strong signal for Nornir’s long-term future. Nornir remains open source and community-driven — existing plugins, scripts and workflows keep working exactly as they do today — but it now has dedicated engineering resources and a roadmap behind it, with the focus turning to modernising the framework alongside the community. Reassuringly, Nornir’s creator David Barroso continues to support the project as a Technical Advisor. The natural synergy is obvious: pair Nornir as a proven execution engine with Infrahub as a reliable source of truth, and you have inventory, data and execution all pulling in the same direction — there’s even a nornir-infrahub plugin that lets Infrahub act as your Nornir inventory source.
https://opsmill.com/nornir-joins-opsmill/
Scrapli vs Nornir: the real difference
Once you see the two clearly, the “versus” almost dissolves. They operate at different layers:
| Scrapli | Nornir | |
|---|---|---|
| What it is | Connection / driver library | Automation framework |
| Its job | Talk to a device (SSH/Telnet/NETCONF) | Manage inventory + run tasks concurrently |
| Scope | One device per connection | Your entire fleet |
| Inventory | You manage it yourself | Built in and pluggable (YAML, NetBox, etc.) |
| Concurrency | You handle it (asyncio or your own threads) | Built in (multithreaded runner) |
| Talks to devices? | Yes | No, needs a connection plugin |
| Comparable to | Netmiko | (loosely) Ansible, but in pure Python |
Put simply:
- Scrapli answers “how do I reliably send commands to a device and get clean output back?”
- Nornir answers “how do I run something against hundreds of devices, in parallel, without reinventing inventory and threading?”
Use Scrapli on its own when you’re writing a focused script, a small tool, or when you want fine-grained control over the connection and are happy to manage concurrency yourself (its async support is excellent for this). Use Nornir when you have a real inventory and you want structure, scale and a repeatable workflow but remember it can’t do anything until you give it a driver.
That naturally leads to the obvious question: what if you want Scrapli’s speed and Nornir’s inventory and concurrency?
Bringing them together: scrapli-nornir
This is where the two tools stop being alternatives and start being teammates. nornir_scrapli is Scrapli’s official plugin for Nornir. It lets you use Scrapli as the connection driver inside the Nornir framework so Nornir handles the inventory and the concurrency, and Scrapli handles the fast, reliable device conversations.
Nearly all of Scrapli’s synchronous methods are exposed as Nornir tasks send_command, send_commands, send_configs, get_prompt along with the scrapli_netconf and scrapli_cfg capabilities. You get the best of both layers with almost no glue code.
Install it with:
pip install nornir-scrapli
Point your Nornir inventory at Scrapli as the connection type. A host entry looks like this:
# hosts.yaml
iosxe-1:
hostname: 192.0.2.1
platform: cisco_iosxe
connection_options:
scrapli:
platform: cisco_iosxe
extras:
auth_strict_key: false
Then your script barely changes from the Netmiko example above — you just import the task from nornir_scrapli:
from nornir import InitNornir from nornir_scrapli.tasks import send_command from nornir_utils.plugins.functions import print_result nr = InitNornir(config_file="config.yaml") results = nr.run(task=send_command, command="show version") print_result(results)
That’s it. Nornir loops over the whole inventory concurrently; every device conversation underneath is being driven by Scrapli. Because Nornir provides the threading, you use Scrapli’s synchronous methods here and let the framework handle the parallelism you don’t need to touch asyncio yourself.
You also keep Scrapli’s structured-data superpowers. The Scrapli response object rides along inside each Nornir result, so you still get elapsed_time, the raw and structured output, and TextFSM/Genie parsing now multiplied neatly across your whole fleet.
So, which should you use?
- Just need to talk to devices in a script or tool? Reach for Scrapli on its own. It’s fast, clean and modern, and its async support covers you if you need concurrency.
- Need inventory, structure and scale? Use Nornir but pair it with a driver.
- Want both? Use
scrapli-nornirand stop choosing. Nornir gives you inventory and concurrency; Scrapli gives you a fast, reliable, well-typed connection layer. Together they’re one of the nicest pure-Python automation stacks available today.
The framing of “Scrapli vs Nornir” is really a category error a bit like asking “engine vs car.” Scrapli is a superb engine for talking to devices; Nornir is the chassis that carries a fleet of them. The moment you stop treating them as rivals, you end up building something better than either could manage alone.
Got a preferred network automation stack, or a war story about migrating from Netmiko to Scrapli? I’d love to hear about it — drop a comment below.

Leave a Reply