{"id":908,"library":"opentelemetry-instrumentation-httpx","title":"OpenTelemetry HTTPX Instrumentation","description":"OpenTelemetry HTTPX Instrumentation provides automatic tracing for HTTPX, a modern HTTP client for Python supporting both synchronous and asynchronous APIs. It is part of the OpenTelemetry Python Contrib project, which is actively developed and receives frequent beta releases, generally aligning with the core OpenTelemetry Python SDK's release cadence.","status":"active","version":"0.61b0","language":"python","source_language":"en","source_url":"https://github.com/open-telemetry/opentelemetry-python-contrib","tags":["opentelemetry","observability","tracing","http client","httpx","asynchronous","instrumentation"],"install":[{"cmd":"pip install opentelemetry-instrumentation-httpx opentelemetry-sdk opentelemetry-exporter-otlp-proto-http httpx","lang":"bash","label":"Full Installation"}],"dependencies":[{"reason":"The HTTP client being instrumented.","package":"httpx"},{"reason":"Core OpenTelemetry API.","package":"opentelemetry-api"},{"reason":"Core OpenTelemetry SDK for tracer providers and span processors.","package":"opentelemetry-sdk"},{"reason":"Common exporter for sending telemetry data to an OpenTelemetry Collector via HTTP, often used in examples.","package":"opentelemetry-exporter-otlp-proto-http","optional":true}],"imports":[{"note":"The main class to instrument HTTPX clients.","symbol":"HTTPXClientInstrumentor","correct":"from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor"},{"note":"Alternative for explicit synchronous transport instrumentation.","symbol":"SyncOpenTelemetryTransport","correct":"from opentelemetry.instrumentation.httpx import SyncOpenTelemetryTransport"},{"note":"Alternative for explicit asynchronous transport instrumentation.","symbol":"AsyncOpenTelemetryTransport","correct":"from opentelemetry.instrumentation.httpx import AsyncOpenTelemetryTransport"}],"quickstart":{"code":"import asyncio\nimport httpx\nfrom opentelemetry import trace\nfrom opentelemetry.sdk.resources import Resource\nfrom opentelemetry.sdk.trace import TracerProvider\nfrom opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor\nfrom opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor\nimport os\n\n# Configure OpenTelemetry SDK\nresource = Resource.create({\"service.name\": os.environ.get(\"OTEL_SERVICE_NAME\", \"httpx-client-app\")})\nprovider = TracerProvider(resource=resource)\nprocessor = BatchSpanProcessor(ConsoleSpanExporter())\nprovider.add_span_processor(processor)\ntrace.set_tracer_provider(provider)\n\n# Instrument all HTTPX clients\nHTTPXClientInstrumentor().instrument()\n\nasync def make_async_request():\n    print(\"\\nMaking async HTTPX request...\")\n    async with httpx.AsyncClient() as client:\n        response = await client.get(\"https://example.com\")\n        print(f\"Async request status: {response.status_code}\")\n\ndef make_sync_request():\n    print(\"\\nMaking sync HTTPX request...\")\n    with httpx.Client() as client:\n        response = client.get(\"https://example.com\")\n        print(f\"Sync request status: {response.status_code}\")\n\nif __name__ == \"__main__\":\n    make_sync_request()\n    asyncio.run(make_async_request())\n    print(\"\\nTraces should be printed above (if ConsoleSpanExporter is used).\")\n","lang":"python","description":"This quickstart demonstrates how to set up the OpenTelemetry SDK and instrument both synchronous and asynchronous HTTPX clients. After running, you should see trace information printed to the console (if using ConsoleSpanExporter)."},"warnings":[{"fix":"Update to the latest instrumentation version. To facilitate migration, set the environment variable `OTEL_SEMCONV_STABILITY_OPT_IN=http/dup` to emit both old and new attributes during transition, then switch to `http` to emit only stable attributes.","message":"OpenTelemetry's HTTP Semantic Conventions have been stabilized, leading to attribute name changes (e.g., `http.url` to `url.full`, `http.status_code` to `http.response.status_code`).","severity":"breaking","affected_versions":"<=0.60b0"},{"fix":"Ensure `HTTPXClientInstrumentor().instrument()` is called as early as possible in your application's lifecycle, preferably before any HTTPX clients are created. For single-client instrumentation, use `HTTPXClientInstrumentor.instrument_client(client_instance)`.","message":"HTTPX clients or their subclasses instantiated *before* `HTTPXClientInstrumentor().instrument()` is called will not be instrumented. This is particularly relevant when using libraries that internally create HTTPX clients (e.g., `openai-python`).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Consider using a single worker for pre-fork servers or exploring workarounds like programmatic auto-instrumentation or specific configurations for your deployment environment. Refer to OpenTelemetry troubleshooting guides for detailed strategies.","message":"Pre-fork servers (like Gunicorn with multiple workers) can cause issues with metrics generation when using OpenTelemetry auto-instrumentation due to threading and lock inconsistencies in child processes.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use the environment variable `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS` with a comma-delimited list of header names (regex supported) to redact values. For custom payload logging, implement `request_hook` and `response_hook` functions, being mindful of data sensitivity.","message":"By default, sensitive HTTP headers and request/response bodies are not captured or are sanitized. Directly logging or capturing raw payloads can expose sensitive data.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your environment has the necessary root CA certificates installed. For Debian-based Docker images, this typically means adding `RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*` to your Dockerfile. For other environments, ensure your system's SSL certificate store is up-to-date and correctly configured.","message":"Networking requests via HTTPX may fail with `SSL: CERTIFICATE_VERIFY_FAILED` errors, particularly in minimal container environments (e.g., `python:*-slim` Docker images). This indicates a missing or outdated root CA certificate bundle required to verify SSL connections.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your environment has the necessary CA certificates installed (e.g., `apk add ca-certificates` on Alpine Linux, or mount appropriate certificate bundles). For testing, you can disable SSL verification in HTTPX by passing `verify=False` to the `httpx.Client` constructor, but this is not recommended for production environments.","message":"When running in minimal environments (e.g., Alpine Docker images), SSL certificate validation for HTTPS requests may fail with `CERTIFICATE_VERIFY_FAILED`. This is an environmental issue due to missing root CA certificates, not a bug in the instrumentation, but it prevents HTTPX requests from completing.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T21:12:15.235Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Ensure that `HTTPXClientInstrumentor().instrument()` is called at the very beginning of your application's startup, before any `httpx.Client` or `httpx.AsyncClient` subclasses are defined or instances are created.","cause":"The OpenTelemetry HTTPX instrumentation monkey-patches `httpx.Client` and `httpx.AsyncClient` by replacing them with instrumented versions. If a subclass of `httpx.Client` or an instance of `httpx.Client` is created before `HTTPXClientInstrumentor().instrument()` is called, it will use the original, uninstrumented classes.","error":"HttpX instrumentation does not work on classes that extend httpx client"},{"fix":"While `HTTPXClientInstrumentor().instrument()` is intended to instrument all clients, including those implicitly used by functional calls, explicitly creating and using an `httpx.Client` or `httpx.AsyncClient` instance after instrumentation is a more robust approach. Alternatively, ensure your OpenTelemetry SDK and instrumentation packages are up-to-date.","cause":"When using the functional API (`httpx.get`, `httpx.post`, etc.) directly without explicitly creating an `httpx.Client` instance, the global instrumentation might not correctly capture these calls in some configurations or older versions of the library.","error":"httpx instrumentation doesn't work for `httpx.get`, `httpx.post`, etc."},{"fix":"Install the package using `pip install opentelemetry-instrumentation-httpx`. Verify that you are running your application with the same Python environment where the package was installed, and ensure `opentelemetry-sdk` is also installed.","cause":"This error occurs because the `opentelemetry-instrumentation-httpx` package is either not installed, installed in a different Python environment than the one running the application, or there is a conflict with OpenTelemetry's namespace packages.","error":"ModuleNotFoundError: No module named 'opentelemetry.instrumentation.httpx'"},{"fix":"A known fix involves patching `self._mounts` in the `_InstrumentedClient` to use `SyncOpenTelemetryTransport` directly. This indicates that the instrumentation might not be correctly wrapping the transport layer when proxies are involved. Check the latest library versions for a permanent fix or refer to GitHub issues for workarounds.","cause":"The default `opentelemetry-instrumentation-httpx` might not correctly apply tracing to HTTPX clients when a proxy is configured, leading to missing traces for requests made through the proxy.","error":"httpx instrumentation does not work when proxy is set"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.62b1","cli_name":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.41,"mem_mb":11.4,"disk_size":"34.6M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.45,"mem_mb":11.2,"disk_size":"34.4M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4.5,"import_time_s":0.28,"mem_mb":11.4,"disk_size":"36M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.34,"mem_mb":11.2,"disk_size":"35M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.59,"mem_mb":12.8,"disk_size":"38.3M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.72,"mem_mb":12.7,"disk_size":"38.0M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4.4,"import_time_s":0.51,"mem_mb":12.8,"disk_size":"39M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.55,"mem_mb":12.7,"disk_size":"39M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.73,"mem_mb":14.7,"disk_size":"29.8M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.83,"mem_mb":14.7,"disk_size":"29.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.7,"import_time_s":0.73,"mem_mb":14.7,"disk_size":"31M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.78,"mem_mb":14.7,"disk_size":"30M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.4,"mem_mb":11.4,"disk_size":"29.5M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.46,"mem_mb":11.3,"disk_size":"29.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.6,"import_time_s":0.4,"mem_mb":11.4,"disk_size":"30M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":11.3,"disk_size":"30M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.36,"mem_mb":11.3,"disk_size":"33.8M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.39,"mem_mb":11.2,"disk_size":"33.7M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":5.2,"import_time_s":0.36,"mem_mb":11.3,"disk_size":"35M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.34,"mem_mb":11.2,"disk_size":"35M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}