Skip to content

Add async support with AsyncAnticaptchaClient#131

Merged
ad-m merged 9 commits intomasterfrom
claude/add-async-support-oN5u6
Mar 7, 2026
Merged

Add async support with AsyncAnticaptchaClient#131
ad-m merged 9 commits intomasterfrom
claude/add-async-support-oN5u6

Conversation

@ad-m
Copy link
Owner

@ad-m ad-m commented Mar 7, 2026

Summary

This PR adds comprehensive async/await support to the python-anticaptcha library through a new AsyncAnticaptchaClient class, enabling seamless integration with async frameworks like FastAPI, aiohttp, and Starlette.

Key Changes

  • New async client: Added AsyncAnticaptchaClient and AsyncJob classes that mirror the sync API but use httpx.AsyncClient for HTTP requests and asyncio for async operations
  • Code refactoring: Extracted common functionality into _BaseClientMixin and _BaseJobMixin to eliminate duplication between sync and async implementations
  • Module reorganization:
    • Moved sync client code from base.py to new sync_client.py
    • Created new async_client.py for async implementation
    • Created _common.py for shared base classes and constants
    • Updated base.py to re-export from sync_client.py for backward compatibility
  • Optional dependency: Async support requires httpx and is installed via pip install python-anticaptcha[async]
  • Documentation: Added async usage examples in README and docs, including a complete integration example (examples/async_recaptcha_request.py)
  • Test coverage: Added comprehensive test suite for async client (tests/test_async_client.py) with 290+ lines covering initialization, response handling, task creation, job polling, and context manager behavior
  • Example scripts: Added async examples (async_balance.py, async_recaptcha_request.py) and renamed existing examples with sync_ prefix for clarity

Implementation Details

  • The async client uses httpx.AsyncClient for HTTP operations instead of requests.Session
  • All I/O operations are properly awaitable (task creation, result polling, balance checks, etc.)
  • The AsyncJob.join() method uses asyncio.sleep() for non-blocking polling
  • Error handling for IP-based errors (errorId 11) is async-aware with _get_client_ip() as an async method
  • Both sync and async clients support context managers (async with for async, with for sync)
  • Snake_case method aliases are provided for both sync and async clients for consistency
  • Backward compatibility is maintained through re-exports in base.py

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm

claude added 9 commits March 7, 2026 15:09
Add a new async_client module providing AsyncAnticaptchaClient and AsyncJob
classes that mirror the sync API but use httpx.AsyncClient and asyncio.sleep
for non-blocking operation in async frameworks (FastAPI, aiohttp, etc.).

This is a non-breaking change: the sync API is untouched, httpx remains an
optional dependency (pip install python-anticaptcha[async]), and the new
classes are lazily imported in __init__.py to avoid requiring httpx at
package import time.

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
- Extract _BaseClientMixin and _BaseJobMixin into _common.py to share
  init logic, payload builders, solution getters, and repr between
  sync and async clients
- Refactor AnticaptchaClient and AsyncAnticaptchaClient to inherit
  from shared mixins, reducing maintenance burden
- Add "Async Usage" section to README.md and docs/usage.rst
- Add async_client automodule to docs/api.rst
- Add CHANGELOG.rst entries for async support
- Add async example scripts (async_recaptcha_request.py, async_balance.py)
- Add "Framework :: AsyncIO" and "Topic :: Internet :: WWW/HTTP" classifiers
- Add "asyncio", "async", "httpx" keywords for PyPI discoverability

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
- Rename base.py → sync_client.py for symmetry with async_client.py;
  add backward-compat base.py re-export shim
- Rename all sync example files with sync_ prefix to match async_ examples
- Rename test_base.py → test_sync_client.py
- Promote "Async Usage" to same heading level as sync in README and docs
- Add "Sync client" heading in docs/usage.rst for symmetry
- Rename "Base" → "Sync Client" in docs/api.rst
- Update __init__.py to import from sync_client instead of base
- All existing import paths preserved for backward compatibility

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
- Adopt upstream improvements: backoff support in Job.join(), assert
  statements, Literal type hints, code quality fixes
- Make async_client.py standalone (remove _common.py mixin dependency)
  to match upstream's standalone sync_client.py style
- Remove _common.py — both clients are now self-contained
- Update CHANGELOG to remove _common.py reference
- Resolve merge conflicts in __init__.py, base.py, test_sync_client.py

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
The module-level ImportError prevented Sphinx autodoc from importing
async_client when httpx is not installed. Now the module imports
successfully (setting httpx=None) and raises ImportError only when
AsyncAnticaptchaClient is instantiated without httpx.

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
- Fix ruff import sorting in __init__.py, test_sync_client.py,
  test_async_client.py
- Fix ruff-format: async_client.py await parenthesization,
  string concatenation
- Fix mypy: add return type to __getattr__, add type:ignore for
  optional httpx import
- Add httpx to test dependencies so async tests work in CI
- Remove redundant explicit imports from base.py shim (covered by *)

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
The example files were renamed with sync_ prefix but test_examples.py
still imported them by their old names.

https://claude.ai/code/session_01Pimg4VAco2v4srPeZj44Zm
@ad-m ad-m merged commit 3a7840e into master Mar 7, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants