Supabase Auth (Python)
raw JSON → 2.28.2 verified Tue May 12 auth: no python install: verified quickstart: stale
Official Supabase Python client. Current version is 2.28.2 (Mar 2026). Auth is accessed via supabase.auth — not a separate install. The underlying auth library was renamed twice: gotrue-py → auth-py → supabase-auth. The standalone package is 'supabase-auth' (imports as 'supabase_auth'). Most auth is used through the main 'supabase' package via create_client(). Massive tutorial corpus uses the old sign_in() method removed in favor of sign_in_with_password().
pip install supabase Common errors
error AttributeError: 'AuthApi' object has no attribute 'sign_in' ↓
cause The `sign_in()` method for user authentication was deprecated and removed in favor of `sign_in_with_password()`.
fix
client.auth.sign_in_with_password(email="user@example.com", password="your_password")
error TypeError: create_client() missing 2 required positional arguments: 'supabase_url' and 'supabase_key' ↓
cause The `create_client` function requires both the Supabase project URL and the Anon (or Service Role) Key to be explicitly provided.
fix
import os
from supabase import create_client
supabase_url = os.environ.get("SUPABASE_URL")
supabase_key = os.environ.get("SUPABASE_KEY")
supabase = create_client(supabase_url, supabase_key)
error PostgrestAPIError ↓
cause A database operation (e.g., insert, select, update) failed due to a backend issue such as an invalid table name, a constraint violation, or insufficient permissions.
fix
Examine the specific error message that follows
PostgrestAPIError in the traceback to diagnose the issue; common solutions include verifying table/column names, checking data types, ensuring unique constraints, or reviewing Row Level Security (RLS) policies in your Supabase project. error ModuleNotFoundError: No module named 'gotrue' ↓
cause This error occurs when old tutorials or code attempt to import the deprecated `gotrue-py` library, which has been renamed and is now primarily accessed via the main `supabase` client's `auth` attribute.
fix
Remove
import gotrue or from gotrue.sync import AuthClient. Instead, use from supabase import create_client and access authentication via supabase_client.auth. If a standalone auth client is required, install supabase-auth and import supabase_auth. Warnings
breaking supabase.auth.sign_in() is removed. All pre-2.0 tutorials use sign_in(). The correct method is sign_in_with_password(). Calling sign_in() raises AttributeError. ↓
fix Replace supabase.auth.sign_in({'email': ..., 'password': ...}) with supabase.auth.sign_in_with_password({'email': ..., 'password': ...})
breaking The standalone auth package was named 'gotrue' (pip install gotrue), then renamed to 'supabase-auth'. 'from gotrue import' raises ModuleNotFoundError if only supabase-auth is installed. ↓
fix Replace 'from gotrue import' with 'from supabase_auth import'. Or just use the main supabase package which bundles auth.
breaking Admin auth methods (list_users, create_user, delete_user) require the service_role key, NOT the anon key. Using the anon key returns 403. The distinction is not obvious — both keys look identical in format. ↓
fix For admin ops: create_client(url, os.environ['SUPABASE_SERVICE_ROLE_KEY']). Never expose service_role key to the client/browser.
breaking sign_up() returns (user, session) where session is None if email confirmation is enabled (the default). Code that immediately uses res.session.access_token will raise AttributeError: 'NoneType' object has no attribute 'access_token'. ↓
fix Check: if res.session is not None before accessing access_token. Or disable email confirmation in Supabase dashboard for dev environments.
breaking Realtime subscriptions only work with the async client (acreate_client). The sync client silently ignores realtime calls or raises errors. ↓
fix Use acreate_client() for any code that needs realtime. sync create_client() is for REST/auth only.
gotcha SUPABASE_KEY should be the anon key for user-facing operations. The service_role key bypasses Row Level Security entirely — accidental use in client-side code exposes all data. ↓
fix Use anon key (SUPABASE_ANON_KEY) for client operations. Use service_role key only in server-side admin contexts.
gotcha Default row limit is 1000 rows. Queries that return more than 1000 rows are silently truncated with no error. Agents building data pipelines hit this constantly. ↓
fix Use .range(start, end) for pagination or increase the limit in Supabase project API settings.
gotcha supabase.auth.admin is only accessible when the client was initialized with the service_role key. Calling admin methods with the anon key returns 403 with 'not authorized' — not a clear 'wrong key' error. ↓
fix Maintain two client instances: one with anon key for user operations, one with service_role key for admin operations.
breaking The Supabase client requires configuration values such as `SUPABASE_URL` and `SUPABASE_ANON_KEY` (or `SUPABASE_SERVICE_ROLE_KEY` for admin operations). If these are accessed via `os.environ` and not set, a `KeyError` will occur during client initialization. ↓
fix Ensure `SUPABASE_URL` and `SUPABASE_ANON_KEY` (and `SUPABASE_SERVICE_ROLE_KEY` if performing admin operations) are set as environment variables. Alternatively, pass the URL and key values directly to `create_client()`.
breaking The Supabase client typically requires SUPABASE_URL and SUPABASE_KEY (or SUPABASE_ANON_KEY) environment variables for initialization. Missing these will result in KeyError if accessed via os.environ. ↓
fix Ensure SUPABASE_URL and SUPABASE_KEY (or SUPABASE_ANON_KEY) environment variables are set before initializing the Supabase client.
Install
pip install supabase-auth Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) supabase - - 2.91s 106.4M
3.10 alpine (musl) supabase-auth - - - -
3.10 slim (glibc) supabase - - 2.10s 113M
3.10 slim (glibc) supabase-auth - - - -
3.11 alpine (musl) supabase - - 3.67s 117.3M
3.11 alpine (musl) supabase-auth - - - -
3.11 slim (glibc) supabase - - 3.13s 124M
3.11 slim (glibc) supabase-auth - - - -
3.12 alpine (musl) supabase - - 3.41s 107.4M
3.12 alpine (musl) supabase-auth - - - -
3.12 slim (glibc) supabase - - 3.38s 114M
3.12 slim (glibc) supabase-auth - - - -
3.13 alpine (musl) supabase - - 3.25s 107.1M
3.13 alpine (musl) supabase-auth - - - -
3.13 slim (glibc) supabase - - 3.35s 114M
3.13 slim (glibc) supabase-auth - - - -
3.9 alpine (musl) supabase - - 2.53s 92.4M
3.9 alpine (musl) supabase-auth - - - -
3.9 slim (glibc) supabase - - 2.24s 91M
3.9 slim (glibc) supabase-auth - - - -
Imports
- create_client wrong
from gotrue import SyncGoTrueClientcorrectfrom supabase import create_client, Client - SyncGoTrueClient wrong
from gotrue import SyncGoTrueClientcorrectfrom supabase_auth import SyncGoTrueClient
Quickstart stale last tested: 2026-05-12
import os
from supabase import create_client, Client
url: str = os.environ['SUPABASE_URL']
key: str = os.environ['SUPABASE_KEY'] # anon key for client-side, service_role for admin
supabase: Client = create_client(url, key)
# Sign up
res = supabase.auth.sign_up({
'email': 'user@example.com',
'password': 'securepassword'
})
# Sign in — NOT sign_in(), use sign_in_with_password()
res = supabase.auth.sign_in_with_password({
'email': 'user@example.com',
'password': 'securepassword'
})
print(res.user)
print(res.session.access_token)
# Admin operations — requires service_role key
res = supabase.auth.admin.list_users()
for user in res:
print(user.email)