How Nornir, NAPALM, Netmiko, and Scrapli Work Together

|

Oct 19, 2026

Should you use Nornir, NAPALM, Netmiko, or Scrapli for Python automation? These four projects serve different purposes so it depends on which part of the job you need a tool for.

Netmiko and Scrapli are alternatives. Nornir runs tasks across your inventory. NAPALM provides a common API for supported operations across vendors. You can use them together.

The distinctions between them become clearer when you think about network automation as four functions or layers: orchestration, abstraction, connection, and the target device.

Each Python project fits into one of the first three layers, letting you choose the components you need.

Four network automation layers and where the Python projects fit

No matter which tool you use, every network automation job has to answer four questions:

  1. Orchestration: Which devices am I acting on and how many at once?
  2. Abstraction: What am I asking them to do, in a form that doesn’t change per vendor?
  3. Connection: How do I actually reach one device?
  4. Target: What is that device willing to accept?

These are the four layers. Nornir, NAPALM, Netmiko, and Scrapli fit into the first three layers, with Netmiko and Scrapli both operating at the connection layer.

four layers of network automation showing where Nornir, NAPALM, Netmiko & Scrapli fit

Orchestration with Nornir

Nornir is a Python automation framework. It loads an inventory of hosts and groups, lets you filter it down to the hosts you care about, and runs your Python functions against them through a runner.

The default runner uses a thread pool (20 workers unless you configure more) so devices run in parallel batches rather than one at a time. The runner itself is a plugin you can swap. You get back a result object per host, including the ones that failed.

What Nornir doesn’t do is open device connections itself. It delegates that work to other projects. The plugin packages (nornir_netmiko, nornir_napalm, and nornir_scrapli) integrate the projects below it and manage connections for tasks.

Where that inventory comes from is a plugin choice too. Nornir’s default inventory plugin reads YAML files stored locally. Other inventory plugins can retrieve data from NetBox, Nautobot, an Ansible inventory, or Infrahub (via nornir_infrahub), which means the host list reflects what your source of truth currently says rather than whatever someone last committed.

Abstraction with NAPALM

The NAPALM Python library gives you one API across vendors.

Methods such as get_facts(), get_interfaces(), and get_bgp_neighbors() return consistently structured dictionaries whether the box underneath is Cisco, Arista, or Juniper, because each driver translates the call for that platform.

For configuration changes, you can load a candidate configuration (a proposed configuration that hasn’t yet been applied), review the differences, then commit or discard the changes.

NAPALM has two limits that may affect your choice.

First, the getters are a fixed set. If you need something only one vendor exposes, NAPALM may have no method for it, and you drop down to the connection layer with that vendor’s own commands.

You can extend NAPALM by writing a custom driver but you’ll then be responsible for maintaining that driver, including updating it when the vendor changes its output format.

Second, NAPALM normalizes what it reads, not what it writes. The configuration you push is still the vendor’s own syntax. NAPALM manages the lifecycle of the configuration but doesn’t translate it for you.

Connection with Netmiko and Scrapli

The connection layer is where Netmiko and Scrapli offer two approaches to much the same job.

Both Netmiko and Scrapli establish sessions with network devices and let you execute commands. They differ in platform coverage, transport options, and execution models.

The Netmiko Python library opens an SSH session to a device’s CLI and handles the misery that lives there: prompt detection, disabling paging, entering enable mode, and the accumulated quirks of a very long list of platforms.

It’s synchronous, built on Paramiko, and covers an extensive range of vendors. You send a command string and you get text back. Parsing that text is your problem, which is what tools such as ntc-templates and TextFSM are for.

Scrapli does the same job with a different architecture. Since version 2.0, Scrapli’s core is a library called libscrapli, written in Zig. The Python package, and its Go counterpart, scrapligo, are thin wrappers around that core.

Scrapli 2.0 offers three transports:

  • bin: The default transport. It runs your system’s OpenSSH executable and can take advantage of existing SSH configuration, including jump hosts.
  • ssh2: Uses libssh2 library, so OpenSSH doesn’t need to be installed. This can be useful in containers.
  • telnet: Supports devices that still require Telnet.

Scrapli has both a synchronous and an asynchronous API. NETCONF support is now part of the project rather than a separate package.

Scrapli also uses YAML-based platform definitions to describe how it interacts with different devices. These specify details such as device prompts, operating modes (including exec and configuration modes), and commands to run when a session opens, such as disabling paging.

Scrapli’s asynchronous API is an important difference from Netmiko and NAPALM, which are synchronous. And Nornir’s default runner gets its concurrency from a thread pool rather than an event loop.

A synchronous task waits for an operation to finish before moving on. Asynchronous code can use that waiting time to make progress on other operations. This can be useful when managing many device connections.

You can use Scrapli directly in your own asyncio code to take advantage of its asynchronous API. But putting Scrapli underneath Nornir doesn’t automatically make the entire stack asynchronous.

If threads already meet your requirements, async alone is little reason to change projects.

Both Netmiko and Scrapli are commonly used for CLI screen scraping. CLI scraping remains important because many devices in production still expose some operations only through a command-line interface.

Target capabilities depend on the device

The device constrains the layers above it.

A device with an API can accept structured requests directly, which is why NAPALM uses Arista eAPI and NETCONF on Junos where supported. A device without a suitable API may give you a CLI over SSH and nothing else.

The transport isn’t always a design choice you get to make. It’s often a property of the hardware you were given, and quite a lot of that hardware was bought before anyone in the building said the word automation out loud.

The tools you choose have to work with the interfaces your network devices actually support.

How the Python projects work together

Let’s walk through a common network automation task to show how the four Python projects work together in practice.

Our task is to collect interface information from several hundred switches across a mixed-vendor network. We need to query Cisco, Arista, and Juniper devices, gather interface status, and return the results in a consistent format.

One approach is to combine Nornir and NAPALM.

Nornir handles orchestration. It loads the device inventory, filters it to the switches you want to query, and runs the collection task concurrently using its runner.

NAPALM handles abstraction. The task calls get_interfaces() through the appropriate NAPALM driver. Each supported driver retrieves the interface information and returns it using NAPALM’s common data structure.

The NAPALM driver also handles the connection layer, using the connection method supported by the platform. Depending on the driver, that may involve SSH, eAPI, or NETCONF.

In this workflow, you don’t need to call Netmiko or Scrapli directly because the NAPALM driver handles the device connection.

Now suppose you also need to collect a vendor-specific detail that NAPALM doesn’t expose.

You can use Netmiko or Scrapli to execute the appropriate CLI command and parse the response. Nornir can still manage the inventory, execute the task across devices, and collect the results.

The same automation job can therefore follow different paths through the stack.
diagram showing 2 ways to collect interfaces using Python tools

Both paths use Nornir for orchestration. The choice of library for the next step depends on what the task needs to accomplish and what the device supports.

You don’t need all four projects in every workflow. A small script might use Netmiko alone. A larger workflow might use Nornir with NAPALM for standardized operations and Scrapli for device-specific commands.

How Ansible handles the four network automation layers

If you’re already familiar with Ansible, it can be a helpful frame of reference for understanding these Python projects. Ansible handles the same four layers but in a single tool. Here’s how it maps:

Comparing how Python automation tools and Ansible handle network automation

Ansible’s inventory and ansible-playbook handle orchestration. The inventory defines hosts and groups, host patterns select the devices to act on, and forks control how many hosts Ansible works on concurrently.

Modules provide the abstraction layer, defining the operations your automation performs. Network resource modules such as ios_interfaces and eos_interfaces expose structured interfaces for managing network resources on their respective platforms.

Connection plugins are the connection layer, where network_cli does much of what Netmiko does, and netconf or httpapi cover devices with supported APIs. Then you select the appropriate connection plugin through the ansible_connection setting.

Ansible’s execution engine is part of ansible-core, while network connection plugins are provided through the ansible.netcommon collection. Platform-specific resource modules are typically provided through collections such as cisco.ios and arista.eos.

The devices are the devices.

Ansible bundles those four layers and hands you the bundle. The Python projects split them apart and hand you the pieces.

Ansible gives you an integrated automation framework with YAML as the primary authoring language. The Python stack gives you a choice of projects, Python for your task logic, and the ability to change individual components without necessarily rewriting the others.

The approaches suit different teams, and plenty of organizations run both.

Choosing the right tools for your automation

The projects you choose depend on the scale of your automation, the devices you’re managing, and the operations you need to perform.

  • Starting with a handful of devices and a script you’ll run manually: Netmiko on its own is fine. Adding Nornir to automate 12 switches is overhead you probably don’t need yet.
  • Once you have hundreds of devices and care how long a run takes: Consider adding Nornir. It provides inventory filtering and concurrent execution so you can focus on what each task needs to accomplish. Its plugins also let you work with different device libraries through the same framework.
  • When you’re reading the same facts across vendors: Add NAPALM. Its standardized getters provide consistent structured results, and its configuration methods support workflows with diffs, commits, and rollbacks rather than a hopeful send_config_set. Skip it when your environment is single-vendor and you’re mostly sending commands that NAPALM’s drivers don’t model anyway.
  • When choosing between Scrapli and Netmiko: Scrapli is worth considering if your devices are supported and you need its asynchronous API, its transport options, or NETCONF and CLI in one library. Netmiko is a strong choice if you have a long tail of unusual vendors because breadth of platform support is one of its strengths. You may need both for a mixed environment.
  • If you’re already happy in Ansible: Keep using it. Knowing what these four Python projects do is useful when you need something Ansible’s existing modules don’t cover. You can then choose the project for that part of the job.

Where these tools fit in a larger automation system

Nornir, NAPALM, Netmiko, and Scrapli cover important parts of network automation but they don’t provide everything needed for a complete automation system.

The NAF Network Automation Framework describes six functional building blocks for robust automation: intent, observability, collector, executor, orchestrator, and presentation.

The four Python projects address the collector, executor, and task coordination (i.e., orchestrator) functions:

  • NAPALM’s getters collect state, while its configuration methods execute changes.
  • Netmiko and Scrapli do both, depending on whether the command you send is a show or a config.
  • Nornir runs tasks across inventory, although a larger system may use a separate workflow orchestrator to coordinate those tasks in response to events.

The remaining functions from the NAF Framework require other tools and systems.

Nothing in these four projects, for example, stores a complete model of what the network should look like (intent), maintains historical observability data (observability), or provides an interface for users to request and approve changes (presentation).

The need for infrastructure intent also makes the inventory source important.

A hosts.yaml file in Git can provide a basic device inventory. That holds up fine until someone asks what the network is supposed to look like, and the answer is spread across four repositories and a wiki page from 2023.

A platform such as Infrahub can manage infrastructure intent, including device information, topology, addressing, and relationships. Nornir can then retrieve inventory data from Infrahub through nornir_infrahub, connecting the Python automation workflow to a structured source of truth.

The projects handle the work of collecting information and executing operations. The broader automation system must also provide the data and context those operations depend on.

Build your automation stack around the job

Nornir, NAPALM, Netmiko, and Scrapli serve different functions, and understanding those functions makes it easier to choose the right combination.

You can use one project on its own or combine several as your requirements grow.
Start with the simplest combination that solves the problem. You can add further orchestration, abstraction, and supporting systems when the work justifies them.

Pete Crocker

Pete Crocker | Seasoned builder of infrastructure automation strategy and early-stage tech. Comfortable hanging out from the CLI to the C-suite, connecting technical detail to business impact. Holds a full buzzword bingo card in tech and protocols. Savors two flat whites a day. Director, Solution Architecture at OpsMill.

REQUEST A DEMO

Infrahub by OpsMill logo

See what Infrahub can do for you

✔ Get a personal tour of Infrahub Enterprise

✔ Learn how we can support your infrastructure automation goals

✔ Ask questions and get advice from our automation experts

By submitting this form, I confirm that I have read and agree to OpsMill’s privacy policy.

Fantastic! 🙌

Check your email for a message from our team.

From there, you can pick a demo time that’s convenient for you and invite any colleagues who you want to attend.

We’re looking forward to hearing about your automation goals and exploring how Infrahub can help you meet them.

Get Ottermatic

Join hundreds of your industry peers exploring trends, tips, and talk in infrastructure automation.

Activate your subscription.

blue OpsMill otter