ldap3

A pure Python LDAP v3 client library for querying and managing directory servers without any C bindings or system OpenLDAP dependency.

Library
PyPI
v2.9.1
935stars
LGPL-3.0-or-later

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity8
Maintenance0
Community84
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
70/100Good
Architecture80
Code Quality45
Innovation78
Learning Curve75

ldap3 is a pure Python implementation of the LDAP version 3 protocol (RFC 4510), built to run identically across CPython, PyPy, and PyPy3 without compiling against the system’s OpenLDAP libraries. It exposes the full set of low-level bind, search, add, modify, delete, compare, and extended operations, alongside a higher-level Abstract Layer that lets applications read and write directory entries as native Python objects instead of hand-building LDAP filters and BER-encoded attribute lists.

Connections can run under five different strategies — synchronous, asynchronous, restartable, thread-safe SAFE_SYNC/SAFE_RESTARTABLE, and a connection-pooling REUSABLE mode — so the same codebase backs a one-off script or a multithreaded service talking to Active Directory, OpenLDAP, NetIQ eDirectory, or any RFC-4510-compliant directory server. Built-in SASL, NTLM, and TLS support cover the authentication and transport-security needs of enterprise directory integrations.

What You Get

  • Full RFC 4510 coverage: bind, search, add, modify, delete, compare, and extended operations plus LDIF import/export.
  • An Abstract Layer that maps directory entries to Python objects with schema-aware attribute definitions, cursors, and writable entries.
  • Five connection strategies (SYNC, ASYNC, RESTARTABLE, SAFE_SYNC/SAFE_RESTARTABLE, REUSABLE) covering scripts, async workloads, and thread-safe pooled connections.
  • Built-in SASL mechanisms (EXTERNAL, DIGEST-MD5, GSSAPI/KERBEROS, PLAIN), NTLM authentication, and TLS/start_tls support with certificate validation.
  • Vendor-specific extensions for Microsoft Active Directory and NetIQ/Novell eDirectory alongside the standard RFC operations.

Common Use Cases

  • Authenticating application users against a corporate Active Directory or OpenLDAP server.
  • Querying and syncing employee or group data from a directory into an internal system.
  • Building admin tooling that creates, modifies, or deletes directory entries such as users, groups, and OUs.
  • Writing test suites against a mocked in-memory LDAP server via the mock strategies, without a live directory.

Under The Hood

Architecture The codebase splits cleanly by concern: core/ holds the Connection/Server façade, operation/ builds per-LDAP-operation requests, protocol/ implements the RFC ASN.1 wire format and SASL mechanisms, strategy/ implements a Strategy-pattern set of pluggable connection behaviors (sync, async, restartable, reusable, mock), and abstract/ layers an ORM-like API (ObjectDef/AttrDef/Entry/Cursor) on top of it all. The central Connection class in core/connection.py wires operation builders to protocol encoders through whichever strategy object was selected at construction time, so swapping transport/threading behavior never touches operation or protocol code — a clean separation, though Connection itself is a large façade that owns most of the public surface.

Tech Stack The library depends on pyasn1 for ASN.1 handling and pycryptodomex for cryptographic primitives, with optional winkerberos/gssapi extras for Kerberos SASL on Windows and Unix respectively. It ships its own internal ASN.1 BER encoder/decoder (utils/asn1.py) as a faster alternative to pyasn1, selectable via a DECODER=INTERNAL vs DECODER=PYASN1 flag exercised in CI. There is no web or ORM framework in play — this is a standalone protocol client using the standard socket and ssl modules under its own TLS wrapper (core/tls.py).

Code Quality The test/ directory holds 52 unittest-based modules driven by a shared test/config.py that opens real connections against a configurable LDAP server (STRATEGY/SERVER/DECODER env vars in .travis.yml), meaning most of the suite is integration-level rather than isolated unit tests. Error handling uses a dedicated typed exception hierarchy (core/exceptions.py: LDAPBindError, LDAPSocketReceiveError, etc.) rather than bare exceptions. No type hints, mypy, or linter/formatter configuration were found in the repo, and CI is defined only via a legacy Travis config targeting Python 2.7/3.8, which reads as stale relative to current Python versions.

API Design The standout ergonomics feature is the Abstract Layer: declare a schema once via ObjectDef/AttrDef, then read and write directory attributes as native Python types through Entry/Cursor/Writer objects, hiding the BER encoding and multi-valued-attribute quirks that raw LDAP APIs expose. Selecting among five connection strategies through a single client_strategy= constructor argument is unusual for a client library — most LDAP bindings expose only a thin synchronous wrapper and leave async, pooling, and retry behavior to the caller. Bundled MockSync/MockAsync strategies further let consumers unit-test LDAP-backed code without any external directory service, which is uncommon among protocol client libraries.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search