Clerk Python SDK
raw JSON → 5.0.2 verified Tue May 12 auth: no python install: verified quickstart: verified
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.
pip install clerk-backend-api Common errors
error 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.
fix
Ensure 'clerk-backend-api' is installed (pip install clerk-backend-api) and import it correctly as 'from clerk_backend_api import Clerk'.
error 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.
fix
Set 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.
error 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.
fix
Ensure 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.
error 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.
fix
Cast 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)'.
error 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.
fix
Consult 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. ↓
fix Always pip install clerk-backend-api (with dashes). Verify with: pip show clerk-backend-api
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. ↓
fix Use sdk.authenticate_request() from clerk_backend_api for request auth instead of manual jwt.decode().
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. ↓
fix Pin: clerk-backend-api==5.0.2 in requirements.txt. Review changelog before upgrading.
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. ↓
fix Clerk(bearer_auth=os.environ['CLERK_SECRET_KEY']). Secret key starts with sk_, not pk_.
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. ↓
fix Use 'with Clerk(...) as clerk:' pattern. Or call clerk.close() explicitly.
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. ↓
fix For FastAPI: construct httpx.Request from request.headers and URL. Or use community packages like fastapi-clerk-auth for framework integration.
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. ↓
fix Pin SDK version in production. Review Clerk API changelog at clerk.com/changelog before upgrading.
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. ↓
fix Ensure the `CLERK_SECRET_KEY` environment variable is set in your environment before running the application. For example, `export CLERK_SECRET_KEY="sk_live_..."` or configure it in your deployment environment.
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`. ↓
fix Ensure `CLERK_SECRET_KEY` is set in the environment before running the application. For example, `export CLERK_SECRET_KEY=sk_test_...` or pass it via Docker/CI configurations.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - 2.90s 53.7M
3.10 slim (glibc) - - 1.96s 53M
3.11 alpine (musl) - - 4.02s 58.4M
3.11 slim (glibc) - - 3.35s 58M
3.12 alpine (musl) - - 3.17s 49.6M
3.12 slim (glibc) - - 3.38s 49M
3.13 alpine (musl) - - 3.13s 49.3M
3.13 slim (glibc) - - 3.16s 49M
3.9 alpine (musl) - - 2.42s 52.7M
3.9 slim (glibc) - - 2.10s 52M
Imports
- Clerk wrong
from clerk import Clerkcorrectfrom clerk_backend_api import Clerk - AuthenticateRequestOptions wrong
from clerk_backend_api import AuthenticateRequestOptionscorrectfrom clerk_backend_api.jwks_helpers import AuthenticateRequestOptions
Quickstart verified last tested: 2026-05-12
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