---
title: File input
description: A file picker for collecting uploads in a modal, up to a configurable file count and type list.
---

`file_input` lets someone attach one or more files to a form. It's an `input`-block-only element,
and Slack restricts it further than most: it's only supported in modals, not in messages or Home
tabs.

<Preview
  payload={{
    type: "modal",
    title: { type: "plain_text", text: "New entry" },
    submit: { type: "plain_text", text: "Save" },
    close: { type: "plain_text", text: "Cancel" },
    blocks: [
      {
        type: "input",
        block_id: "attachments",
        label: { type: "plain_text", text: "Attachments" },
        element: {
          type: "file_input",
          action_id: "files",
          filetypes: ["pdf", "png"],
          max_files: 3,
        },
      },
    ],
  }}
/>

:::note
This is a UI-only picker: choosing a file records its name, type and size in the shape Slack sends
to a `files:read`-scoped app, but no bytes are uploaded anywhere.
:::

## Fields

| Prop | Type | Default | Description |
| - | - | - | - |
| `type` | `"file_input"` | - | Always `file_input`. |
| `action_id?` | `string` | - | Identifies this action in the interaction payload and as the key in `state.values`. Maximum length is 255 characters. |
| `filetypes?` | `string[]` | - | Accepted file extensions, without the dot (e.g. `["pdf", "png"]`). All file types are accepted when omitted. |
| `max_files?` | `number` | `10` | Maximum number of files that can be uploaded. Minimum 1, maximum 10. |

:::note
Slack always labels the picker button "Upload File" (singular), even when `max_files` allows
several.
:::

## Examples

### Restricted to specific file types

The preview above limits uploads to `pdf` and `png` files via `filetypes`, and to 3 files via
`max_files`. The native file picker only offers matching files, but treat this as a convenience for
the person filling out the form. Validate the uploaded file types yourself when you handle the
submission.

### Any file type, single upload

<Preview
  payload={{
    blocks: [
      {
        type: "input",
        block_id: "resume",
        label: { type: "plain_text", text: "Resume" },
        element: {
          type: "file_input",
          action_id: "resume_input",
          max_files: 1,
        },
      },
    ],
  }}
/>

Without `filetypes`, any file is accepted. `max_files: 1` still shows the same singular "Upload
File" button; Slack doesn't change its label based on the limit.

## Interactivity

Picking files calls `onAction` with the picked files' metadata under `files`:

```json
{
  "type": "file_input",
  "action_id": "files",
  "block_id": "attachments",
  "action_ts": "1706000000.000100",
  "files": [{ "id": "F1706000000000", "name": "report.pdf", "filetype": "pdf", "size": 48213 }]
}
```

### Reading the value

Picking files writes the same list to `state.values` as `{ type, files }`:

```json
{
  "attachments": {
    "files": {
      "type": "file_input",
      "files": [{ "id": "F1706000000000", "name": "report.pdf", "filetype": "pdf", "size": 48213 }]
    }
  }
}
```

## Related

**[Rich text input](/elements/rich-text-input)**

A formatted text field, also modal-only, that reports a `rich_text` value.

**[Text inputs](/elements/text-inputs)**

Plain text, email, URL and number inputs for modals and Home tabs.

**[Date picker](/elements/date-picker)**

Pick a single date from a calendar dropdown.

**[Elements overview](/elements/index)**

Where each element can live, and how `action_id` and `block_id` fit together.
