How to Access Raw Response Headers Using the Anthropic Python SDK
Use the .with_raw_response accessor on any resource to return a LegacyAPIResponse object containing the underlying httpx.Response and its headers.
The anthropics/anthropic-sdk-python library wraps HTTP calls in convenient Pydantic models, but production applications often need to inspect raw response headers for rate-limit tracking, request IDs, or debugging. While the SDK automatically surfaces the request ID via the _request_id property, custom headers and detailed HTTP metadata remain accessible only through the low-level response object.
Using the .with_raw_response Accessor
The SDK exposes a dedicated .with_raw_response property on every resource that returns a thin wrapper around the standard client methods. According to the source code in [src/anthropic/_client.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_client.py#L42-L48), the main Anthropic and AsyncAnthropic clients define this property to return an AnthropicWithRawResponse instance.
When you invoke a method through this accessor—such as client.messages.with_raw_response.create()—the call returns a LegacyAPIResponse object instead of the parsed Pydantic model. As implemented in [src/anthropic/_legacy_response.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_legacy_response.py), this wrapper stores the original httpx.Response and exposes:
.headers– A case-insensitive dictionary of HTTP headers.status_code– The integer HTTP status code.parse()– A method to convert the raw body back into the standard typed model
Each resource defines its own WithRawResponse class. For example, [src/anthropic/resources/messages/messages.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/resources/messages/messages.py#L84-L96) implements MessagesWithRawResponse, which forwards calls to the underlying API method while ensuring the raw HTTP response is preserved.
The official documentation mirrors this approach in the README section "Accessing raw response data (e.g. headers)".
Retrieving Headers from Synchronous Requests
To access headers from a standard blocking call, prefix your method invocation with .with_raw_response:
from anthropic import Anthropic
client = Anthropic()
# Request the Messages endpoint while preserving the raw HTTP response
raw_resp = client.messages.with_raw_response.create(
max_tokens=256,
messages=[{"role": "user", "content": "Hello, Claude"}],
model="claude-sonnet-20240229",
)
# Access any header (e.g., custom metadata or rate-limit info)
print("X-My-Header →", raw_resp.headers.get("X-My-Header"))
# Parse the response body into the standard Message model
msg = raw_resp.parse()
print("Assistant reply →", msg.content)
The raw_resp.headers attribute provides direct access to the case-insensitive header dictionary from the underlying httpx.Response. Calling raw_resp.parse() returns the standard Message model without requiring a second network request.
Accessing Headers in Async Applications
The asynchronous client mirrors this pattern exactly. Await the method call on the with_raw_response accessor, then await .parse() to deserialize the model:
import asyncio
from anthropic import AsyncAnthropic
async def main() -> None:
client = AsyncAnthropic()
raw_resp = await client.messages.with_raw_response.create(
max_tokens=256,
messages=[{"role": "user", "content": "Hi, async Claude"}],
model="claude-sonnet-20240229",
)
print("X-My-Header →", raw_resp.headers.get("X-My-Header"))
# Parse the response model asynchronously
msg = await raw_resp.parse()
print("Assistant reply →", msg.content)
await client.aclose()
asyncio.run(main())
Inspecting Headers During Streaming
When using streaming responses, you can still access headers by combining .with_streaming_response with a context manager. The streaming response object exposes the same .headers attribute before you consume the body:
from anthropic import Anthropic
client = Anthropic()
with client.messages.with_streaming_response.create(
max_tokens=512,
messages=[{"role": "user", "content": "Stream me something"}],
model="claude-sonnet-20240229",
) as stream:
# Headers are available immediately without consuming the stream
print("Rate-Limit-Remaining →", stream.headers.get("Rate-Limit-Remaining"))
# Iterate over Server-Sent Events (SSE)
for line in stream.iter_lines():
print(line)
As defined in [src/anthropic/_response.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_response.py), the streaming response wrapper ensures the HTTP connection closes properly when exiting the context manager, while still exposing header metadata upfront.
Summary
- Use
.with_raw_responseon any resource (e.g.,client.messages.with_raw_response.create()) to receive aLegacyAPIResponseinstead of a parsed model. - Access headers via the
.headersproperty, which returns a case-insensitive dictionary from the underlyinghttpx.Response. - Parse the body by calling
.parse()(orawait raw_resp.parse()in async contexts) to convert the raw response back into the standard Pydantic model. - Stream with headers using
.with_streaming_responseand a context manager; headers are available immediately viastream.headers.
Frequently Asked Questions
How do I access the request ID from a response?
The SDK automatically extracts the request_id from response headers and exposes it via the _request_id property on every returned model. However, if you need the raw header value or additional metadata, use .with_raw_response and inspect raw_resp.headers.get("request-id").
Does using .with_raw_response impact performance?
No. The accessor returns the same underlying HTTP response that the SDK already processed; it simply skips the automatic Pydantic parsing step until you explicitly call .parse(). No additional network requests are made.
Can I access response headers when using the streaming API?
Yes. When using .with_streaming_response.create(), the returned context manager exposes .headers immediately upon entering the with block, before any stream data is consumed. This allows you to check rate limits or request IDs before processing the streamed content.
What is the difference between LegacyAPIResponse and APIResponse?
LegacyAPIResponse (defined in [src/anthropic/_legacy_response.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_legacy_response.py)) is returned by .with_raw_response and wraps a complete httpx.Response. APIResponse (defined in [src/anthropic/_response.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_response.py)) is returned by .with_streaming_response and wraps a streaming response that must be consumed within a context manager.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →