# What changed in werkzeug

> 25 changes in werkzeug 3 from its official release notes, upgrade guides and advisories: 4 breaking. Each one cited. Sources checked 2026-10-18. HTML: https://unstale.sh/pypi/werkzeug/

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

## werkzeug 3

### Breaking changes

- Basic auth parsing disallows non-base64 characters. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- The URL converter returns a 404 instead of a 500 error when the value exceeds sys.get_int_max_str_digits(). (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- On Windows, safe_join no longer allows special device names with empty ADS markers on NTFS. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- `Request.host`, `get_host`, and `host_is_trusted` validate value characters; empty values are disallowed and Unix socket server addresses are ignored. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)

### Performance

- Performance is improved. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Performance is improved. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Performance is improved. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)

### Behavior and default changes

- Form data is no longer limited by max_form_memory_size, only by max_content_length. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Sets the `Accept-Ranges` header even when the range request is not satisfiable. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)

### Fixes and other changes

- PIN generation from cgroup data inside Podman is improved. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Also checks that the port is in the valid range. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Preserves empty usernames and passwords, and port 0. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Does not resize the buffer when it reads less than the remaining size. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Uses profiling.tracing on Python 3.15. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- The invalid suffix length -0 is no longer accepted. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Preserves empty usernames and passwords, and port 0. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Rules with 10 or more converters in a single part assign matched values correctly. (3.1.9) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.9)
- Returns the empty string if the header is missing or has invalid characters. (3.1.8) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.8)
- Returns the empty string if the header is missing or has invalid characters. (3.1.8) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.8)
- The `trusted_list` argument is optional. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
- Merges any number of consecutive slashes. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
- Fixes handling of a newline at a multipart boundary. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
- Preserves partially quoted items, discards empty items, and returns empty for unclosed quoted values. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
- Is parsed as a set. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
- Does not produce a trailing space when there are no parameters. (3.1.7) — [release notes](https://github.com/pallets/werkzeug/releases/tag/3.1.7)
