# PDF, Image & Office to Text/Markdown with OCR (`jadelike_mustang/document-to-text`) Actor

Input links to PDF, scanned PDF, image, DOCX, PPTX or XLSX files (Google Drive and Dropbox links work). Output one item per document: clean text, LLM-ready Markdown with tables, per-page content, optional RAG chunks. OCR in 24 languages only where needed.

- **URL**: https://apify.com/jadelike_mustang/document-to-text.md
- **Developed by:** [Ernesto Privato](https://apify.com/jadelike_mustang) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 page (text layer or office)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## PDF, Image & Office to Text and Markdown (with OCR)

Turn **any document into clean text and LLM-ready Markdown** in one Actor: PDFs (digital or scanned), images, **Word (.docx), PowerPoint (.pptx) and Excel (.xlsx)**. Tables become Markdown tables and structured rows, scanned pages are read with **OCR in 24 languages**, and you can get **RAG-ready chunks** directly.

### Why this Actor

- **One Actor for every format**: PDF, PNG, JPG, TIFF (multi-page), WebP, BMP, GIF, DOCX, PPTX, XLSX. No need to chain a PDF parser, an OCR tool and an Office converter.
- **Smart OCR, cheaper runs**: in *Auto* mode the PDF text layer is used when it exists and OCR runs **only on scanned pages**. You pay the OCR price only for pages that need it.
- **Markdown with structure**: headings and lists from Word, slide titles and speaker notes from PowerPoint, one table per Excel sheet, and real tables from PDFs placed where they appear on the page.
- **RAG-ready**: set a chunk size and get the Markdown split on paragraph boundaries.
- **Google Drive and Dropbox links** work as they are (share links are converted to direct downloads).
- **No start fee**: you pay per page actually processed. A broken or missing file is not charged and does not stop the run.

### Use cases

- **RAG and AI agents**: feed PDFs, decks and spreadsheets to your LLM as Markdown chunks
- **Document processing**: invoices, contracts, reports, forms and scans to searchable text
- **Data extraction**: tables from PDF reports and Excel files as rows of cells
- **Archives**: OCR of scanned books, letters and faxes in 24 languages

### Input example

```json
{
  "documents": [
    "https://arxiv.org/pdf/1706.03762",
    "https://example.com/scanned-invoice.pdf",
    "https://drive.google.com/file/d/FILE_ID/view",
    "https://example.com/quarterly-report.docx"
  ],
  "ocrMode": "auto",
  "ocrLanguages": ["eng", "deu"],
  "chunkSize": 2000
}
```

### Output example

One item per document:

```json
{
  "url": "https://example.com/quarterly-report.docx",
  "fileName": "quarterly-report.docx",
  "fileType": "docx",
  "pageCount": 1,
  "pagesProcessed": 1,
  "ocrPages": 0,
  "truncated": false,
  "text": "Quarterly report\nRevenue grew 12% year over year.\n…",
  "markdown": "# Quarterly report\n\nRevenue grew 12% year over year.\n\n| Quarter | Revenue |\n|---|---|\n| Q1 | 100 |\n| Q2 | 112 |",
  "wordCount": 18,
  "tableCount": 1,
  "chunks": ["# Quarterly report\n\nRevenue grew 12%…"],
  "pages": [
    { "page": 1, "text": "…", "markdown": "…", "tables": [[["Quarter", "Revenue"], ["Q1", "100"], ["Q2", "112"]]], "ocr": false }
  ],
  "error": null
}
```

What a "page" is: a PDF page, an image (or a TIFF frame), a PowerPoint slide, an Excel sheet; a Word document counts as one page.

### Options

- **OCR**: *Auto* (only scanned pages), *Always* (every PDF page, e.g. PDFs with a broken text layer), *Never* (text layer only)
- **OCR languages**: English, German, French, Italian, Spanish, Portuguese, Dutch, Polish, Swedish, Danish, Norwegian, Finnish, Czech, Romanian, Hungarian, Turkish, Russian, Ukrainian, Greek, Chinese (simplified), Japanese, Korean, Arabic, Hindi
- **Pages** (e.g. `1-5,8`) and **max pages per document**
- **Per-page content**, **tables as data**, **RAG chunk size**, **OCR resolution**

### Pricing

Pay per event, only for results you get:

- **$0.001** per page with a text layer, slide, sheet or Word document; **$0.004** per page or image that needs OCR. No start fee.
- Apify subscribers pay less: **10% off on Bronze, 20% on Silver, 30% on Gold** and higher plans.
- Set a maximum charge per run in the run options: the Actor stops cleanly when it is reached.

### Input reference

| Field | Type | Default | Description |
|---|---|---|---|
| `documents` *(required)* | array |  | **Document URLs**. Public links to PDF, image (PNG, JPG, TIFF, WebP, BMP, GIF), Word (.docx), PowerPoint (.pptx) or Excel (.xlsx) files. Google Drive and Dropbox share links work too. |
| `ocrMode` | string (`auto`, `always`, `never`) | `auto` | **OCR**. Auto reads the PDF text layer and runs OCR only on pages without text (scans). Images are always read with OCR. |
| `ocrLanguages` | array of codes | `eng` | **OCR languages**. Languages in the scanned documents. Pick only the ones you need: more languages = slower. |
| `pages` | string |  | **Pages**. PDF pages to read, e.g. '1-5,8'. Leave empty for all. |
| `maxPagesPerDocument` | integer |  | **Max pages per document**. Stop after this many pages in each document. 0 or empty = no limit. |
| `includePages` | boolean | `true` | **Include per-page content**. Add a 'pages' list with text, Markdown, tables and OCR flag for each page (slide, sheet). |
| `includeTables` | boolean | `true` | **Include tables as data**. Add the tables found on each page as rows of cells (they are always in the Markdown). |
| `chunkSize` | integer |  | **RAG chunk size (characters)**. Also split the Markdown into chunks of at most this many characters, on paragraph boundaries (e.g. 2000). 0 or empty = no chunks. |
| `ocrDpi` | integer | `200` | **OCR resolution (DPI)**. Resolution used to render scanned PDF pages for OCR. 300 for small print, 200 is faster. |

### Tips

- Files must be reachable by a public link. To use a file from your computer, upload it to an Apify key-value store, Google Drive or Dropbox and paste the link.
- For scans, choose only the languages that are in the document: OCR is faster and more accurate.
- Password-protected PDFs cannot be read.

### Privacy

Documents are downloaded, processed in memory during the run and returned only to your dataset: they are not stored or shared elsewhere. At the end of each run the developer receives an anonymous notification with only numbers (pages processed, amount charged, duration, success or failure). Your input, the documents and your identity are never sent.

# Actor input Schema

## `documents` (type: `array`):

Public links to PDF, image (PNG, JPG, TIFF, WebP, BMP, GIF), Word (.docx), PowerPoint (.pptx) or Excel (.xlsx) files. Google Drive and Dropbox share links work too.

## `ocrMode` (type: `string`):

Auto reads the PDF text layer and runs OCR only on pages without text (scans). Images are always read with OCR.

## `ocrLanguages` (type: `array`):

Languages in the scanned documents. Pick only the ones you need: more languages = slower.

## `pages` (type: `string`):

PDF pages to read, e.g. '1-5,8'. Leave empty for all.

## `maxPagesPerDocument` (type: `integer`):

Stop after this many pages in each document. 0 or empty = no limit.

## `includePages` (type: `boolean`):

Add a 'pages' list with text, Markdown, tables and OCR flag for each page (slide, sheet).

## `includeTables` (type: `boolean`):

Add the tables found on each page as rows of cells (they are always in the Markdown).

## `chunkSize` (type: `integer`):

Also split the Markdown into chunks of at most this many characters, on paragraph boundaries (e.g. 2000). 0 or empty = no chunks.

## `ocrDpi` (type: `integer`):

Resolution used to render scanned PDF pages for OCR. 300 for small print, 200 is faster.

## Actor input object example

```json
{
  "documents": [
    "https://arxiv.org/pdf/1706.03762",
    "https://upload.wikimedia.org/wikipedia/commons/a/af/Atomist_quote_from_Democritus.png"
  ],
  "ocrMode": "auto",
  "ocrLanguages": [
    "eng"
  ],
  "includePages": true,
  "includeTables": true,
  "ocrDpi": 200
}
```

# Actor output Schema

## `documents` (type: `string`):

Overview table.

## `fullData` (type: `string`):

Text, Markdown, pages, tables and chunks.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "documents": [
        "https://arxiv.org/pdf/1706.03762",
        "https://upload.wikimedia.org/wikipedia/commons/a/af/Atomist_quote_from_Democritus.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jadelike_mustang/document-to-text").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "documents": [
        "https://arxiv.org/pdf/1706.03762",
        "https://upload.wikimedia.org/wikipedia/commons/a/af/Atomist_quote_from_Democritus.png",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jadelike_mustang/document-to-text").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "documents": [
    "https://arxiv.org/pdf/1706.03762",
    "https://upload.wikimedia.org/wikipedia/commons/a/af/Atomist_quote_from_Democritus.png"
  ]
}' |
apify call jadelike_mustang/document-to-text --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jadelike_mustang/document-to-text"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/AF4xoDHE8bghaZ5UX/builds/dmzzuctIwMTfW7urf/openapi.json
