Install & Compatibility
Where this runs
tested against v? · pip install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
build_error
glibcpy 3.10–3.95 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
modlist
✓ from ldap import modlist
✗ import ldap.modlist # Access via ldap.modlist is okay, but from ldap import modlist is more direct for common use.
modlist is commonly used for creating/comparing LDAP modification lists.
ldap.dn
✓ import ldap.dn
Used for DN manipulation and escaping.
ldap.filter
✓ import ldap.filter
Used for filter manipulation and escaping.
This quickstart demonstrates how to establish a connection to an LDAP server, perform a simple bind, search for entries, and process the results. It highlights the use of `ldap.initialize`, `simple_bind_s`, and `search` with error handling. Note the explicit encoding of strings to bytes, which is crucial for python-ldap 3.x.
import ldap
import os
# Configure LDAP server details
LDAP_SERVER_URI = os.environ.get('LDAP_SERVER_URI', 'ldap://localhost:389')
LDAP_BIND_DN = os.environ.get('LDAP_BIND_DN', 'cn=admin,dc=example,dc=org')
LDAP_BIND_PASSWORD = os.environ.get('LDAP_BIND_PASSWORD', 'adminpassword')
LDAP_SEARCH_BASE = os.environ.get('LDAP_SEARCH_BASE', 'dc=example,dc=org')
LDAP_SEARCH_FILTER = os.environ.get('LDAP_SEARCH_FILTER', '(objectClass=person)')
LDAP_SEARCH_ATTRIBUTES = ['cn', 'mail']
try:
# Initialize LDAP connection
l = ldap.initialize(LDAP_SERVER_URI)
l.set_option(ldap.OPT_REFERRALS, 0)
l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# Bind to the directory
l.simple_bind_s(LDAP_BIND_DN.encode('utf-8'), LDAP_BIND_PASSWORD.encode('utf-8'))
print(f"Successfully bound to {LDAP_SERVER_URI}")
# Search the directory
result_id = l.search(
LDAP_SEARCH_BASE.encode('utf-8'),
ldap.SCOPE_SUBTREE,
LDAP_SEARCH_FILTER.encode('utf-8'),
LDAP_SEARCH_ATTRIBUTES
)
results = []
while True:
result_type, result_data = l.result(result_id, 0)
if not result_data:
break
if result_type == ldap.RES_SEARCH_ENTRY:
for dn, entry in result_data:
results.append((dn.decode('utf-8'), {k.decode('utf-8'): [v.decode('utf-8') for v in val] for k, val in entry.items()}))
print(f"Found {len(results)} entries:")
for dn, entry in results:
print(f"DN: {dn}")
print(f" CN: {entry.get('cn')}")
print(f" Mail: {entry.get('mail')}")
except ldap.SERVER_DOWN as e:
print(f"LDAP server down or connection failed: {e}")
except ldap.LDAPError as e:
print(f"LDAP Error: {e}")
finally:
# Unbind from the directory
if 'l' in locals() and l:
try:
l.unbind_s()
print("Unbound from LDAP server.")
except ldap.LDAPError as e:
print(f"Error during unbind: {e}")
Debug
Known issues
breakingpython-ldap 3.x is Python 3 ONLY. Version 3.0.0 dropped support for Python 2.x entirely. Attempts to use python-ldap 3.x in a Python 2 environment will fail.fixEnsure your project is running on Python 3.6+ (3.4.0+ requires 3.6+). For Python 2 compatibility, you must use python-ldap 2.x, which is no longer maintained.
affects: 3.0.0 and newer
breakingAll string data in python-ldap 3.x is handled as bytes. Inputs for DNs, filters, attribute names/values, and outputs from search operations are bytes. This is a fundamental change from python-ldap 2.x and is a common source of `TypeError` or unexpected behavior.fixExplicitly encode Python strings to bytes (e.g., `my_string.encode('utf-8')`) when passing them to python-ldap functions. Decode byte results back to strings (e.g., `my_bytes.decode('utf-8')`) when consuming them. affects: 3.0.0 and newer
deprecatedThe `ldap.open()` and `ldap.init()` functions were deprecated and completely removed in version 3.1.0.fixAlways use `ldap.initialize()` to create an LDAPObject instance.
affects: 3.1.0 and newer
deprecatedThe `OPT_X_TLS` option was removed in 3.4.2, brought back as deprecated in 3.4.3, and is slated for final removal in version 3.5.0. Relying on this option may cause future breaking changes.fixMigrate to `OPT_X_TLS_CACERTFILE`, `OPT_X_TLS_CERTFILE`, `OPT_X_TLS_KEYFILE`, etc., for specific TLS configuration. Consult OpenLDAP documentation for recommended TLS options.
affects: 3.4.2, 3.4.3, 3.4.4, 3.4.5 (and future 3.5.0+)
gotchaThe return type of `LDAPObject.compare_s()` and `LDAPObject.compare_ext_s()` changed from an integer (0 or 1) to a boolean (`False` or `True`) in version 3.1.0. Code expecting an integer return value may behave incorrectly.fixUpdate logic to expect and handle boolean `True`/`False` values instead of integers for comparison results.
affects: 3.1.0 and newer
gotchaVersions prior to 3.4.5 had security vulnerabilities (CVE-2025-61911, CVE-2025-61912) related to improper escaping of input in `ldap.filter.escape_filter_chars` and `ldap.dn.escape_dn_chars`.fixUpgrade to python-ldap 3.4.5 or newer. When using `escape_filter_chars`, ensure `str` input when `escape_mode=1`. For DNs, verify NUL character handling. Always validate and sanitize user inputs meticulously.
affects: 3.x up to 3.4.4
Errors
Common errors & fixes
ModuleNotFoundError: No module named '_ldap'
The `python-ldap` library requires OpenLDAP development headers and libraries to compile its internal `_ldap` C extension module, which failed during installation.
fixInstall the necessary OpenLDAP development packages for your operating system (e.g., `sudo apt-get install libldap2-dev libsasl2-dev` on Debian/Ubuntu or `sudo yum install openldap-devel cyrus-sasl-devel` on RHEL/CentOS) before running `pip install python-ldap`.
ldap.LDAPError: (81, 'Can\'t contact LDAP server')
The `python-ldap` client failed to establish a network connection to the specified LDAP server, often due to an incorrect host/port, the server being down, or a firewall blocking access.
fixVerify the LDAP server's hostname, port, and network reachability. Ensure the server is running and accessible, and check for any firewall rules that might be blocking the connection.
ldap.LDAPError: (49, 'Invalid credentials')
The Distinguished Name (DN) or password provided during the LDAP bind operation is incorrect or does not have sufficient permissions to authenticate.
fixDouble-check the exact DN and password used for binding. Ensure the user's credentials are valid and have the necessary permissions.
ldap.LDAPError: (32, 'No such object')
The target Distinguished Name (DN) specified for a search base, modification, or deletion operation does not exist in the LDAP directory.
fixVerify the correctness of the DN. Use an LDAP browser or an existing search to confirm the object's existence and its exact path in the directory.
Upgrade
Version history
3.4.7latest on PyPI · released May 20, 2026
Audit
Dependencies
pyasn1requiredRequired for ASN.1 encoding/decoding, introduced in 3.0.0.
pyasn1_modulesrequiredRequired for ASN.1 encoding/decoding, introduced in 3.0.0.