Anthropic Python SDK 1.0: 2026 Migration Guide

Python SDK 1.0 shipped on August 20, 2026, moving the anthropic package out of its 0.x prefix and into a stable 1.x line. This guide covers every breaking change that can touch real code, reproduces the exact errors you will hit, and walks one project through the complete upgrade from 0.125 to 1.0.

Python SDK 1.0 upgrade installing anthropic 1.0.0 with httpx2 in a terminal window

Python SDK: What You’ll Learn

You will learn what changed in the Python SDK between 0.125.0 and 1.0.0, which of those changes actually break running code, and how to migrate a real project with a type checker as the safety net. By the end you will know whether your Python SDK usage needs edits today or can ride along until the next routine dependency bump.

What changed in version 1.0

Anthropic published anthropic 1.0.0 on August 20, 2026, one day after 0.125.0, the final 0.x release of the Python SDK. The version jump is not cosmetic. The v1.0.0 release notes describe one headline breaking change, an upgrade of the HTTP layer, plus a set of smaller removals the team had been warning about across the 0.x line.

The headline change is that the Python SDK no longer runs on httpx. It now runs on httpx2, a fork of httpx that the Pydantic team now maintains and that keeps the public API intact, because upstream httpx development has wound down. The minimum Python version also rises from 3.9 to 3.10. Everything else on the breaking list is a removal of something already deprecated: legacy parameters, legacy type aliases, and the long retired Text Completions API.

What did not change matters just as much. The Messages API surface your code calls every day is untouched, prompt caching and streaming behave the same, and both Pydantic v1 and Pydantic v2 remain supported. If your Python SDK calls look like client.messages.create(model=..., max_tokens=..., messages=[...]) and you pass plain numbers for options such as timeout=30.0 or max_retries=3, the upgrade is close to invisible.

The changes group into five buckets, and the rest of this guide takes them in order:

  • The HTTP layer moved from httpx to httpx2, which affects code that passes HTTP objects to the SDK or reads them back.
  • Raw response wrappers were replaced, so .with_raw_response code needs method calls instead of properties.
  • Deprecated request parameters were removed from method signatures, including temperature, top_p, and top_k.
  • The Text Completions API, its types, and the HUMAN_PROMPT and AI_PROMPT constants are gone.
  • Bedrock clients now require an explicit AWS region instead of silently falling back to us-east-1.

Who needs to act right away

Most projects sit in one of three tiers, and the tier tells you how urgent this is. Tier one is code that only passes plain values to the SDK: strings, numbers, message dicts. For those projects the Python SDK 1.0 release is a normal upgrade, and if the tests pass after pip install --upgrade, the migration is done.

Tier two is code that constructs httpx objects and hands them to the Python SDK: custom clients, transports, proxies, or timeouts built from httpx.Timeout. That code keeps working only after the imports move to httpx2, and the SDK enforces the client argument with a hard TypeError at construction time, so it cannot fail quietly.

Tier three is code that observes or stubs HTTP traffic: OpenTelemetry instrumentation, Sentry integrations, and mocking libraries such as respx, pytest-httpx, or vcrpy. These hook the httpx package itself, and after the upgrade they keep running while silently seeing none of the Python SDK’s requests, which is the most dangerous failure mode in the whole release.

Whichever tier you are in, run pyright or mypy immediately after upgrading the Python SDK. The migration guide is explicit that a type checker flags almost every breaking change in the Python SDK 1.0, which makes the compiler output a ready made checklist for this migration.

Upgrading the package

The install command pins the major version explicitly, which is worth keeping in your requirements file so CI never resolves a 0.x version by accident:

pip install --upgrade "anthropic>=1,<2"

In a clean virtualenv on Python 3.14, the upgrade from 0.125.0 pulled three new packages and replaced the SDK in place:

Downloading anthropic-1.0.0-py3-none-any.whl (1.2 MB)
Downloading httpx2-2.12.0-py3-none-any.whl (95 kB)
Downloading httpcore2-2.12.0-py3-none-any.whl (83 kB)
Installing collected packages: truststore, httpcore2, httpx2, anthropic
  Attempting uninstall: anthropic
    Found existing installation: anthropic 0.125.0
    Uninstalling anthropic-0.125.0:
      Successfully uninstalled anthropic-0.125.0
Successfully installed anthropic-1.0.0 httpcore2-2.12.0 httpx2-2.12.0 truststore-0.10.4

Note what arrives alongside the SDK: httpx2, httpcore2, and truststore. The old httpx stays installed because other tools may still need it, so from this point two HTTP stacks can coexist in one process, and that detail drives several fixes later in this guide.

If you use Claude Code, there is a faster route through the whole migration. Version 2.1.239 added a /claude-api upgrade command that edits Python projects from anthropic 0.x to 1.x automatically; point /claude-api upgrade python at the repository; the official MIGRATION.md guide documents the route. The command is young, so treat its output like any other agent edit: read every line of the diff before you commit.

Smaller removals worth grepping for

A long tail of deprecated names and behaviors went away. None of these will surprise you if you followed deprecation warnings, but they bite codebases that silenced warnings years ago, so put them all in one grep pass, ideally before you touch the requirements file:

  • BetaBase64PDFBlockParam is now BetaRequestDocumentBlockParam, and agent_toolset.READ_MAX_BYTES is now DEFAULT_MAX_FILE_BYTES.
  • messages.parse(stream=True) is removed; the argument never worked. Switch to messages.stream(), which handles the same structured-output types.
  • tool_runner(compaction_control=...) is removed in favor of server-side compaction via betas=["compact-2026-01-12"] and context_management, with a trigger threshold of at least 50,000 tokens.
  • Raw bytes as body= on the low-level request methods are gone; use content=, an argument that also takes iterators, which suits a streaming upload.
  • The compatibility shim that kept isinstance(stream, anthropic.Stream) passing for message streams is gone; check for MessageStream instead.
  • Headers now merge case-insensitively, so a default_headers entry replaces the SDK’s own header whatever the casing, and omit drops a header on the same matching rule.
  • bytes header values now raise; decode them to str before passing.
grep -rn -E "HUMAN_PROMPT|AI_PROMPT|completions\.create|compaction_control|READ_MAX_BYTES|BetaBase64PDFBlockParam|parse\(.{0,40}stream=True" app/

That grep finds nearly every long tail item in a typical codebase. With those out of the way, the remaining Python SDK 1.0 diff shrinks to the parameter removals, the Bedrock region change, the HTTP layer, and the raw response changes.

Removed parameters and removed APIs

The generated methods no longer accept the deprecated sampling parameters. Passing temperature, top_p, or top_k to messages.create(), messages.stream(), messages.parse(), or their beta counterparts raises TypeError before any request leaves the process:

client.messages.create(..., temperature=0.2)
# TypeError: Messages.create() got an unexpected keyword argument 'temperature'

None of the current models read these sampling settings, which is why deleting them outright is the correct fix. If you are pinned to an older model that still honors them, the parameters are gone from the signatures but not from the API: pass them through extra_body, whose keys travel into the request body untouched.

client.messages.create(
    ...,
    model="claude-sonnet-4-6",
    extra_body={"temperature": 0.2},
)

Structured output moved the same way. A schema dict passed as output_format={...} now raises; move it to output_config={"format": {...}}. The output_format= argument of the parse(), stream(), count_tokens(), and tool_runner() helpers still takes a type, and that is now the only thing it takes.

Finally, the legacy Text Completions API is removed outright: client.completions.create(), its Completion types, and the anthropic.HUMAN_PROMPT and anthropic.AI_PROMPT constants no longer exist. All current models are reachable through the Messages API alone, and Anthropic has pointed developers there since 2023. If a /v1/complete call still survives in your codebase, porting it comes before anything else in this release.

Bedrock clients now require a region

In the 0.x line, a missing region produced a warning and an implicit default of us-east-1. The 1.0 Python SDK deletes the implicit default; when region discovery comes up empty, the constructor raises instead:

ValueError: No AWS region was provided. Set the `aws_region` argument,
the `AWS_REGION` / `AWS_DEFAULT_REGION` environment variable, or configure
a region for your AWS profile.

The region is resolved in order from the aws_region= argument, then the AWS_REGION or AWS_DEFAULT_REGION environment variables, then the boto3 session configuration for the given aws_profile, which the Python SDK previously ignored during region lookup. One related change: unknown Bedrock streaming events are now skipped instead of yielded, with amazon-bedrock-invocationMetrics the only known case.

The httpx2 switch and custom HTTP clients

Code written against httpx usually runs on httpx2 untouched: the class names line up, the methods line up, and the fork keeps taking security fixes. Where the switch bites is at the boundary, either constructing httpx objects and giving them to the Python SDK, or reading back the HTTP objects the client returns. If you build nothing from httpx yourself, this section does not apply to you.

The Python SDK validates the client argument hard. Passing an httpx.Client from the old package raises immediately, with one of the clearest errors you will ever see from a constructor:

TypeError: Invalid `http_client` argument; Expected an instance of
`httpx2.Client` but got <class 'httpx.Client'>

The simplest fix is to alias the import, after which every existing reference keeps working because httpx2 is API-compatible:

import httpx2 as httpx  # one line, everything below keeps working

from anthropic import Anthropic, DefaultHttpxClient

client = Anthropic(
    timeout=httpx.Timeout(60.0, connect=5.0),
    http_client=DefaultHttpxClient(proxy="http://my.proxy.example"),
)

You can also skip the import question entirely by preferring the Python SDK’s own re-exports. anthropic.Timeout, anthropic.DefaultHttpxClient, anthropic.DefaultAsyncHttpxClient, and anthropic.DefaultAioHttpClient already point at httpx2 in 1.0 and keep working unchanged. Code that only used those names needs no edit at all.

One nuance from testing the upgrade: the constructor check is strict about clients but lenient about timeouts. An old httpx.Timeout instance still passes as a duck-typed value, so timeout-only code may not fail loudly. Alias the import anyway; relying on duck typing across two HTTP stacks is a debugging session waiting to happen.

Objects that flow back out of the Python SDK are now httpx2 types. That covers APIStatusError.response, APIConnectionError.request, the http_response, headers, and url attributes of a raw response, plus the response= payload handed to any custom event hook you registered. Attributes are identical, so only isinstance checks and type annotations naming httpx.Response or httpx.Headers need the rename:

def log_failure(err: anthropic.APIStatusError) -> None:
    response: httpx2.Response = err.response
    print(response.status_code, response.headers.get("request-id"))

When two HTTP stacks in one process get awkward, there is an escape hatch. Call httpx2.alias_httpx() once at startup and import httpx resolves to httpx2 for the entire process. The call has to happen before the first httpx import anywhere in the process, and a late call raises RuntimeError. Keep it in your application’s entry point: a published library that silently remaps imports for everyone downstream is doing something hostile.

Two smaller notes complete the HTTP picture. The anthropic.Transport and anthropic.ProxiesTypes re-exports no longer exist; reach for httpx2.BaseTransport, httpx2.AsyncBaseTransport, and httpx2.Proxy instead. And if you install the aiohttp extra, be aware that anthropic[aiohttp] no longer pulls in the separate httpx_aiohttp package because that transport now ships inside the SDK.

Raw responses changed shape

Python SDK code that calls .with_raw_response has the most mechanical migration ahead of it. The old LegacyAPIResponse wrapper is gone; both sync and async clients now return the same APIResponse and AsyncAPIResponse classes that .with_streaming_response always used.

On the async client, reading the body became awaitable: the four body readers parse(), read(), text(), and json() all became coroutines. On both clients, .text and .content stopped being properties and became .text() and .read() method calls. The new wrappers also expose json() and the iter_bytes(), iter_text(), and iter_lines() iterators directly, so you stop reaching into response.http_response for those.

The metadata attributes you probably care about most are unchanged: .headers, .status_code, .url, .request_id, .retries_taken, .http_response, and .elapsed all behave exactly as before. Reading a request id stays plain attribute access:

response = await client.messages.with_raw_response.create(...)
print(response.headers["request-id"])  # metadata is still sync
message = await response.parse()       # body access is now async

If your code reads only headers and status codes, nothing changes. If it reads bodies, count the await keywords and the parentheses carefully; the property-to-method change is exactly the kind of edit a type checker catches and a runtime smoke test can miss.

Instrumentation and test doubles need aliasing

Libraries that hook HTTP traffic by patching httpx keep working after the upgrade while seeing exactly zero Python SDK requests. The official guide names the common ones: OpenTelemetry’s HTTPXClientInstrumentor, Sentry’s httpx integration, respx, pytest-httpx, and vcrpy. Silent no-op tracing and silently passing mocks are unpleasant to discover in production, so fix this at upgrade time, not later.

The holistic fix is the same alias call. In an application, put it at the very top of your entry point. Under pytest, the least intrusive pattern is an early plugin, registered so it executes ahead of respx, ahead of pytest-httpx, and ahead of every test module import:

# tests/_alias_httpx.py
import httpx2

httpx2.alias_httpx()  # import httpx now resolves to httpx2
# pyproject.toml
[tool.pytest.ini_options]
addopts = "-p tests._alias_httpx"
pythonpath = ["."]

With that plugin in place, your mocks and traces observe the Python SDK’s traffic again without touching a single test. Without it, a mock-heavy suite can pass end to end while exercising none of your new HTTP code, which defeats the point of having the suite.

A Worked Example

To make this concrete, here is the full migration run against a small real project. The project starts on Python 3.14 with anthropic 0.125.0 and httpx 0.28.1, a custom client with a proxy, a retry wrapper that logs the response object, and a call that still sets temperature. It is the same Python SDK usage pattern you would find in any production service.

First, the state before the upgrade, confirmed from inside the virtualenv:

$ python -c "import anthropic, httpx; print(anthropic.__version__, httpx.__version__)"
0.125.0 0.28.1

The upgrade itself is uneventful, which is the point: every failure mode in this migration surfaces when your code runs, not when the package installs. After pip install --upgrade "anthropic>=1,<2", the Python SDK reports 1.0.0 and the process now has both httpx and httpx2 available.

Second, the first launch. The custom client code passes httpx.Client() to the SDK and dies at construction with the TypeError shown earlier, before a single API call is attempted. The one-line fix is to alias the import in the module that builds the client: import httpx2 as httpx. Every later reference, the Timeout, the proxy, the transport, keeps working because the fork is API-compatible.

Third, the next launch gets further and dies on the request line instead. The old temperature=0.2 argument is now an unexpected keyword, and the resulting TypeError names the method and the argument with no ambiguity. Deleting the argument takes one line because current models ignore sampling parameters anyway; a project pinned to an older model would move it into extra_body instead.

Fourth, the checks you cannot see from the command line. The retry wrapper’s type annotation still says httpx.Response, which pyright flags as an error even though the code runs. The fix is mechanical: annotate against httpx2.Response or, better, drop the annotation and let the re-exported SDK types carry it. The same pyright pass catches the Stream isinstance check hiding in a utility module.

Fifth, the test suite. It mocks HTTP with respx and passed on the first run after the upgrade, which is the trap: respx patches httpx, the Python SDK no longer uses httpx, so the tests were passing against nothing. Adding the tests/_alias_httpx.py early plugin and the pytest addopts line from the instrumentation section restores real mocking, after which two tests that should have been exercising request retries started failing honestly and got fixed.

Total effort for this Python SDK migration: one aliased import, one deleted argument, two annotation edits, one pytest plugin, and the two test fixes the plugin exposed. The project ran on 1.0.0 with no further changes, and the entire diff was reviewed in a single sitting, which is the realistic size of this migration for most codebases.

Python SDK: Common Mistakes to Avoid

Even careful teams hit the same four traps during a Python SDK migration. Each one comes from a reasonable instinct that happens to be wrong for this release.

  • Rewriting every httpx reference by hand instead of aliasing the import. The fork is API-compatible; one import line covers the whole module, and hand edits invite typos.
  • Trusting a green test suite after the upgrade. Mocking tools that patch httpx keep passing while seeing none of the SDK’s traffic, so verify mocks intercept real calls.
  • Assuming temperature errors come from the API. The TypeError is raised by the SDK before a request is sent, so no API log will ever show it.
  • Calling httpx2.alias_httpx() from inside a shared library. The alias is process-wide and must precede every httpx import; only the application entry point should own it.
Python SDK 1.0 TypeError raised when an old httpx Client is passed to the upgraded client

Python SDK: Best Practices

  • Pin "anthropic>=1,<2" in your requirements so the major version boundary is explicit and CI cannot drift back to 0.x.
  • Run pyright or mypy as your migration checklist; the 1.0 removals are exactly what strict type checking surfaces.
  • Prefer the SDK’s re-exports, anthropic.Timeout and anthropic.DefaultHttpxClient, over importing httpx2 directly where you can.
  • Put httpx2.alias_httpx() at the top of application entry points and pytest early plugins, never inside library code.
  • Add one test that constructs the Python SDK client with your real options, so constructor level TypeError regressions surface in CI, not at 2 a.m.

Python SDK: Frequently Asked Questions

Do simple scripts need any changes for 1.0?

Usually no. If you pass plain values only, numbers for timeouts, strings for keys, dicts for messages, the Python SDK treats 1.0 as a routine upgrade. Run your tests; if nothing uses httpx objects or mocking libraries, you are done.

Does the Python SDK 1.0 upgrade force a Python upgrade?

Yes, if you are on 3.9. The minimum supported version rose from 3.9 to 3.10, and pip enforces the limit at install time from the package metadata. Both Pydantic generations, v1 and v2, are still supported, so nothing changes there.

What happens to temperature, top_p, and top_k?

The Python SDK removes them from the method signatures and raises TypeError if passed. Current models ignore them, so delete them; for an older model that still honors sampling, pass the setting through extra_body.

Why did my respx or OpenTelemetry setup stop seeing requests?

Those tools patch the httpx package, and the Python SDK now sends over httpx2. Call httpx2.alias_httpx() before anything imports httpx, and the tools observe SDK traffic again.

Is there an automated migration tool?

Yes. Claude Code 2.1.239 added /claude-api upgrade python, which applies the 0.x to 1.x edits to your project automatically. Review the diff like any agent edit; the Claude Code changelog documents the command.

Python SDK 1.0 comes down to three things: the HTTP layer moved to httpx2 and anything that hands over or receives HTTP objects needs the alias, deprecated parameters and legacy APIs were removed with loud errors, and observability tooling needs alias_httpx() to keep seeing traffic. Handle those three and the rest of your code carries over untouched.