# What changed in starlette

> 44 changes in starlette 1 from its official release notes, upgrade guides and advisories: 8 breaking, 8 new APIs and options. Each one cited. Sources checked 2026-10-19. HTML: https://unstale.sh/pypi/starlette/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## starlette 1

### Breaking changes

- Percent-encode `?`, `#`, `\` and a leading `//` in the request path when building `request.url`. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- TestClient response bodies are streamed, so client.stream returns before the application finishes; closing an unfinished streamed response cancels the application. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- By default, excludes native gRPC media types from compression. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Requires Python 3.11 or later; Python 3.10 is no longer supported. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Requires anyio>=4.0.0,<5, dropping support for AnyIO 3. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Background tasks now run only after the response is sent. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Invalid multipart parser input now returns 400. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Disconnected WebSocket operations now raise WebSocketDisconnected, a RuntimeError subclass. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)

### New APIs and options

- Adds a method to send HTTP 103 Early Hints through the ASGI http.response.early_hint extension. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Adds experimental HTTP server tracing with URL exclusions and custom tracer providers; its API and emitted telemetry may change in minor releases without a deprecation period. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Supports the QUERY HTTP method in HTTPEndpoint, CORS, and OpenAPI 3.2 schema generation. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Adds the partitioned option on Python 3.14 and later. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- TestClient captures HTTP response trailers and exposes them through the response extensions mapping. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Exposes the matched route through the request scope. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Supports partitioned cookies in session middleware. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Implements identity on SimpleUser and UnauthenticatedUser. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)

### Performance

- ServerErrorMiddleware offloads debug traceback rendering to a worker thread. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)

### Behavior and default changes

- Host names are matched case-insensitively. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Sends http.response.start immediately for responses with an existing Content-Encoding, status 206, or an excluded content type, rather than waiting for the first body chunk. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Allows non-standard status codes without an explicit detail. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- TrustedHostMiddleware and TestClient support IPv6 hosts. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)

### Fixes and other changes

- Use the byte length for `Content-Length` when the response body is a typed or multidimensional `memoryview`. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Host routing matches host names case-insensitively. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Include `HEAD` in the `Allow` header of 405 responses when `GET` is defined. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Preserve every existing `Vary` header; this method is used by `GZipMiddleware` and `SessionMiddleware`. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Percent-encode `\` and a leading `//` in `url_path_for`. (1.9.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.9.0)
- Stops transfers when the client disconnects. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Preserves response trailers when the middleware handles a response. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Stops a multipart range response when the file ends before a range is complete, instead of looping forever. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Ignores Range when If-Range contains a weak ETag. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Closes generators deterministically, avoiding "Exception ignored" errors with stacked BaseHTTPMiddleware. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Adds Vary: Cookie when removing an existing key. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Emits Max-Age=0 on the session cookie when max_age=0. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Includes Allow: GET, HEAD in 405 responses. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Brackets IPv6 hostnames in replacement URLs. (1.8.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.8.0)
- Normal CORS responses include Vary: Origin, and preflight responses vary by all request headers that affect them. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Configuration annotations accept Collection[str], including sets and frozensets. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Range headers are ignored when the response status is not 200, preserving its status and full body. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Malformed Host headers and IPv6 authorities are handled consistently across URL construction, host routing, and redirect middleware. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Adds support for Python 3.15. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Session mutations made with popitem() and |= are now persisted. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Handles a standalone If-None-Match: * header. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Rejects WebSocket requests without raising an assertion error. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
- Handles empty and absent payloads. (1.7.0) — [release notes](https://github.com/Kludex/starlette/releases/tag/1.7.0)
