# What changed in oauthlib

> 32 changes in oauthlib 3 to 4 from its official release notes, upgrade guides and advisories: 16 breaking, 1 deprecations, 2 security, 8 new APIs and options. Each one cited. Sources checked 2026-10-26. HTML: https://unstale.sh/pypi/oauthlib/

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

## oauthlib 4

### Breaking changes

- The grant_type parameter is validated before client authentication. (4.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v4.0.0)
- JSONP support was removed from the token revocation endpoint. (4.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v4.0.0), [security advisory](https://github.com/advisories/GHSA-HJ66-6F7G-4R5V)

### Security

- Client authentication when getting a token was fixed for DeviceCodeGrant. (4.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v4.0.0)
- PKCE code comparison was improved. (4.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v4.0.0), [security advisory](https://github.com/advisories/GHSA-XPV3-W29H-X7CV)

### New APIs and options

- Request._params now includes resource. (4.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v4.0.0)

## oauthlib 3

### Breaking changes

- The status code for access_denied changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The behavior of confirm_redirect_uri changed. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The status code for consent_required changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- expires no longer overrides expires_in. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- expires_in in the Implicit flow is now an integer. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The behavior of get_default_redirect_uri changed. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- invalid_client is now a FatalError. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The status code for invalid_grant changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The status code for invalid_scope changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The status code for login_required changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- parse_request_uri_response is now required. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Request attributes are no longer overridden by HTTP Headers. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- The status code for unauthorized_client changed from 401 to 400. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- A 401 response must include the WWW-Authenticate HTTP Header. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)

### Deprecations

- Passing client_id to WebApplicationClient.prepare_request_body emits a DeprecationWarning; use the already configured self.client_id instead. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)

### New APIs and options

- Adds request to confirm_redirect_uri. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds HMAC-SHA256 support for the OAuth1.0 Client. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- WebApplicationClient.prepare_request_body adds the include_client_id keyword argument to control whether client_id is sent; it defaults to included. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds OpenID Connect Core support to the OAuth2.0 Provider. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds RFC7636 PKCE support to the OAuth2.0 Provider. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds RFC7662 Introspect support to the OAuth2.0 Provider. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds RFC8414 OAuth2.0 Authorization Server Metadata support to the OAuth2.0 Provider. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)

### Behavior and default changes

- pytest is set as the default unittest framework. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)

### Fixes and other changes

- Empty scopes no longer raise exceptions for implicit and authorization_code. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- prepare_token_request supports sending an empty string for client_id. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- Adds support for Python 3.7. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
- $ and ' are allowed to be unencoded in query strings. (3.0.0) — [release notes](https://github.com/oauthlib/oauthlib/releases/tag/v3.0.0)
