> ## Documentation Index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Install upstash-blob, pick Bucket or AsyncBucket, and build a client for your server.

`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](https://upstash.com/docs/blob/uploads/upload-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

```bash pip theme={"system"}
pip install upstash-blob
```

```bash uv theme={"system"}
uv add upstash-blob
```

```bash poetry theme={"system"}
poetry add upstash-blob
```

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

| Import | Exports |
| - | - |
| `upstash_blob` | `Bucket`, `AsyncBucket`, `UploadHandler`, `AsyncUploadHandler`, `UploadRoute`, `BeforeUploadResult`, `unique_path`, `BlobError`, `format_bytes`, and the types |
| `upstash_blob.fastapi` | `upload_view`, for an `AsyncUploadHandler` on FastAPI or Starlette |
| `upstash_blob.django` | `upload_view`, for either handler |
| `upstash_blob.flask` | `upload_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](https://upstash.com/docs/blob/uploads/upload-client#with-a-server-in-another-language).

***

## Bucket and AsyncBucket

```python Sync theme={"system"}
from upstash_blob import Bucket

bucket = Bucket.from_env()  # reads UPSTASH_BLOB_TOKEN
blob = bucket.put("notes/1.md", "# Hello")
```

```python Async theme={"system"}
from upstash_blob import AsyncBucket

bucket = AsyncBucket.from_env()  # reads UPSTASH_BLOB_TOKEN
blob = await bucket.put("notes/1.md", "# Hello")
```

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:

```python Sync theme={"system"}
with Bucket.from_env() as bucket:
    bucket.put("exports/today.csv", rows)
```

```python Async theme={"system"}
async with AsyncBucket.from_env() as bucket:
    await bucket.put("exports/today.csv", rows)
```

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

***

## The Bucket client

```python app/blob.py theme={"system"}
import os

from upstash_blob import Bucket

bucket = Bucket(
    os.environ["UPSTASH_BLOB_TOKEN"],
    cache="immutable",
    enable_telemetry=False,
)
```

`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:

```python theme={"system"}
Bucket.from_env(cache="immutable")
Bucket.from_env("REPORTS_BUCKET_TOKEN", cache="immutable")
```

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

| Option | Type | Description |
| - | - | - |
| `token` | `str` | Required, and the only positional argument. See [Connecting](https://upstash.com/docs/blob/bucket/connecting). |
| `cache` | `CacheOption` | The default `Cache-Control` for every object this client stores. A per-call `cache` overrides it. See [Caching](https://upstash.com/docs/blob/bucket/caching). |
| `enable_telemetry` | `bool` | `False` turns telemetry off for this client. See [Telemetry](https://upstash.com/docs/blob/bucket/connecting#telemetry). |
| `retry` | `RetryConfig \| Literal[False]` | `False`, or `{"retries": ..., "backoff": ...}`. See [Retries](#retries). |
| `http_client` | `httpx.Client` / `httpx.AsyncClient` | Sends 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](https://upstash.com/docs/blob/bucket/connecting#public-or-private).

### Retries

```python theme={"system"}
Bucket(token, retry=False)  # every request once
Bucket(token, retry={"retries": 5, "backoff": lambda n: n * 500})
```

| Field | Type | Description |
| - | - | - |
| `retries` | `int` | Retries after the first attempt, for every request this client makes. |
| `backoff` | `Callable[[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](https://upstash.com/docs/blob/bucket/connecting#retries).

***

## Using an S3 client

```python theme={"system"}
import boto3

from app.blob import bucket

cfg = bucket.s3()
s3 = boto3.client("s3", **cfg.client_kwargs())

s3.get_object(Bucket=cfg.bucket, Key="reports/q3.pdf", Range="bytes=0-1023")
```

`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](https://upstash.com/docs/blob/bucket/connecting#using-an-s3-client).

***

## Option types

| Type | Python | Grammar |
| - | - | - |
| `Size` | `int \| str` | [Size](https://upstash.com/docs/blob/reference/types#size) |
| `Duration` | `int \| float \| str \| timedelta` | [Duration](https://upstash.com/docs/blob/reference/types#duration). A `timedelta` counts as its total seconds. |
| `CacheOption` | `Duration \| Literal["immutable", "revalidate", "no-store"]` | [CacheOption](https://upstash.com/docs/blob/reference/types#cacheoption). A raw header is a `str`. |
| `MultipartOption` | `bool \| Size` | [Changing the threshold](https://upstash.com/docs/blob/uploads/large-files#changing-the-threshold) |

All four are exported from `upstash_blob`.

```python theme={"system"}
from datetime import timedelta

bucket.signed_read_url("reports/q3.pdf", expires_in=timedelta(minutes=2))
bucket.put("avatars/7.png", data, cache=timedelta(days=7))  # public, max-age=604800
bucket.put("export.csv", chunks, max_size="10MiB")
```

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](https://upstash.com/docs/blob/sdks/py/errors#bad-options-raise-typeerror-or-valueerror).

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

> [card] [Bucket API](https://upstash.com/docs/blob/sdks/py/bucket)
>
> Every `Bucket` method, its options and the records it returns.

> [card] [Upload handler](https://upstash.com/docs/blob/sdks/py/upload-handler)
>
> `UploadHandler` options, callbacks, and mounting it in FastAPI, Django and Flask.

> [card] [Errors](https://upstash.com/docs/blob/sdks/py/errors)
>
> `BlobError`, the fields it carries, and what raises something else.

> [card] [FastAPI + React](https://upstash.com/docs/blob/recipes/fastapi-react)
>
> A Python backend serving `useUpload`, end to end.


## Related topics

- [Python SDK](https://upstash.com/docs/workflow/sdk/workflow-py.md)
- [API Examples](https://upstash.com/docs/qstash/overall/apiexamples.md)
- [Ratelimit Python SDK Overview](https://upstash.com/docs/redis/sdks/ratelimit-py/overview.md)
- [Redis Python SDK Overview](https://upstash.com/docs/redis/sdks/py/overview.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.