Supabase Storage client for Python
storage3 is the Python client library for interacting with Supabase Storage. It allows developers to manage files and folders within Supabase buckets. As of version 2.28.3, it provides both synchronous and asynchronous APIs for seamless integration. The library is actively maintained by Supabase, with frequent releases to add features and address issues.
Warnings
- breaking A minor breaking change related to `supabase_auth` affected `storage3` version `2.24.0`, which was subsequently yanked from PyPI. If you encounter authentication issues, especially around this version range, consider using a different version of `storage3` or consult the `supabase-py` changelog for compatible `gotrue` (Supabase Auth) client versions.
- gotcha When uploading files, it is crucial to explicitly set the `content-type` within the `file_options` argument (e.g., `{'content-type': 'image/png'}`). If omitted, files will default to `text/plain` MIME type, which can lead to incorrect serving or handling by browsers and applications.
- gotcha Supabase Storage access is governed by Row Level Security (RLS) policies defined within your Supabase project. Improperly configured RLS on the `objects` table (and sometimes `buckets` table) is a common source of 'permission denied' errors when performing operations like uploading, downloading, or listing files.
- gotcha The `storage-py` repository, which contains `storage3`, has been moved into the main `supabase-py` monorepo. While `storage3` continues to be released as a standalone package, its development and issue tracking are now integrated with the broader Supabase Python client.
Install
-
pip install storage3
Imports
- AsyncStorageClient
from storage3 import AsyncStorageClient
- SyncStorageClient
from storage3 import SyncStorageClient
Quickstart
import os
from storage3 import AsyncStorageClient
import asyncio
# Replace with your Supabase project URL and API Key
SUPABASE_URL = os.environ.get('SUPABASE_URL', 'https://your-project-id.supabase.co/storage/v1')
SUPABASE_KEY = os.environ.get('SUPABASE_KEY', 'your_anon_public_key')
# Headers are required for authentication
HEADERS = {"apiKey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}"}
async def main():
storage_client = AsyncStorageClient(SUPABASE_URL, HEADERS)
print("Listing buckets...")
try:
buckets = await storage_client.list_buckets()
if buckets:
print(f"Found {len(buckets)} bucket(s): {[b['name'] for b in buckets]}")
else:
print("No buckets found. Attempting to create one...")
new_bucket = await storage_client.create_bucket('my-test-bucket-py', {'public': True})
print(f"Created bucket: {new_bucket['name']}")
buckets = [new_bucket]
if buckets:
bucket_name = buckets[0]['name']
print(f"Using bucket: {bucket_name}")
# Example: Uploading a dummy file (requires a file_object, e.g., from an open file)
# For a real scenario, replace `b'Hello, Supabase Storage!'` with actual file data
file_content = b'Hello, Supabase Storage from Python!'
file_name = 'hello_world.txt'
print(f"Uploading file '{file_name}' to bucket '{bucket_name}'...")
upload_response = await storage_client.from_(bucket_name).upload(
f'public/{file_name}',
file_content,
{'content-type': 'text/plain'}
)
print(f"Upload successful: {upload_response}")
# Example: Listing files in the bucket
print(f"Listing files in bucket '{bucket_name}'...")
files = await storage_client.from_(bucket_name).list(path='public/')
print(f"Files in bucket '{bucket_name}': {[f['name'] for f in files]}")
# Example: Downloading the file
print(f"Downloading file '{file_name}' from bucket '{bucket_name}'...")
downloaded_data = await storage_client.from_(bucket_name).download(f'public/{file_name}')
print(f"Downloaded content: {downloaded_data.decode()}")
# Example: Deleting the file
print(f"Deleting file '{file_name}' from bucket '{bucket_name}'...")
delete_response = await storage_client.from_(bucket_name).remove([f'public/{file_name}'])
print(f"Delete successful: {delete_response}")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
asyncio.run(main())