Registry / http-networking / pycares

pycares

JSON →
library5.0.1pypypi✓ verified 29d ago

Pycares is a Python module that provides an asynchronous interface to c-ares, a C library for performing DNS requests and name resolutions. It enables non-blocking DNS lookups, making it suitable for high-performance network applications. The library is actively maintained, currently at version 5.0.1, with regular releases addressing bug fixes and introducing new features.

pip install pycares
INSTALL
IMPORT
SIG · PYCARES
P
pycares
http-networkingpythonv5.0.1
Install
2.2s avg
Import
79ms
Disk
19MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v5.0.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.082s · 20.4MB
glibc
py 3.10–3.910 runs
installs and imports cleanly · install 2.2s · import 0.076s · 21MB
19MB installed
● package 19MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

pycares
✓ import pycares

This quickstart demonstrates how to perform asynchronous DNS queries for A and MX records using `pycares`. It sets up a `Channel` and makes two queries with a shared callback function. A basic `select`-based loop is used to process file descriptors and handle the asynchronous responses. In a production environment, `pycares` is typically integrated with a more robust event loop like `asyncio` (via `aiodns`), `Tornado`, or `Gevent`.

import pycares import socket def callback(result, error): if error: print(f"Error: {error}") return if result: for record in result.answer: if record.type == pycares.QUERY_TYPE_A: print(f"A record for {record.name}: {record.data.addr}") elif record.type == pycares.QUERY_TYPE_AAAA: print(f"AAAA record for {record.name}: {record.data.addr}") elif record.type == pycares.QUERY_TYPE_MX: print(f"MX record for {record.name}: priority={record.data.priority}, exchange={record.data.exchange}") # Add other record types as needed else: print("No records found.") # Using a simple select-based event loop channel = pycares.Channel(timeout=5.0) # Query for A records channel.query("google.com", pycares.QUERY_TYPE_A, callback=callback) # Query for MX records channel.query("example.com", pycares.QUERY_TYPE_MX, callback=callback) # Basic event loop processing while True: read_fds, write_fds = channel.getsockname() if not read_fds and not write_fds: break # In a real application, use an actual event loop (e.g., asyncio, Tornado, Gevent) # For this simple example, we block briefly try: rlist, wlist, xlist = socket.select(read_fds, write_fds, [], 1.0) except socket.error as e: print(f"Socket error in select: {e}") break channel.process_fd(rlist, wlist)
Debug
Known issues
breakingThe DNS query results API was completely rewritten in v5.0.0. Results are now returned as structured dataclasses (`DNSResult`, `DNSRecord`, and specific `RecordData` types like `ARecordData`, `MXRecordData`, etc.) instead of a list of record-specific objects. Existing code accessing results will break.
fix
Update your result parsing logic to expect `DNSResult` objects with `answer`, `authority`, and `additional` sections, and access record data via `record.data.addr`, `record.data.exchange`, etc. Refer to the v5.0.0 migration guide for details.
affects: >=5.0.0
breakingIn v5.0.0, the `Channel` constructor arguments and the `callback` parameter for query methods are now strictly keyword-only. The `event_thread` parameter has also been removed, as event thread mode is now implicit.
fix
Pass all `Channel` constructor arguments (e.g., `timeout`, `flags`, `lookups`) and the `callback` argument to query methods as keyword arguments. Remove any explicit `event_thread` arguments.
affects: >=5.0.0
breakingAs of v5.0.0, TXT record data is returned as bytes instead of strings. This change affects how TXT record content should be handled.
fix
Ensure your application decodes TXT record data (e.g., `record.data.data.decode('utf-8')`) if string representation is required.
affects: >=5.0.0
breakingPycares v5.0.0 switched its build system for the bundled c-ares library to CMake. Building from source now requires CMake version 3.5 or higher to be installed on the system.
fix
Install CMake (version 3.5+) on your system before attempting to build `pycares` from source (e.g., `apt-get install cmake` on Debian/Ubuntu, `brew install cmake` on macOS).
affects: >=5.0.0
gotchaImproper management of `pycares.Channel` objects, particularly allowing them to be garbage collected while DNS queries are still pending, can lead to a use-after-free vulnerability, causing a fatal Python interpreter crash.
fix
Ensure `Channel` objects are explicitly kept alive and properly managed for the entire duration of any pending DNS queries. Implement robust lifecycle management, especially in long-running or highly concurrent applications. Avoid creating `Channel` objects per-request that might be prematurely destroyed.
affects: <=5.0.1 (general concern, specific fixes likely in 5.x)
gotchaDNS queries made by `pycares` are real network operations. Consequently, tests and examples often require active internet access and can be sensitive to network conditions or DNS server configurations, potentially leading to environment-specific failures.
fix
When developing or testing, ensure a stable network connection and a properly configured DNS resolver. Account for network-related errors in your application's error handling for DNS lookups.
affects: All
breakingThe `Channel.getsockname()` method has been removed in v5.0.0. Code relying on this method for manual polling of file descriptors will encounter an AttributeError.
fix
Remove calls to `Channel.getsockname()`. For integrating `pycares` with custom event loops, refer to the v5.0.0 migration guide for updated methods, typically involving `channel.poll()`, `channel.fd`, or `asyncio` integration.
affects: >=5.0.0
breakingThe `getsockname` method has been removed from the `pycares.Channel` object. This impacts custom event loop integrations that previously relied on `getsockname` to obtain file descriptors for polling.
fix
The `getsockname` method on `Channel` objects has been removed. Instead of manually polling file descriptors via `select.select` and `getsockname`, integrate `pycares` with an event loop using `channel.loop()` or by registering `channel.fileno()` with your event loop and calling `channel.handle_event(fd, flag)` when events are ready. Refer to the v5.0.0 migration guide or updated examples for detailed event loop integration.
affects: >=5.0.0
Errors
Common errors & fixes
ERROR: Failed building wheel for pycares
This error typically occurs during installation when required C compilation tools (like `gcc` or `clang`) or Python development headers are missing on the system, preventing the `pycares` C extension from being built.
fix
Ensure that your system has the necessary build tools and Python development headers. For Debian/Ubuntu, run: `sudo apt-get update && sudo apt-get install build-essential python3-dev`. For Fedora/RHEL: `sudo dnf groupinstall "Development Tools" && sudo dnf install python3-devel`. For macOS, install Xcode Command Line Tools: `xcode-select --install`. Then, try `pip install pycares` again.
ModuleNotFoundError: No module named 'pycares._cares'
This error indicates that the `pycares` C extension module, `_cares`, was not correctly built or cannot be found by Python, often due to a failed or incomplete installation, or issues within a virtual environment.
fix
Reinstall `pycares`, potentially forcing a source build to ensure the C extension is properly compiled: `pip install --upgrade --force-reinstall --no-binary pycares pycares`. Ensure all build dependencies mentioned in the previous fix are also installed.
AttributeError: module 'pycares' has no attribute 'ares_query_a_result'
This `AttributeError` arises when a dependent library (such as `aiodns`) attempts to use a function or constant (like `ares_query_a_result` or `QUERY_TYPE_CAA`) that exists in a newer version of `pycares`, but an older, incompatible version of `pycares` is currently installed.
fix
Upgrade your `pycares` installation to the latest version or a version compatible with the dependent library's requirements: `pip install --upgrade pycares`.
Fatal Python error: b_from_handle: ffi.from_handle() detected that the address passed points to garbage
This fatal error is a result of a use-after-free vulnerability in `pycares` versions prior to 4.9.0, where a `Channel` object could be garbage collected while active DNS queries were still pending, causing a crash when c-ares attempted to access freed memory for callbacks.
fix
Upgrade `pycares` to version 4.9.0 or newer, which includes a fix for this vulnerability: `pip install --upgrade pycares`. It is also recommended to explicitly close `pycares.Channel` objects when done or use them as context managers (e.g., `with pycares.Channel() as channel:`).
Upgrade
Version history
5.0.1latest on PyPI · released Jan 1, 2026
Audit
Dependencies
cffirequiredRequired for the Python C interface; version 1.5.0 or higher is needed for Python < 3.14, and 2.0.0b1 or higher for Python >= 3.14.
idnaoptionalProvides IDNA 2008 encoding support; otherwise, the built-in IDNA 2003 codec is used.
c-aresrequiredThe underlying C library for asynchronous DNS resolution. pycares bundles c-ares by default, but a system-wide c-ares can be used by setting PYCARES_USE_SYSTEM_LIB=1 during build.
cmakerequiredRequired (version >= 3.5) to build pycares from source, as it's used to compile the bundled c-ares library.
Agent activity
18 hits · last 30 days
node
16
Resources
pycares — pip install pycares · libregistry