Clerk Python SDK
Official Clerk backend SDK for Python. Current version is 5.0.2 (Feb 2026). PyPI package is 'clerk-backend-api', imports as 'clerk_backend_api'. SDK was only released in beta Oct 2024 — most tutorials predate it and use manual JWT verification with PyJWT. Three confusable PyPI packages: 'clerk-backend-api' (official), 'clerk-sdk' (unrelated third-party), 'clerk-sdk-python' (single-release stub). Package was previously also distributed as 'clerk' during alpha.
Common errors
-
ModuleNotFoundError: No module named 'clerk' OR ModuleNotFoundError: No module named 'clerk_backend_api'
cause The official 'clerk-backend-api' package is imported as 'clerk_backend_api', but developers might try to import 'clerk' due to older tutorials or package name confusion (e.g., from the 'clerk-sdk-python' package or alpha versions). Alternatively, 'clerk-backend-api' might not be installed at all.fixEnsure 'clerk-backend-api' is installed (pip install clerk-backend-api) and import it correctly as 'from clerk_backend_api import Clerk'. -
Error: Missing Clerk Secret Key OR Error: Clerk: Invalid API key
cause The CLERK_SECRET_KEY environment variable is not set, is incorrect, or does not match the Clerk application it's being used with.fixSet CLERK_SECRET_KEY in your environment variables (e.g., in a .env file) to the Secret Key found in your Clerk Dashboard under API Keys. -
401 Could not authenticate request. OR Invalid Authorization header format.
cause The Authorization header in the request is missing, malformed, or contains an invalid or expired JWT/API key.fixEnsure your backend is receiving a valid Bearer token from the frontend and is correctly passing your Clerk Secret Key or a valid session token in the 'Authorization: Bearer <token>' header when making requests to the Clerk API or when authenticating incoming requests. -
request_body_invalid (often seen when using expires_in_seconds with create_session_token)
cause When calling 'create_session_token', the 'expires_in_seconds' argument is being passed as a float, but the Clerk API expects an integer value.fixCast the 'expires_in_seconds' argument to an integer before passing it to the 'create_session_token' method. Example: 'expires_in_seconds=int(some_float_value)'. -
AttributeError: 'Clerk' object has no attribute 'users' (or similar for other resources like 'email_addresses', 'sessions')
cause Attempting to access a sub-resource or method on the 'Clerk' client that either does not exist, is named differently, or is not available in the imported SDK version.fixConsult the official 'clerk-backend-api' documentation or the SDK source code to verify the correct attribute and method names for the desired API operation (e.g., 'clerk.users' vs 'clerk.users', 'list()' vs 'get_all()'). For example, to list users, use 'clerk.users.list()' or to get an email address, use 'clerk.email_addresses.get(email_address_id=...)'.
Warnings
- breaking 'pip install clerk-sdk' installs an unrelated third-party package (F-One's document management SDK, not Clerk auth). It has the same top-level Clerk class name but completely different API. Silent wrong-package installation.
- breaking The official SDK was only released Oct 2024. All tutorials and LLM training data before that date use manual JWT verification with PyJWT + JWKS endpoint fetch — not the SDK. That pattern still works but is not the official approach.
- breaking SDK has had breaking changes between minor versions during beta/v4-v5 cycle. The docs warn: 'pin usage to a specific package version' to avoid silent breakage.
- breaking bearer_auth must be your Secret Key (sk_live_... or sk_test_...), NOT the Publishable Key (pk_live_... or pk_test_...). Passing a Publishable Key returns 401 with no clear error message.
- gotcha Clerk() must be used as a context manager (with Clerk(...) as clerk:) or explicitly closed to release HTTPX connection pool. Omitting causes ResourceWarning in long-lived processes.
- gotcha authenticate_request() requires an httpx.Request object, not a raw dict or string token. Framework-specific adapters are needed to convert Flask/Django/FastAPI request objects.
- gotcha Clerk API versioning: each SDK version pins to a specific API version. Upgrading the SDK may silently change API behavior (field renames, new required fields) not just the SDK interface.
- breaking The Clerk constructor expects the `CLERK_SECRET_KEY` environment variable to be set when accessing it via `os.environ['CLERK_SECRET_KEY']`. If this variable is not defined, a `KeyError` will occur, preventing the application from initializing.
- breaking The `CLERK_SECRET_KEY` environment variable must be set for the SDK to initialize. Accessing `os.environ['CLERK_SECRET_KEY']` when it's not set will raise a `KeyError`.
Install
-
pip install clerk-backend-api
Imports
- Clerk
from clerk import Clerk
from clerk_backend_api import Clerk
- AuthenticateRequestOptions
from clerk_backend_api import AuthenticateRequestOptions
from clerk_backend_api.jwks_helpers import AuthenticateRequestOptions
Quickstart
import os
from clerk_backend_api import Clerk
# Management API — use CLERK_SECRET_KEY (sk_live_... or sk_test_...)
with Clerk(bearer_auth=os.environ['CLERK_SECRET_KEY']) as clerk:
# List users
users = clerk.users.list(limit=10)
for user in users:
print(user.email_addresses)
# Get single user
user = clerk.users.get(user_id='user_abc123')
print(user.id)
# Request authentication (verify JWT from frontend)
import httpx
from clerk_backend_api.jwks_helpers import AuthenticateRequestOptions
def is_signed_in(request: httpx.Request) -> bool:
sdk = Clerk(bearer_auth=os.environ['CLERK_SECRET_KEY'])
state = sdk.authenticate_request(
request,
AuthenticateRequestOptions(
authorized_parties=['https://your-app.com']
)
)
return state.is_signed_in