Skip to main content

This page covers reading objects from your server: get for the bytes, info for the facts, exists for a boolean, list for a page of keys, and signed read URLs for a link that reads a private object without going through your server.

The records these return are on Types. Method signatures and option types: TypeScript, Python, Go.


get#

get returns the object’s record, with its content type and metadata, plus the body. In TypeScript and Go the body is a stream and nothing is buffered for you; Python’s get reads it in full, and stream() does not. Reading the body in each SDK: TypeScript, Python, Go.

A missing object throws a BlobError with code not_found, status 404. See Errors.

There is no range option. For byte ranges, use an S3 client.


info#

One HEAD request. The same record as get without the bytes, so reading a 2 GB object’s facts is cheap. A missing object throws not_found.

Metadata comes back from get and info only, with keys lowercased. See Metadata.


exists#

The same HEAD request as info, answering false instead of throwing.

If you need the etag, size or metadata anyway, call info and catch not_found instead of making two round trips.


list#

list returns one page of records and a cursor. The cursor is set only while more remains; pass it back for the next page. A full walk loops until it is unset.

All three options are optional.

OptionDefaultDescription
Prefixnone, the whole bucketOnly keys starting with this.
Limitstorage picks, at most 1000Page size, clamped to 1 to 1000.
Cursornone, the first pageThe cursor from the previous page.

Each entry carries path, size, etag, timestamp and URLs. There is no content type or metadata; reading those is one info per object.

The prefix is the only filter. There is no query by owner, type or date, so “this user’s files” has to be a prefix you chose at upload time. An app that needs to query its files should keep its own table and treat the bucket as storage, not an index.


Public URLs#

Every record on a public bucket already carries its URL; the public URL call gives you one for any path. It returns nothing on a private bucket. An empty path, or one with a . or .. segment, is rejected before any request is sent; see Paths.

The URL itself is built from the token, but whether the bucket has a public host at all is known only to the backend, so the first call on a fresh client fetches credentials. They are cached, so every call after that is local.

Versioned URLs#

The versioned URL is the URL with ?v=<etag> appended, so it changes whenever the content does. Use it for a stable path that gets overwritten: if avatars/u7.png is replaced every time the user picks a new picture, the plain URL never changes and caches keep serving the old bytes.

Pair it with cache: 'immutable' at upload. See Caching.


Private buckets#

A private bucket has no public host, so no record carries a URL or versioned URL. Nothing in the code declares this: the SDK learns it from the backend when it fetches credentials, and objects are stored with Cache-Control: private. Reads go through signed read URLs.


Signed read URLs#

A time-limited URL anyone can GET, returned with the moment it expires. Use it on a private bucket, or for an object you do not want linked from a public page. Names and types: TypeScript, Python, Go.

All three options are optional.

OptionDefaultDescription
Expires in'5m'How long to ask for, at most '10m'. '2m', '10m', or a bare number of seconds. A longer ask gets 10 minutes.
Download asnone, displayed inlineSave as this filename instead of displaying inline.
Content typethe stored typeWhat storage answers with as Content-Type, overriding what was stored.

Use the returned expiry#

What you pass as expires-in is what you asked for. The expiry that comes back is what you got, and it can be sooner, because no link lives longer than 10 minutes. Cache the link until the returned expiry, never until a deadline you compute yourself. This applies to signed upload URLs too. The reason is on How signing works.

Download filename#

Sets Content-Disposition: attachment, so the browser saves the file under that name rather than rendering it. Unicode names arrive intact. The filename is signed into the URL, so it cannot be edited afterwards.

Content type override#

Overrides what storage answers with, without rewriting the object. Refused with invalid_input if it is not a valid media type.


Next steps#