---
title: File uploads
description: Let people upload images, PDFs and other files with crow.files buckets, and control who can see and add them.
---

# File uploads

`crow.files` stores uploads in buckets you declare in [crow.json](/crow-json). Each bucket has its own rules, size limit and allowed types.

## Declare a bucket

```json
{
  "files": {
    "receipts": { "read": "creator", "write": "viewers", "maxSize": "10MB", "types": ["image/*", "application/pdf"] }
  }
}
```

| Key | Values |
| --- | --- |
| `read` | `public`, `viewers`, `creator`, `owner` |
| `write` | `viewers`, `creator`, `owner`, `public-add` |
| `maxSize` | Largest file, like `10MB` |
| `types` | Allowed MIME types; wildcards like `image/*` work |

## Upload and use files

```js
const receipts = crow.files.bucket("receipts");

const f = await receipts.upload(input.files[0]);   // { id, name, size, type, createdBy, createdAt, url }
img.src = receipts.url(f.id);                      // use it in <img>, <a href> or fetch()

const { files, cursor } = await receipts.list({ limit: 50, mine: true });
await receipts.get(f.id);                          // the record, or null
await receipts.remove(f.id);
```

## Uploads from signed-out visitors

On a `public` app, `write: "public-add"` lets signed-out visitors upload files up to 5 MB each.

## Safety

HTML and SVG uploads are always served as downloads, never as pages, so an upload can't run code on your app's address.

## Limits

Files are up to 25 MB each (100 MB for companies). Storage counts toward your plan: see [Plans and billing](/pricing). The dashboard's Data tab lists every bucket's files with their sizes and a delete button.
