# Upload Files as Text (https://www.librechat.ai/docs/features/upload_as_text)

# Upload Files as Text

Ever wanted to hand a PDF, a code file, or a spreadsheet to the AI and just say _"read this"_? That's exactly what **Upload as Text** does.

You attach a file, LibreChat extracts the text from it, and the full content gets pasted straight into your conversation. The AI can then read every word of it — no plugins, no vector databases, no extra services to configure. It works out of the box.

<Callout type="info" title="Zero setup required">
  Upload as Text works immediately on any LibreChat instance. It uses built-in text parsing — you don't need OCR, a RAG pipeline, or any external service to get started.
</Callout>

---

## How to use it

<Steps>
  <Step>
    ### Click the attachment icon

    In the chat input bar, click the **paperclip** (📎) icon.
  </Step>
  <Step>
    ### Pick "Upload as Text"

    From the dropdown menu, select **Upload as Text**. This tells LibreChat to read the file contents rather than pass it as a raw attachment.
  </Step>
  <Step>
    ### Choose your file

    Select the file from your device. LibreChat will extract the text and embed it directly into your message.
  </Step>
  <Step>
    ### Ask your question

    Type your prompt as usual. The AI now has the full text of your file in context and can reference any part of it.
  </Step>
</Steps>

When you select several files, LibreChat skips individual duplicates and files over the per-file size limit, names the skipped files in a notice, and continues uploading the valid files. The file-count and total-batch-size limits still apply to the files that remain; if the surviving batch exceeds either limit, the batch is rejected together. Single-file behavior is unchanged.

<Callout type="warn" title="Don't see the option?">
  If "Upload as Text" doesn't appear, the `context` capability may have been disabled by your admin. It's on by default — but if the capabilities list was customized, `context` needs to be explicitly included. See the [configuration section](#the-context-capability) below.
</Callout>

---

## Paste long text as a file

In the normal message composer, LibreChat can turn a paste longer than 2,500 characters into an Upload as Text attachment. This keeps a large paste out of the input while still providing its contents to the model through the conversation context. The first attachment is named `pasted-text.txt`; additional pasted-text attachments receive numbered names.

The browser-local **Paste long text as a file** setting is enabled by default under **Settings > Chat > Sending**. Shorter pastes and text pasted while answering an Agent's **Ask User** form remain inline. If context uploads are unavailable, the text also remains inline. If an attachment upload fails, LibreChat restores the text to the composer when it can do so without overwriting a newer draft.

Pasted-text attachments follow the same file-size, token, and [`fileTokenLimit`](#token-limits-and-truncation) rules as other Upload as Text files.

---

## What happens under the hood

When you upload a file this way, LibreChat doesn't just dump raw bytes into the prompt. It runs through a processing pipeline to extract clean, readable text:

1. **MIME type detection** — LibreChat checks what kind of file you uploaded (PDF, image, audio, source code, etc.) by inspecting its MIME type.
2. **Method selection** — Based on the file type and what services are available, it picks the best extraction method using this priority:

<Tabs items={["Priority order", "Decision examples"]}>
  <Tabs.Tab>
    | Priority | Method | When it's used |
    |----------|--------|---------------|
    | 1st | **OCR** | File is an image or scanned document, _and_ OCR is configured |
    | 2nd | **STT** (Speech-to-Text) | File is audio, _and_ STT is configured |
    | 3rd | **Text parsing** | File matches a known text MIME type |
    | 4th | **Fallback** | None of the above matched — tries text parsing anyway |
  </Tabs.Tab>
  <Tabs.Tab>
    **A `.pdf` on an instance with OCR configured:**
    → OCR kicks in. Great for scanned docs and complex layouts.

    **A `.pdf` on a default instance (no OCR):**
    → Text parsing handles it. Works well for digitally-created PDFs.

    **A `.py` Python file:**
    → Straight to text parsing. Source code is already text — no conversion needed.

    **An `.mp3` on an instance with STT configured:**
    → Speech-to-Text transcribes it into text for the conversation.

    **A `.png` screenshot with no OCR configured:**
    → Falls back to text parsing (limited results — consider setting up OCR for images).
  </Tabs.Tab>
</Tabs>

3. **Token truncation** — The extracted text is trimmed to the `fileTokenLimit` (default: 100,000 tokens) so it doesn't blow past the model's context window.
4. **Prompt injection** — The text gets included in the conversation context, right alongside your message.

When you preview or download an Upload as Text attachment, LibreChat serves the extracted text stored with the file record. Downloads use a `.txt` filename even when OCR or another parser produced the stored text and there is no original backing file to stream.

---

## Which files are supported

<Tabs items={["Text & code", "Documents", "Images", "Audio"]}>
  <Tabs.Tab>
    These are parsed directly — they're already text, so no conversion is needed.

    - Plain text (`.txt`), Markdown (`.md`), CSV, JSON, XML, HTML, CSS
    - Programming languages — Python, JavaScript, TypeScript, Java, C#, PHP, Ruby, Go, Rust, Kotlin, Swift, Scala, Perl, Lua
    - Config files — YAML, TOML, INI
    - Shell scripts, SQL files
  </Tabs.Tab>
  <Tabs.Tab>
    Text parsing handles these out of the box. If OCR is configured, it takes over for better accuracy on complex layouts.

    - **PDF** — digital and scanned (scanned PDFs benefit from OCR)
    - **Word** — `.docx`, `.doc`
    - **PowerPoint** — `.pptx`, `.potx`, `.ppt`
    - **Excel** — `.xlsx`, `.xls`
    - **EPUB** books
  </Tabs.Tab>
  <Tabs.Tab>
    Images **require OCR** to produce useful text. Without it, results will be poor.

    - JPEG, PNG, GIF, WebP
    - HEIC, HEIF (Apple formats)
    - Screenshots, photos of documents, scanned pages
  </Tabs.Tab>
  <Tabs.Tab>
    Audio files **require STT** to be configured. There's no fallback — audio can't be "text parsed."

    - MP3, WAV, OGG, FLAC
    - M4A, WebM
    - Voice recordings, podcast clips
  </Tabs.Tab>
</Tabs>

LibreChat normalizes shell-script MIME variants reported by Chrome on Linux (`application/x-shellscript`) and libmagic (`text/x-shellscript`) to the canonical `application/x-sh` before checking the endpoint allowlist. Custom [`supportedMimeTypes`](/docs/configuration/librechat_yaml/object_structure/file_config#supportedmimetypes-3) rules must still permit `application/x-sh`.

---

## Upload as Text vs. other upload options

LibreChat has three ways to upload files. Each one works differently and suits different situations:

<Cards>
  <Card title="Upload as Text" href="#how-to-use-it">
    Extracts the full file content and drops it into the conversation. Best for smaller files where you want the AI to read everything — contracts, code files, articles. Works with all models, no extra services needed.
  </Card>
  <Card title="Upload for File Search (RAG)" href="/docs/features/rag_api">
    Indexes the file in a vector database and retrieves only the relevant chunks when you ask a question. Better for large files or collections of files where dumping everything into context would waste tokens. Requires the RAG API.
  </Card>
  <Card title="Standard Upload" href="/docs/features/agents">
    Passes the file directly to the model — used for vision models analyzing images, or code interpreter running scripts. No text extraction happens.
  </Card>
</Cards>

**Quick decision guide:**

| Situation | Best option |
|-----------|-------------|
| _"Read this 5-page contract and summarize it"_ | **Upload as Text** |
| _"I have 50 PDFs, find what mentions pricing"_ | **File Search (RAG)** |
| _"What's in this screenshot?"_ (vision model) | **Standard Upload** |
| _"Run this Python script"_ (code interpreter) | **Standard Upload** |
| _"Review this code file for bugs"_ | **Upload as Text** |
| _"Search through our company docs"_ | **File Search (RAG)** |

---

## The `context` capability

Under the hood, Upload as Text is powered by the **`context` capability**. This is what controls whether the feature appears in your chat UI.

<Callout type="info">
  The `context` capability is **enabled by default**. You only need to touch this if your admin has customized the capabilities list and accidentally left it out.
</Callout>

```yaml title="librechat.yaml"
endpoints:
  agents:
    capabilities:
      - "context"  # This is what enables "Upload as Text"
```

The same `context` capability also powers **Agent File Context** (uploading files through the Agent Builder to embed text into an agent's system instructions). The difference is _where_ the text ends up:

| | Upload as Text | Agent File Context |
|---|---|---|
| **Where** | Chat input (any conversation) | Agent Builder panel |
| **Scope** | Current conversation only | Persists in agent's instructions |
| **Use case** | One-off document questions | Building specialized agents with baked-in knowledge |

---

## Token limits and truncation

When a file is too long to fit in the model's context window, LibreChat truncates the extracted text to stay within bounds. This happens automatically — you don't need to worry about it, but it's good to know how it works.

```yaml title="librechat.yaml"
fileConfig:
  fileTokenLimit: 100000  # Default: 100,000 tokens
```

<Callout type="warn" title="Truncation means lost content">
  If your file exceeds the limit, the text is cut off at the end. If you're getting incomplete answers, this might be why. You can increase `fileTokenLimit`, but keep in mind that larger values use more tokens per message — which increases cost and may hit the model's own context limit.
</Callout>

**Rules of thumb:**
- 100k tokens ≈ a 300-page book (plenty for most use cases)
- If you're working with very large files, consider [File Search (RAG)](/docs/features/rag_api) instead — it only retrieves the relevant sections rather than stuffing everything into context

---

## Optional: boosting extraction with OCR

Text parsing works fine for digitally-created documents (PDFs saved from Word, code files, plain text). But if you're uploading **scanned documents, photos of pages, or images with text**, the built-in parser won't get great results.

That's where OCR comes in. When configured, LibreChat automatically uses OCR for file types that benefit from it — you don't need to do anything differently as a user.

<Accordions>
  <Accordion title="How to tell your admin to set up OCR">
    Point them to the [OCR configuration docs](/docs/features/ocr). The short version:

    ```yaml title="librechat.yaml"
    ocr:
      strategy: "mistral_ocr"
      apiKey: "${OCR_API_KEY}"
      baseURL: "https://api.mistral.ai/v1"
      mistralModel: "mistral-ocr-latest"
    ```

    Once configured, OCR automatically handles images and scanned PDFs — no changes needed on the user side.
  </Accordion>
  <Accordion title="How to tell your admin to set up STT (for audio files)">
    For transcribing audio uploads, the admin needs to configure a Speech-to-Text service. See the [STT configuration reference](/docs/configuration/librechat_yaml/object_structure/file_config#stt).
  </Accordion>
</Accordions>

---

## File handling configuration reference

This section is for admins who want to control which file types get processed by which method. The defaults work well — you only need to touch this if you want to fine-tune behavior.

<Accordions>
  <Accordion title="Full fileConfig example">
    ```yaml title="librechat.yaml"
    fileConfig:
      # Max tokens extracted from a single file before truncation
      fileTokenLimit: 100000

      # Files matching these MIME patterns use OCR (if configured)
      ocr:
        supportedMimeTypes:
          - "^image/(jpeg|gif|png|webp|heic|heif)$"
          - "^application/pdf$"
          - "^application/vnd\\.openxmlformats-officedocument\\.(wordprocessingml\\.document|presentationml\\.presentation|spreadsheetml\\.sheet)$"
          - "^application/vnd\\.ms-(word|powerpoint|excel)$"
          - "^application/epub\\+zip$"

      # Files matching these MIME patterns use text parsing
      text:
        supportedMimeTypes:
          - "^text/(plain|markdown|csv|json|xml|html|css|javascript|typescript|x-python|x-java|x-csharp|x-php|x-ruby|x-go|x-rust|x-kotlin|x-swift|x-scala|x-perl|x-lua|x-shell|x-sql|x-yaml|x-toml)$"

      # Files matching these MIME patterns use STT (if configured)
      stt:
        supportedMimeTypes:
          - "^audio/(mp3|mpeg|mpeg3|wav|wave|x-wav|ogg|vorbis|mp4|x-m4a|flac|x-flac|webm)$"
    ```

    **Priority reminder:** OCR > STT > text parsing > fallback.

    For the full reference, see [File Config Object Structure](/docs/configuration/librechat_yaml/object_structure/file_config).
  </Accordion>
</Accordions>

---

## Troubleshooting

<Accordions>
  <Accordion title="Upload as Text option not appearing">
    The `context` capability was likely removed from your configuration. Ask your admin to add it back:

    ```yaml
    endpoints:
      agents:
        capabilities:
          - "context"
    ```
  </Accordion>
  <Accordion title="File content looks wrong or is mostly empty">
    A few things to check:
    - **Scanned PDFs / images** — These need OCR to extract text properly. Without it, the parser might return garbage or nothing. Ask your admin to [configure OCR](/docs/features/ocr).
    - **Audio files** — These need STT. There's no text fallback for audio.
    - **Corrupted files** — Try opening the file locally to make sure it's not damaged.
    - **Unsupported format** — If the MIME type doesn't match any configured pattern, LibreChat attempts a text parse fallback, which may not work for binary formats.
  </Accordion>
  <Accordion title="Upload is rejected as an unsupported file type">
    LibreChat returns the rejected MIME type in the upload error. Check the active endpoint's [`fileConfig.endpoints.<endpoint>.supportedMimeTypes`](/docs/configuration/librechat_yaml/object_structure/file_config#supportedmimetypes-3) patterns and allow the canonical type you intend to accept. For shell scripts, use `application/x-sh`; LibreChat normalizes the common `application/x-shellscript` and `text/x-shellscript` variants before matching.
  </Accordion>
  <Accordion title="The AI seems to be missing part of my file">
    Your file probably exceeded the `fileTokenLimit`. The text was truncated.

    **Options:**
    - Ask your admin to increase `fileTokenLimit` in `librechat.yaml`
    - Use [File Search (RAG)](/docs/features/rag_api) instead, which retrieves relevant chunks rather than loading the entire file
    - Split the file into smaller parts and upload them separately
  </Accordion>
  <Accordion title="Images upload but the AI can't read the text in them">
    Without OCR, images are processed through text parsing, which can't actually "see" text in an image. You need OCR configured for this to work. See [OCR for Documents](/docs/features/ocr).

    Alternatively, use a **vision model** with standard file upload — the model itself can read text in images.
  </Accordion>
</Accordions>

---

## Related

- [OCR for Documents](/docs/features/ocr) — Set up optical character recognition for images and scans
- [RAG API (Chat with Files)](/docs/features/rag_api) — Semantic search over large document collections
- [Agents — File Context](/docs/features/agents#file-context) — Embed file content into an agent's system instructions
- [File Config reference](/docs/configuration/librechat_yaml/object_structure/file_config) — Full YAML schema for file handling
