Implementation:Anthropics Anthropic sdk python LegacyAPIResponse
| Knowledge Sources | |
|---|---|
| Domains | SDK_Infrastructure, Response_Parsing |
| Last Updated | 2026-02-15 12:00 GMT |
Overview
⚠️ DEPRECATED: This page documents LegacyAPIResponse, the legacy response wrapper class that parses raw httpx responses into typed Python objects. This class is deprecated and scheduled for replacement by APIResponse/AsyncAPIResponse in a future major version. The stream_to_file() and astream_to_file() methods are explicitly marked @deprecated due to a streaming bug.
Description
The _legacy_response.py module provides LegacyAPIResponse, a generic wrapper around httpx.Response that implements a parse() method to decode HTTP responses into rich Python types. It inspects the cast_to type parameter to determine the decoding strategy: constructing Stream/AsyncStream for streaming responses, JSONLDecoder for JSONL content, BaseModel subclasses for JSON bodies, or returning raw text/bytes for primitive types.
The module also exports to_raw_response_wrapper() and async_to_raw_response_wrapper() decorator functions that inject the RAW_RESPONSE_HEADER to short-circuit normal processing in the base client, causing the raw LegacyAPIResponse object to be returned instead of the parsed result. Additionally, HttpxBinaryResponseContent wraps binary responses with convenient access methods like write_to_file().
Usage
This class is used internally by the base client when the RAW_RESPONSE_HEADER is present on the request. End users encounter it when using the .with_raw_response accessor on older SDK versions. New code should prefer APIResponse/AsyncAPIResponse from _response.py.
Code Reference
Source Location
- Repository: Anthropic SDK Python
- File:
src/anthropic/_legacy_response.py - Lines: 1-511
- Key classes:
LegacyAPIResponse(line 47),HttpxBinaryResponseContent(toward end of file)
Signature
class LegacyAPIResponse(Generic[R]):
_cast_to: type[R]
_client: BaseClient[Any, Any]
_parsed_by_type: dict[type[Any], Any]
_stream: bool
_stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None
_options: FinalRequestOptions
http_response: httpx.Response
retries_taken: int
def __init__(
self,
*,
raw: httpx.Response,
cast_to: type[R],
client: BaseClient[Any, Any],
stream: bool,
stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None,
options: FinalRequestOptions,
retries_taken: int = 0,
) -> None
def parse(self, *, to: type[_T] | None = None) -> R | _T
Import
from anthropic._legacy_response import LegacyAPIResponse
from anthropic._legacy_response import to_raw_response_wrapper, async_to_raw_response_wrapper
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
raw |
httpx.Response |
Yes | The raw HTTP response from httpx |
cast_to |
type[R] |
Yes | The target type to parse the response into (e.g., Message, str, bytes)
|
client |
BaseClient[Any, Any] |
Yes | Reference to the parent client for response data processing |
stream |
bool |
Yes | Whether this response should be parsed as a server-sent events stream |
stream_cls |
type[AsyncStream] | None | Yes | The stream class to use when stream=True
|
options |
FinalRequestOptions |
Yes | The request options that produced this response |
retries_taken |
int |
No (default: 0) | Number of retries that were made before this response |
Outputs
| Name | Type | Description |
|---|---|---|
parse() return |
_T | The parsed response; type depends on cast_to. Can be a BaseModel, Stream, str, bytes, dict, etc.
|
request_id |
None | The request-id response header value, useful for debugging
|
http_response |
httpx.Response |
Direct access to the underlying httpx response |
retries_taken |
int |
The number of retries made; 0 if no retries occurred |
Parse Logic
The parse() method implements a type-based dispatch to determine how to decode the response:
def parse(self, *, to: type[_T] | None = None) -> R | _T:
# Results are cached by type to avoid re-parsing
cache_key = to if to is not None else self._cast_to
cached = self._parsed_by_type.get(cache_key)
if cached is not None:
return cached
parsed = self._parse(to=to)
# Apply post_parser hook if configured
if is_given(self._options.post_parser):
parsed = self._options.post_parser(parsed)
# Attach request_id to BaseModel instances
if isinstance(parsed, BaseModel):
add_request_id(parsed, self.request_id)
self._parsed_by_type[cache_key] = parsed
return parsed
The internal _parse() handles these types:
Stream/AsyncStream-- Wraps the response as a server-sent events streamJSONLDecoder/AsyncJSONLDecoder-- Creates a line-by-line JSON decoderNoneType-- ReturnsNonestr-- Returnsresponse.textbytes-- Returnsresponse.contentBaseModelsubclass -- Parses JSON and constructs the model viaconstruct_type()httpx.Response-- Returns the raw response
Wrapper Functions
def to_raw_response_wrapper(func: Callable[P, R]) -> Callable[P, LegacyAPIResponse[R]]:
"""Wraps a sync API method to return LegacyAPIResponse instead of the parsed type."""
def async_to_raw_response_wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[LegacyAPIResponse[R]]]:
"""Wraps an async API method to return LegacyAPIResponse instead of the parsed type."""
Usage Examples
Accessing Raw Response
import anthropic
client = anthropic.Anthropic()
# The LegacyAPIResponse is returned when accessing .with_raw_response
response = client.with_raw_response.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
# Access HTTP metadata
print(response.status_code)
print(response.headers)
print(response.request_id)
# Parse the response body into the expected type
message = response.parse()
print(message.content)
Dependencies
- httpx -- Underlying HTTP response object
- anyio -- Async utilities for the async response variant
- pydantic -- Used for BaseModel type checking during parse dispatch