Skip to main content

upstash-blob is the Python SDK. It has a sync Bucket and an async AsyncBucket, and an upload handler for each that serves the browser client, so a React app can upload straight to storage through a Python backend.

This section is the Python reference: names, types, and framework wiring. What each call does, its defaults and its limits are on the concept pages it links to.


Install#

It needs Python 3.10 or later, and its one dependency is httpx. FastAPI, Django, Flask, pydantic and boto3 are not pulled in; the modules that use them import them only when you do.


Modules#

ImportExports
upstash_blobBucket, AsyncBucket, UploadHandler, AsyncUploadHandler, UploadRoute, BeforeUploadResult, unique_path, BlobError, format_bytes, and the types
upstash_blob.fastapiupload_view, for an AsyncUploadHandler on FastAPI or Starlette
upstash_blob.djangoupload_view, for either handler
upstash_blob.flaskupload_view, for an UploadHandler

There is no Python browser client. The browser runs @upstash/blob/react or @upstash/blob/browser, which speak the same protocol to a Python handler as to a TypeScript one; see With a server in another language.


Bucket and AsyncBucket#

The two have the same methods, options and records. Every AsyncBucket method is awaited, including public_url() and s3(), except stream(), which is async with and yields an AsyncBlobStream. Its put also takes async iterables as a body. Use AsyncBucket under FastAPI, Starlette or any other asyncio code, and Bucket everywhere else.

Each bucket holds an httpx client with its own connection pool. A bucket built once at import lives as long as the process and needs no closing. One you build for a single job closes with a context manager:

close() and await aclose() do the same by hand.


The Bucket client#

app/blob.py

Bucket.from_env() is the same constructor with the token read from UPSTASH_BLOB_TOKEN. It takes the same keyword options, and a variable name when the token lives somewhere else:

An unset or empty variable raises a TypeError when the bucket is built, not on the first request.

OptionTypeDescription
tokenstrRequired, and the only positional argument. See Connecting.
cacheCacheOptionThe default Cache-Control for every object this client stores. A per-call cache overrides it. See Caching.
enable_telemetryboolFalse turns telemetry off for this client. See Telemetry.
retryRetryConfig | Literal[False]False, or {"retries": ..., "backoff": ...}. See Retries.
http_clienthttpx.Client / httpx.AsyncClientSends every request, for a proxy or custom timeouts. A client you pass is never closed by the bucket.

AsyncBucket takes an httpx.AsyncClient; Bucket takes an httpx.Client.

There is no visibility option. Whether the bucket is public or private is a console setting; see Connecting.

Retries#

FieldTypeDescription
retriesintRetries after the first attempt, for every request this client makes.
backoffCallable[[int], float]Milliseconds before retry n, counted from 0. A Retry-After from the service wins over it.

RetryConfig is the TypedDict for this shape. An unknown key, a negative count or a backoff that is not callable raises a TypeError when the bucket is built. Which requests are retried, and the default budget and backoff, are on Retries.


Using an S3 client#

bucket.s3() returns an S3Config with the endpoint, region, bucket name and a short-lived credential. client_kwargs() is what boto3.client("s3", ...) takes. On AsyncBucket, s3() is awaited.

Unlike the TypeScript config, the credential is a fixed value, not a provider: boto3 cannot refresh it. It stops working at cfg.expires_at, so build a new client from a fresh bucket.s3() before then.

What an S3 client is for, and why it must not presign, is on Using an S3 client.


Option types#

TypePythonGrammar
Sizeint | strSize
Durationint | float | str | timedeltaDuration. A timedelta counts as its total seconds.
CacheOptionDuration | Literal["immutable", "revalidate", "no-store"]CacheOption. A raw header is a str.
MultipartOptionbool | SizeChanging the threshold

All four are exported from upstash_blob.

A value of the wrong type, such as a bool size, raises a TypeError. A string that does not parse, such as "5mbit", raises a ValueError naming the option. Both are raised by the call that takes the option, except a cache on the client, which is checked on each call that stores an object. See Bad options.

Every size the SDK returns is an int of bytes. format_bytes(2_400_000) is '2.4 MB', the same text the browser client shows.


Next steps#