Skip to main content

py-libp2p

py-libp2p hex logo

The Python implementation of the libp2p networking stack.

Discord PyPI version Python versions Build Status Docs build

py-libp2p has moved beyond its experimental roots and is steadily progressing toward production readiness. The core features are stable, and we’re focused on refining performance, expanding protocol support, and ensuring smooth interop with other libp2p implementations. We welcome contributions and real-world usage feedback to help us reach full production maturity.

Read more in the documentation on ReadTheDocs. View the release notes.

Maintainers

Currently maintained by @pacrob, @seetadev and @dhuseby. Please reach out to us for collaboration or active feedback. If you have questions, feel free to open a new discussion. We are also available on the libp2p Discord — join us at #py-libp2p sub-channel.

Feature Breakdown

py-libp2p aims for conformity with the standard libp2p modules. Below is a breakdown of the modules we have developed, are developing, and may develop in the future.

Legend: ✅: Done  🛠️: In Progress/Usable  🌱 Prototype/Unstable  ❌: Missing


Transports

Transport Status Source
libp2p-tcp ✅ source
libp2p-quic ✅ source
libp2p-websocket ✅ source
libp2p-webtransport 🌱 source
libp2p-webrtc-browser-to-server 🌱
libp2p-webrtc-private-to-private 🌱

WebRTC-Direct (browser/server) uses the spec STUN path by default: inbound dials hit a shared UDP port and the listener infers the offer from the first STUN packet; outbound dials synthesise an ICE-Lite answer from the multiaddr with no default public STUN servers. This is the only signalling path that interoperates with go-libp2p / js-libp2p / browsers. An experimental HTTP POST /sdp harness (WebRTCTransportConfig(enable_sdp_http_harness=True)) is for py↔py debugging only and is not interoperable — leave it off in production.

Choosing a dial version. The listener always accepts both v1 and v2; the dialer picks with WebRTCTransportConfig(webrtc_direct_dial_version=1|2):

  • v1 (default today) — the migration path (SDP ufrag/pwd munging). Kept the default while libp2p/specs#715 is unmerged so existing v1 peers keep working.
  • v2 (recommended) — the specs#715 flow, no SDP munging. Prefer it for new deployments; browser dialling needs v2 once NoSdpMangleUfrag support is widespread. The default flips to v2 once specs#715 lands.

NAT Traversal

NAT Traversal Status Source
libp2p-circuit-relay-v2 ✅ source
libp2p-autonat ✅ source
libp2p-hole-punching ✅ source

Secure Communication

Secure Communication Status Source
libp2p-noise ✅ source
libp2p-tls ✅

Discovery

Discovery Status Source
bootstrap ✅ source
random-walk ✅ source
mdns-discovery ✅ source
rendezvous ✅ source

Peer Routing

Peer Routing Status Source
libp2p-kad-dht ✅ source

Publish/Subscribe

Publish/Subscribe Status Source
libp2p-floodsub ✅ source
libp2p-gossipsub ✅ source

Stream Muxers

Stream Muxers Status Source
libp2p-yamux ✅ source
libp2p-mplex ✅ source

Storage

Storage Status
libp2p-record ✅

General Purpose Utilities & Datatypes

Utility/Datatype Status Source
libp2p-ping ✅ source
libp2p-peer ✅ source
libp2p-identify ✅ source

Identity Persistence

For a stable Peer ID across restarts, use opt-in identity helpers (default new_host() behavior is unchanged and still generates a random Ed25519 key):

  • File helpers: libp2p.identity_utils — save_identity / load_identity / create_identity_from_seed (libp2p protobuf private-key format; Unix mode 0600).
  • Key-pair provider: new_host(key_pair_provider=...) accepts Callable[[], KeyPair] as described in issue #312.
  • Filesystem keystore: FileSystemKeyStore stores named keys under a directory; pass new_host(keystore=..., identity_name="default") to load or auto-persist.

Prefer these APIs over the legacy PEM helpers save_keypair / load_keypair (Ed25519-only, fixed path).

Example (keystore)::

from pathlib import Path
from libp2p import new_host
from libp2p.crypto.keystore import FileSystemKeyStore

store = FileSystemKeyStore(Path.home() / ".config" / "py-libp2p" / "keystore")
host = new_host(keystore=store, identity_name="default")
# Subsequent runs with the same store/name reuse the same Peer ID.

Explanation of Basic Two Node Communication

Core Concepts

(non-normative, useful for team notes, not a reference)

Several components of the libp2p stack take part when establishing a connection between two nodes:

  1. Host: a node in the libp2p network.
  2. Connection: the layer 3 connection between two nodes in a libp2p network.
  3. Transport: the component that creates a Connection, e.g. TCP, UDP, QUIC, etc.
  4. Streams: an abstraction on top of a Connection representing parallel conversations about different matters, each of which is identified by a protocol ID. Multiple streams are layered on top of a Connection via the Multiplexer.
  5. Multiplexer: a component that is responsible for wrapping messages sent on a stream with an envelope that identifies the stream they pertain to, normally via an ID. The multiplexer on the other unwraps the message and routes it internally based on the stream identification.
  6. Secure channel: optionally establishes a secure, encrypted, and authenticated channel over the Connection.
  7. Upgrader: a component that takes a raw layer 3 connection returned by the Transport, and performs the security and multiplexing negotiation to set up a secure, multiplexed channel on top of which Streams can be opened.

Communication between two hosts X and Y

(non-normative, useful for team notes, not a reference)

Initiate the connection: A host is simply a node in the libp2p network that is able to communicate with other nodes in the network. In order for X and Y to communicate with one another, one of the hosts must initiate the connection. Let's say that X is going to initiate the connection. X will first open a connection to Y. This connection is where all of the actual communication will take place.

Communication over one connection with multiple protocols: X and Y can communicate over the same connection using different protocols and the multiplexer will appropriately route messages for a given protocol to a particular handler function for that protocol, which allows for each host to handle different protocols with separate functions. Furthermore, we can use multiple streams for a given protocol that allow for the same protocol and same underlying connection to be used for communication about separate topics between nodes X and Y.

Why use multiple streams?: The purpose of using the same connection for multiple streams to communicate over is to avoid the overhead of having multiple connections between X and Y. In order for X and Y to differentiate between messages on different streams and different protocols, a multiplexer is used to encode the messages when a message will be sent and decode a message when a message is received. The multiplexer encodes the message by adding a header to the beginning of any message to be sent that contains the stream id (along with some other info). Then, the message is sent across the raw connection and the receiving host will use its multiplexer to decode the message, i.e. determine which stream id the message should be routed to.

Support

Support py-libp2p on drips.network

Metadata

Release files for libp2p 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for libp2p 0.8.1
File Size Uploaded Provenance
libp2p-0.8.1.tar.gz 36.3 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for libp2p 0.8.1
File Interpreter ABI Platform
libp2p-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 37.6 MB

Release files / libp2p-0.8.1.tar.gz

Download URL libp2p-0.8.1.tar.gz
Size 36.3 MB
Tags Source
SHA-256 checksum
How to use checksums
3fb1493d215d10205f56095014e21c3d4eec025a9becb3e73a768d1151f27fd0
BLAKE2b-256 checksum
How to use checksums
55077da82f3cf3705278c583a5353a1235875ea886324ee7d3cd94ebd4404e56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Release files / libp2p-0.8.1-py3-none-any.whl

Download URL libp2p-0.8.1-py3-none-any.whl
Size 1.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3d53daa20a6a78984c9b4ed1654d771757b187282f90376d7156c2b67828b308
BLAKE2b-256 checksum
How to use checksums
bcc0bc99a6cfb57965313649c3d6f899fa00e51f6b05fb3418459a052d7392b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Security for libp2p 0.8.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page