{"library":"aiodns","title":"aiodns","description":"aiodns is a Python library that provides a simple way to perform asynchronous DNS resolutions using the `asyncio` framework and `pycares` as its backend. The current version is 4.0.0, and it generally follows an active release cadence with several updates throughout the year to improve performance, add features, and maintain compatibility with newer Python and `pycares` versions.","status":"active","version":"4.0.0","language":"en","source_language":"en","source_url":"https://github.com/saghul/aiodns","tags":["async","dns","asyncio","network","resolver"],"install":[{"cmd":"pip install aiodns","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Required backend for DNS resolution; aiodns is a wrapper around pycares.","package":"pycares","optional":false}],"imports":[{"symbol":"DNSResolver","correct":"from aiodns import DNSResolver"},{"note":"DNSError is part of the 'error' submodule.","symbol":"DNSError","correct":"from aiodns import error"}],"quickstart":{"code":"import asyncio\nfrom aiodns import DNSResolver\n\nasync def resolve_a_record(hostname):\n    resolver = DNSResolver()\n    try:\n        # query_dns returns native pycares 5.x DNSResult types\n        result = await resolver.query_dns(hostname, 'A')\n        for record in result.answer:\n            print(f\"Hostname: {hostname}, Type: A, Address: {record.data.addr}\")\n    except Exception as e:\n        print(f\"DNS resolution failed for {hostname}: {e}\")\n    finally:\n        # It's important to close the resolver when no longer needed.\n        # For long-lived resolvers, manual closing is often done at application shutdown.\n        resolver.close()\n\nasync def main():\n    await resolve_a_record('google.com')\n    await resolve_a_record('nonexistent.example.com') # Example of a failed lookup\n\nif __name__ == '__main__':\n    asyncio.run(main())","lang":"python","description":"This quickstart demonstrates how to perform an asynchronous 'A' record DNS lookup using the `DNSResolver` class and its recommended `query_dns` method. It includes basic error handling and shows the crucial step of closing the resolver to release resources."},"warnings":[{"fix":"Ensure `pycares` is updated to version 5.0.0 or higher by running `pip install 'pycares>=5.0.0'`.","message":"Version 4.0.0 introduces a breaking change requiring `pycares >= 5.0.0`. Older `pycares` versions are incompatible and will cause issues.","severity":"breaking","affected_versions":"4.0.0 and later"},{"fix":"Migrate your code to use `await resolver.query_dns(host, type)` instead of `await resolver.query(host, type)` to benefit from native `pycares` result types and future compatibility. Review `pycares` documentation for details on `DNSResult` structure.","message":"The `query()` method is deprecated in favor of `query_dns()`. While `query()` still works for backward compatibility with `aiodns 3.x` result types, `query_dns()` returns native `pycares 5.x DNSResult` types which are preferred.","severity":"deprecated","affected_versions":"4.0.0 and later"},{"fix":"Replace calls to `gethostbyname()` with `getaddrinfo()`. This aligns with modern socket API practices and offers better IPv6 support and flexibility.","message":"The `gethostbyname()` method is deprecated. Use `getaddrinfo()` instead for host and port resolution.","severity":"deprecated","affected_versions":"4.0.0 and later"},{"fix":"For most applications, create a single `DNSResolver` instance and reuse it. Call `resolver.close()` explicitly when the application is shutting down or the resolver is definitively no longer needed. Avoid creating and destroying `DNSResolver` objects in a tight loop.","message":"`DNSResolver` instances are designed to be long-lived and reused across many queries to avoid unnecessary overhead. While `DNSResolver` supports the async context manager (`async with DNSResolver()`), using it for frequent, short-lived instances is discouraged due to performance implications. It's best suited for testing or one-off scripts where automatic cleanup is critical.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Most users can safely ignore this warning when using official `pycares` wheels. If you encounter issues on Windows or are using a custom `pycares` build, consider explicitly setting the event loop to `SelectorEventLoop` or using `winloop`.","message":"On Windows, if you are using a custom build of `pycares` that links against a non-thread-safe `c-ares` library, `aiodns` might require `asyncio.SelectorEventLoop` or `winloop`. This is generally not an issue for users of official prebuilt `pycares` wheels (version 4.7.0 or later), as they include a thread-safe `c-ares`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-05T00:00:00.000Z","next_check":"2026-07-04T00:00:00.000Z"}