Library / SDK
rust-pcap/pcap avatar
rust-pcap/pcap

pcap wraps libpcap for Rust and leaves the linking rules to you

Rust language pcap library

741 stars156 forksRustApache-2.0

At a glance

What is it?
The pcap crate gives Rust programs device listing, BPF filtering, savefiles and packet injection on top of libpcap or Npcap, but the project pushes version detection, permissions and library linking onto your own build setup.
Who is it for?
pcap is the right choice for a Rust engineer who needs raw frames from libpcap, wants one crate covering both Unix and Windows, and can satisfy the libpcap or Npcap prerequisite on the build machine. It is the wrong choice if you want a self-contained pure-Rust capture path, if your target is musl with a static build and no pkgconfig/libpcap.pc, or if raw socket privileges cannot be granted to your binary.
Can I use it commercially?
Yes. Apache-2.0 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 8 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

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

Editorial analysis

libpcap access from Rust without writing the FFI yourself

The pcap crate exists for a narrow job: giving Rust programs the packet capture capabilities that libpcap already provides on Unix-like systems and Npcap provides on Windows. The package description calls it a packet capture API around pcap/wpcap, and the feature list spells out the surface. List devices, open a capture handle on a device or on a savefile, pull packets from that handle, filter them with BPF programs, list, set and get datalink link types, adjust parameters such as promiscuity and buffer length, write packets to savefiles, and inject packets into an interface.

That is a library for people who already know what a capture handle is. It is not a protocol analyser, not a traffic dashboard, and not a place to author filters from scratch. Its user is a developer writing a sensor, a test harness or a monitoring agent who needs raw frames and is prepared to deal with the privileges and linking rules that come with them.

build.rs handles version detection so you do not have to

The interesting machinery sits in build.rs rather than in the public API. The build dependencies are libloading, regex and pkg-config, and the script queries libpcap for its version so the crate exposes only the entrypoints the installed library actually provides. That is how the project can compile against an older libpcap while still offering functionality that only newer releases have.

Windows works differently. No library is linked at build time there. Each entrypoint is declared and resolved the first time it is called, through the windows-sys bindings for Win32_Networking_WinSock, Win32_System_LibraryLoader and the neighbouring features. Calling an entrypoint the installed wpcap.dll does not export returns Error::EntrypointNotFound at runtime rather than failing the build, which is a much kinder failure mode on a platform where library versions drift independently of the crate.

A second feature flag, lending-iter, pulls in the gat-std crate and exposes a lending packet iterator. The project marks it as unstable and says to use it at your own risk, which is an unusually clear signal that the public API may still move.

Install the system library before cargo can link anything

The crate requires libpcap, or Npcap on Windows, before anything compiles. On Debian-based Linux the dependency is libpcap-dev, on Fedora it is libpcap-devel, and on macOS libpcap is already installed by default. On Windows the project points you at the Npcap download.

Once the system library is in place, a project pulls the crate in through Cargo. The feature that enables streamed captures is opted into by name:

toml
[dependencies]
pcap = { version = "2", features = ["capture-stream"] }

Watch the version there. The example in the README says version 2 while the Cargo.toml in the repository declares version 3.0.0, so read the CHANGELOG before copying that line into a new project.

Usage samples live in the examples directory and are registered as Cargo examples in Cargo.toml:

toml
[[example]]
name = "easylisten"
path = "examples/easylisten.rs"

The set includes getdevices.rs for enumerating interfaces, loop.rs and breakloop.rs for capture loops, dispatch.rs, savefile.rs and savemultiplefiles.rs for writing files, sendqueue.rs and winevt.rs for injection, getstatistics.rs for interface counters, and the streaming trio streamecho.rs, streamlisten.rs and streamlisten_mt.rs. The README points to that directory for usage rather than documenting the API inline.

A zero timeout can hang pcap::Capture::next forever

One failure mode is called out in enough detail to be worth reading twice. On macOS, a timeout of zero may cause pcap::Capture::next to hang and never return, because the call waits for the timeout to expire before returning. The suggested fix is a non-zero timeout, as the libpcap manual recommends, and calling pcap::Capture::next in a loop rather than expecting a single call to finish.

Permissions are the other everyday friction. If you are not running as root on Linux, the README says you need to set capabilities, granting cap_net_raw and cap_net_admin to the binary path with setcap. That keeps capture privilege out of the user account while giving the process the raw socket access the library needs. It also means the binary needs rebuilding whenever the path or the ownership changes, which matters for packaging setups that rebuild rarely.

LIBPCAP_LIBDIR and LIBPCAP_VER when the build script guesses wrong

When version detection fails, the compiler tells you so:

text
cannot find function `pcap_<some_function>` in module `raw`

The README explains that this means the installed libpcap does not support the newest API and the build script failed to exclude the unsupported features. Two escape hatches exist. LIBPCAP_LIBDIR points the script at the directory holding the library, which matters because it does not see search paths another build script added with cargo:rustc-link-search=native, and in an unconventional location it may detect a different libpcap or simply assume the newest API. When LIBPCAP_LIBDIR is unset, the build falls back to pkg-config, which the project calls the easiest route and says may remove the need for custom build scripts entirely.

When the location is right but the version is not, LIBPCAP_VER sets the version explicitly, for example 1.5.0. The project says that should be necessary only for an old libpcap. Both variables have boundaries. LIBPCAP_LIBDIR is ignored on Windows, where nothing is linked at build time. With static linking the script cannot load the library to query it, so the version comes from pkgconfig/libpcap.pc under LIBPCAP_LIBDIR, and without that file the newest API is assumed. The same fallback applies on musl, where the build script itself is linked statically by default in rustup toolchains.

capture-stream turns the crate into a tokio citizen

The optional capture-stream feature enables access to Capture::stream, and it is off by default because it depends on tokio. Cargo.toml makes the coupling explicit: the feature list ties capture-stream to tokio, futures and windows-sys/Win32_System_Threading, with tokio pinned at 1.53.3 and the net, rt, macros and rt-multi-thread features enabled.

The cost shows up in the compiler requirement. The README states that when capture-stream is enabled the crate needs a compiler new enough to build tokio, which pushes the effective minimum version above the crate's own floor. For an async Rust service that is the natural configuration, and the streaming examples in the repository match it. For a small synchronous utility, leaving the feature off keeps tokio and futures out of the dependency graph entirely.

Rust 2024, an MSRV of 1.85 and a lockfile for MSRV builds

The crate uses Rust 2024 and states a minimum supported Rust version of 1.85, which also appears as rust-version in Cargo.toml. The dependency graph is not small: bitflags, libc and errno are always present, tokio, futures and gat-std are optional, windows-sys is added on Windows, and the dev-dependencies pull in etherparse, mockall, tempfile, tun-rs, once_cell and eui48.

The project is honest about a problem it cannot fully solve. Some dependencies have dropped support for the chosen compiler version, and semver gives maintainers no clean way to prevent that from reaching users. The answer offered is Cargo.lock: users protect themselves with their own lockfile, and the repository ships msrv.lock as the file the CI tests MSRV builds against. That pattern works for teams pinned to an older toolchain, and it also means the crate cannot quietly raise its compiler requirement on you.

Licensing is the least remarkable part. Cargo.toml declares MIT OR Apache-2.0, and the repository root carries both LICENSE-APACHE and LICENSE-MIT, so a downstream project may pick either. Keep the licence text for the option you choose with whatever you distribute.

Editorial conclusion

pcap is the right choice for a Rust engineer who needs raw frames from libpcap, wants one crate covering both Unix and Windows, and can satisfy the libpcap or Npcap prerequisite on the build machine. It is the wrong choice if you want a self-contained pure-Rust capture path, if your target is musl with a static build and no pkgconfig/libpcap.pc, or if raw socket privileges cannot be granted to your binary. Before adopting it, verify that the build script detects your system libpcap version correctly, decide whether the capture-stream feature is worth pulling tokio into your graph, and note that the last push was on 2026-10-18 with no tagged release to pin against.

Frequently asked questions

Does the pcap crate need libpcap installed on the system?

Yes. The crate requires the libpcap library, or Npcap on Windows. On Debian-based Linux the package is libpcap-dev, on Fedora it is libpcap-devel, and on macOS libpcap is installed by default.

How do I capture packets on Linux without running as root?

The README says that if you are not running as root you need to set capabilities on the binary, using setcap with cap_net_raw and cap_net_admin and the path to your executable. The privileges then belong to the binary rather than to the user account.

What does the capture-stream feature add and what does it pull in?

It enables access to Capture::stream and is disabled by default because it depends on tokio. Cargo.toml ties the feature to tokio, futures and windows-sys/Win32_System_Threading, with tokio pinned at 1.53.3, and enabling it raises the compiler version needed to build tokio.

Why does the build fail with cannot find function pcap_<some_function> in module raw?

That error usually means the build script could not determine which API your installed libpcap supports, so it left in features the library does not have. The README points to setting LIBPCAP_LIBDIR to the library directory or setting LIBPCAP_VER to the version explicitly, with pkg-config as the fallback detection route.

Which Rust version does the pcap crate require?

The crate uses Rust 2024 and requires a compiler version of 1.85 or newer, which is also declared as rust-version in Cargo.toml. Enabling capture-stream raises the floor further, because tokio must compile as well.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. rust-pcap/pcap on GitHub
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/rust-pcap-pcap.svg)](https://hysenlabs.com/projects/rust-pcap-pcap)

Was this useful?