# PDF to Markdown & Document to Markdown: OCR, RAG Chunks (`tobbyb/document-to-markdown-converter`) Actor

PDF to Markdown and document to Markdown converter for LLMs, RAG and AI agents. PDF, scanned PDF (OCR), DOCX, PPTX, XLSX, EPUB and HTML to clean Markdown or plain text, with tables, headings and table-aware RAG chunks. $0.003 per document.

- **URL**: https://apify.com/tobbyb/document-to-markdown-converter.md
- **Developed by:** [Tobby Tools](https://apify.com/tobbyb) (community)
- **Categories:** AI, Developer tools, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 document converteds

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

## Document to Markdown Converter: PDF to Markdown, OCR & RAG Chunks

**Turn PDFs, scans and Office files into clean Markdown and table-aware RAG chunks with one API call, for $0.003 per document.**

| Proof | |
|---|---|
| OCR on a noisy scan | **98.6% word F1**, vs 94.1% for the best competing Apify converter and 96.9% for the Docling library ([benchmark](#benchmark-pdf-to-markdown-quality-vs-other-apify-converters)) |
| Structure | The only converter in our test that kept all 4 heading levels, Table 2's two-level header and `10^20` exponents in *Attention Is All You Need* |
| Reproducible | Scripts, ground truth and every raw output are public: [github.com/tobbytools/pdf-to-markdown-rag](https://github.com/tobbytools/pdf-to-markdown-rag) |
| Price | $0.003 per document (up to 50 pages). Failed documents are free |

**Document to Markdown** for LLMs and RAG: convert **PDF to Markdown**, **PDF to text**, **DOCX to Markdown**, PPTX, XLSX, EPUB, HTML and **scanned PDFs or images (OCR)** to clean Markdown or plain text. Tables (including merged cells and tables that continue across pages), headings, lists and reading order are kept, and every document comes back with **table-aware RAG chunks** that carry page numbers and bounding boxes. **$0.003 per document**, and you only pay for documents that convert.

Use it as a hosted **MarkItDown alternative** that also does OCR, multi-column layouts and real tables, from the Apify Console, the API, or no-code tools (n8n, Make, Zapier).

### Quick start

1. Paste a PDF (or DOCX, PPTX, XLSX, EPUB, HTML, image) URL into **Files**, or upload a file.
2. Keep the defaults and click **Start**.
3. Read `content` (Markdown) and `chunks` (ready for embeddings) in the **Output** tab, or export as JSON, CSV or Excel.

Minimal input:

```json
{ "files": ["https://arxiv.org/pdf/1706.03762"] }
```

Shortened output (the full real result is [below](#sample-output-shortened-real-run-on-arxivorgpdf170603762)):

```json
{ "status": "succeeded", "title": "Attention Is All You Need", "pageCount": 15, "tableCount": 5,
  "content": "# Attention Is All You Need\n\n...\n\n## 3 Model Architecture\n\n### 3.1 Encoder and Decoder Stacks ...",
  "chunks": [{ "section": "Attention Is All You Need > 1 Introduction", "pages": [2], "charCount": 1384, "text": "..." }] }
```

From code, call `run-sync-get-dataset-items`:

```bash
curl -X POST "https://api.apify.com/v2/acts/tobbyb~document-to-markdown-converter/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{"files":["https://arxiv.org/pdf/1706.03762"]}'
```

### Use cases

- **RAG ingestion.** Chunks never split a table row, carry their section path and page numbers, and can be one dataset row each for Pinecone, Qdrant, Weaviate or Chroma.
- **Scanned archives.** Old reports, invoices and typewritten pages become searchable text, plus an optional searchable PDF.
- **Financial and scientific PDFs.** Dense numeric tables and two-column papers keep their structure and reading order.
- **No-code document pipelines.** n8n community node (`n8n-nodes-document-to-markdown-converter`), Make, Zapier, or base64 input when files aren't public.
- **AI agents.** Give an agent a document URL and get Markdown back, through LangChain, LlamaIndex or Apify's MCP server.

### What you get for each document

| Output | What it contains |
|---|---|
| `content` | The whole document as Markdown (`#` headings, lists, tables) or plain text |
| `chunks` | Table-aware chunks for embeddings: never split mid-row, a continued table repeats its header row, each chunk has `section` path, `pages`, page `boxes` (bbox) and character offsets |
| `tables` | Every table as JSON `rows`, `markdown`, and `html` with `rowspan`/`colspan` when cells are merged; `pages` when a table spans several pages; `bbox` |
| `pages` | Text per page, slide, sheet or EPUB chapter, page size, and `quality` flags: text layer or OCR, OCR confidence, table confidence, image coverage, `needsVision` |
| `figures` | Pictures and diagrams with page, bbox and their `Figure N:` caption |
| `elements` (optional) | Headings, paragraphs, list items and tables with bounding boxes, for citations and highlighting |
| `metadata` | Title, author, dates, page/word/table counts, OCR pages, SHA-256, removed running headers/footers per page, warnings |
| Files (optional) | `.md`, `.txt`, editable **Word `.docx`**, **Excel `.xlsx`** with one sheet per table, **searchable PDF** for scans |

### Benchmark: PDF to Markdown quality vs other Apify converters

Same 4 public documents, run on Apify on 2026-10-18 with each Actor's documented input: the *Attention Is All You Need* paper (headings and a two-level table), the two-column *BERT* paper (reading order), the Federal Reserve H.4.1 release (dense financial tables) and a synthetic noisy 150-DPI scan of IRS text with known ground truth (OCR). Other Actors are anonymized by their engine; the scripts and raw outputs are kept so the numbers can be reproduced.

| Converter | Headings found (of 21) / levels | Table 2 rows / two-level header / `10^20` exponents | BERT sentences intact¹ | Fed numeric table rows / key row correct | OCR word F1 on scan | Time, 4 docs |
|---|---|---|---|---|---|---|
| **This Actor** | **21 / 4** | **yes / yes / yes** | 93.4% | 75² / **yes** | **98.6%** | 36 s |
| LLM-Markdown PDF Actor | 21 / 4 | yes / no / yes | 94.4% | 66 / no | 94.1% | 94 s |
| Document-to-Markdown Actor (layout) | 21 / 4 | yes / no / no | 52.8% | 77 / no | 0% (no OCR) | 4 s |
| PDF-to-Markdown API Actor | 21 / 1 | no / no / no | 83.8% | no output | no output | 60 s |
| Docling-based Actor | 21 / 1 | yes / no / no | stopped at its $0.20 cost cap after the first document | – | – | 352 s |
| Docling library (local, 1 CPU core) | 21 / 1 | yes / yes / no | 90.9% | 82 / no (`+` signs split from numbers) | 96.9% | 214 s |
| MarkItDown-based Actors (2, same output) | 0 / 0 | no / no / no | 4.1% (columns turned into fake tables) | 12 / no | failed / 0% | ~51 s |
| Plain PDF text extractors (2) | 0 / 0 | no / no / no | 94.4% | 0 / no | 0% (no OCR) | 3–4 s |

¹ Share of 197 prose sentences from the PDF's own text stream found intact. Plain extractors copy that stream, so they match it by construction; our misses are page numbers and footnotes that we move out of the text, and table cells that we keep as tables.
² Tables that continue on the next page are merged, so repeated header rows are not counted twice.

The open-source libraries were also run locally on the same files (MarkItDown 0.1.8 gives the same output as the MarkItDown-based Actors). Docling 2 is strong on table structure, but flattens every heading to `##`, separates `+`/`-` signs from numbers in financial tables, and needs about 2 GB of RAM. On the same single CPU core it took 214 s for the four files versus 33 s for this converter (174 s versus 1.2 s on the three text PDFs).

#### Hosted Actor vs running a library yourself

| | This Actor | MarkItDown (self-hosted) | Docling (self-hosted) |
|---|---|---|---|
| OCR for scans | Yes, only on pages that need it | No (0% on our scan) | Yes (96.9% word F1) |
| Heading levels kept (Attention paper) | 4 | 0 | 1 |
| Two-column reading order (BERT sentences intact) | 93.4% | 4.1% | 90.9% |
| Time, same 4 documents | 33 s on one core | about 3 s (no OCR) | 214 s on one core, about 2 GB RAM |
| Infrastructure | None: API, Console, n8n, Make, Zapier | Your server | Your server |
| Cost | $0.003 per document | Your compute | Your compute |

### Sample output (shortened, real run on arxiv.org/pdf/1706.03762)

```json
{
  "status": "succeeded",
  "fileType": "pdf",
  "title": "Attention Is All You Need",
  "pageCount": 15,
  "tableCount": 5,
  "wordCount": 6202,
  "content": "# Attention Is All You Need\n\n...\n\n## 3 Model Architecture\n\n### 3.1 Encoder and Decoder Stacks\n\n...",
  "tables": [{
    "page": 8,
    "rows": [["Model", "BLEU EN-DE", "BLEU EN-FR", "Training Cost (FLOPs) EN-DE", "Training Cost (FLOPs) EN-FR"],
             ["GNMT + RL [38]", "24.6", "39.92", "2.3 · 10^19", "1.4 · 10^20"]],
    "markdown": "| Model | BLEU EN-DE | BLEU EN-FR | ...",
    "bbox": [136.7, 98.7, 475.3, 240.3]
  }],
  "chunks": [{
    "index": 5,
    "text": "...eight P100 GPUs.\n\n## 2 Background\n\nThe goal of reducing sequential computation ...",
    "section": "Attention Is All You Need > 1 Introduction",
    "pages": [2],
    "boxes": [{ "page": 2, "bbox": [107.7, 301.7, 505.7, 535.5] }],
    "charStart": 4692, "charEnd": 6078, "charCount": 1384
  }],
  "figures": [{ "page": 3, "bbox": [196.6, 72, 415.4, 394.4], "caption": "Figure 1: The Transformer - model architecture." }],
  "pages": [{ "pageNumber": 3, "text": "...", "ocr": false, "width": 612, "height": 792,
              "quality": { "source": "text-layer", "imageCoverage": 0.15, "figureCount": 1, "needsVision": false } }],
  "metadata": { "creator": "LaTeX with hyperref", "createdAt": "2024-04-10T21:11:43", "marginText": [{ "page": 1, "text": "arXiv:1706.03762v7 [cs.CL] 2 Aug 2023" }] }
}
```

### PDF to Markdown for RAG: table-aware chunking

- Chunks break at headings first, then paragraphs, then sentences, with configurable size and overlap.
- **Tables are never cut mid-row.** If a table is longer than a chunk, the next chunk repeats the header row and the section path, and is marked `tableContinued: true`.
- **Tables that continue across pages are merged** into one table (repeated headers are dropped), and sentences that run over a page break are joined.
- Each chunk keeps `pages` and `boxes` (page + bounding box) so your app can cite and highlight the source.
- Set **One dataset item per chunk** for one row per chunk; that shape works directly with Apify's Pinecone, Qdrant, Weaviate and Chroma integrations and with LangChain or LlamaIndex dataset loaders.

### OCR for scanned PDFs and images

With `ocrMode: auto`, pages with no text layer, pages that are mostly an image, and pages with a garbled text layer (broken fonts) are read with Tesseract 5 OCR in 28 languages. Upside-down and sideways scans are rotated, and tilted scans are deskewed. Each OCR page reports its confidence, and `needsVision: true` flags pages (low confidence, large charts) that are worth sending to a vision model. On a noisy, blurred, tilted 150-DPI synthetic scan with known ground truth, word F1 was **98.6%** (character error rate 1–2.4%).

### DOCX, PPTX, XLSX, EPUB and HTML to Markdown

| Format | What is kept |
|---|---|
| PDF | Text, scanned and mixed PDFs; multi-column reading order; ruled and borderless tables; headings from font size and numbering; superscripts (`10^20`, footnote marks `¹`); password-protected PDFs (`pdfPassword`); page ranges |
| DOCX | Headings, nested lists, tables (merged cells in HTML mode), footnotes, links, image alt text |
| PPTX | One page per slide: title, bullets, tables, grouped shapes, speaker notes |
| XLSX / XLS / CSV | One page per sheet as a table (up to 5,000 rows per sheet) |
| EPUB | Chapters in reading order, with title, author and language |
| HTML | Main content only (menus, cookie banners, sidebars removed), tables, links |
| Images | PNG, JPG, TIFF (multi-page), WebP, BMP, GIF via OCR |
| TXT / Markdown | Passed through and chunked |

### Use with n8n, Make, Zapier, LangChain and the API

- **URLs**: public links, including **Google Drive, Google Docs, Dropbox and GitHub share links** (converted to direct downloads automatically).
- **Base64**: send file bytes in `base64Files` (`[{"fileName": "invoice.pdf", "data": "<base64>"}]`) when the file isn't public, e.g. from an n8n, Make or Zapier step.
- **Key-value store**: convert records from an Apify key-value store.

```json
{
  "files": ["https://arxiv.org/pdf/1706.03762", "https://www.federalreserve.gov/releases/h41/current/h41.pdf"],
  "outputFormat": "markdown",
  "tableFormat": "markdown",
  "chunkSize": 1500,
  "chunkOverlap": 150,
  "ocrMode": "auto",
  "saveFiles": ["docx", "xlsx"]
}
```

### Pricing (pay per event)

| Event | Price |
|---|---|
| Document converted (up to 50 pages) | $0.003 |
| Each additional 50 pages | $0.003 |
| OCR page (only pages that needed OCR and produced text) | $0.003 |

A 12-page text PDF costs **$0.003**; a 140-page report **$0.009**; a 10-page scan $0.003 + 10 × $0.003 = **$0.033**; 1,000 Word or HTML files **$3**. Failed documents (404, damaged, password-protected without a password, empty) are **free**, and the run stops cleanly at your maximum cost per run.

### Input reference

| Field | Default | Description |
|---|---|---|
| `files` | example paper | Uploaded files or file URLs (Drive/Dropbox/GitHub links work) |
| `startUrls` | – | Bulk URL list (`userData` is copied to the output) |
| `base64Files` | – | `[{fileName, data}]` file bytes as base64 or a data: URI |
| `keyValueStoreId`, `keyValueStoreKeys` | – | Convert records from a key-value store |
| `outputFormat` | `markdown` | `markdown` or `text` |
| `tableFormat` | `markdown` | `markdown`, or `html` to keep merged cells (`rowspan`/`colspan`) |
| `chunkSize`, `chunkOverlap` | 1500, 150 | Chunk length and overlap in characters; `0` turns chunking off |
| `datasetItemPerChunk` | false | One dataset row per chunk |
| `ocrMode` | `auto` | `auto`, `force` (every page) or `off` |
| `ocrLanguages` | `["eng"]` | 28 languages incl. French, German, Spanish, Chinese, Japanese, Korean, Arabic, Russian, Hindi |
| `maxOcrPagesPerDocument` | 100 | OCR safety limit per document |
| `saveFiles` | `[]` | `markdown`, `text`, `docx`, `xlsx`, `searchablePdf`, `json` |
| `includePages`, `includeTables` | true | Page-by-page text and structured tables |
| `includeQuality` | true | Per-page quality flags |
| `includeElements` | false | Per-page layout elements with bounding boxes |
| `pageRange` | all | e.g. `1-5, 8, 12-` |
| `pdfPassword` | – | Password for encrypted PDFs (stored encrypted) |
| `extractTables`, `removeHeadersFooters` | true | Table detection; remove running headers/footers (kept in `metadata.headersFootersByPage`) |
| `maxPagesPerDocument` | 500 | Convert only the first N pages (or EPUB chapters) |
| `htmlMainContentOnly` | true | Remove menus and boilerplate from web pages |
| `maxFileSizeMb`, `maxDocuments`, `maxConcurrency`, `downloadTimeoutSecs` | 100, 10000, auto, 120 | Run limits |

### Errors are explicit, not crashes

A document that can't be converted becomes a row with `status: "failed"` and an `errorCode`; the other documents keep going.

| errorCode | Meaning |
|---|---|
| `NOT_FOUND`, `ACCESS_DENIED`, `DOWNLOAD_FAILED`, `TIMEOUT`, `INVALID_URL` | The file couldn't be downloaded |
| `INVALID_BASE64` | `base64Files[].data` isn't valid base64 |
| `FILE_TOO_LARGE` | Above `maxFileSizeMb` |
| `EMPTY_FILE` | 0 bytes |
| `DAMAGED_FILE` | Corrupt or truncated PDF, Office or EPUB file |
| `PASSWORD_REQUIRED`, `WRONG_PASSWORD` | Encrypted PDF: set `pdfPassword` |
| `UNSUPPORTED_FORMAT` | e.g. legacy `.doc`/`.ppt`, ZIP archives, video |
| `NO_TEXT_FOUND` | Blank pages, or OCR is off for a scan |
| `SPENDING_LIMIT_REACHED` | Your maximum cost per run was reached (status `skipped`) |

### FAQ

**How do I convert a PDF to Markdown?** Paste the PDF URL (or upload the file) into **Files**, keep the defaults and click **Start**. The Markdown is in `content`; download it as `.md` with `saveFiles: ["markdown"]`.

**Is this a good document to Markdown converter for RAG?** Yes: chunks are table-aware, carry section paths, pages and bounding boxes, and can be one dataset row each for vector database integrations.

**Does it do PDF to text?** Set `outputFormat: "text"` for plain text (table cells separated by tabs).

**Does it work on scanned PDFs (OCR)?** Yes. `ocrMode: auto` OCRs only the pages that need it and charges only for those pages.

**How does it compare with MarkItDown or Docling?** See the benchmark above: MarkItDown has no OCR and turned two-column text into fake tables; Docling is good on table structure but flattens headings and is much heavier. This Actor keeps heading levels, two-level table headers and superscripts at $0.003 per document.

**Can I keep merged table cells?** Set `tableFormat: "html"`. Every table in `tables[]` also has `html` when it has merged cells.

**Can I get a Word or Excel file?** Add `docx` and/or `xlsx` to `saveFiles`. Excel gets one sheet per table, numbers stored as numbers.

**Is my data kept?** Files are processed inside your own Apify run, and results stay in your run's storage under your account's retention settings.

**Can I try it for free?** Apify's free plan includes monthly platform credit you can spend on this Actor. A 15-page text PDF costs $0.003.

**Where are code examples?** LangChain, LlamaIndex, Python client and n8n examples, plus the full benchmark, are in [github.com/tobbytools/pdf-to-markdown-rag](https://github.com/tobbytools/pdf-to-markdown-rag).

**Limits?** Legacy `.doc`/`.ppt` and ZIP archives aren't supported. Math formulas come out as plain characters with `^` exponents, not LaTeX. Handwriting OCR is limited.

# Actor input Schema

## `files` (type: `array`):

PDF, Word (DOCX), PowerPoint (PPTX), Excel (XLSX/XLS/CSV), EPUB, HTML, TXT/Markdown or image files. Paste public URLs or upload files. Google Drive, Google Docs, Dropbox and GitHub share links are converted to direct downloads automatically.

## `startUrls` (type: `array`):

Optional list of document URLs, e.g. pasted from a spreadsheet or uploaded as a text file. Each URL's userData is copied to the output.

## `base64Files` (type: `array`):

Send file bytes directly instead of a URL: a list of objects like {"fileName": "invoice.pdf", "data": "<base64>"}. A data: URI is also accepted. Handy for n8n, Make, Zapier and API calls where the file is not public.

## `outputFormat` (type: `string`):

Markdown keeps headings, lists and tables (best for LLMs and RAG). Plain text removes all formatting.

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

Split each document into chunks of about this many characters for embeddings/RAG. Chunks break at headings, paragraphs and sentences, and record their pages and section. Set 0 to disable chunking.

## `chunkOverlap` (type: `integer`):

How many characters consecutive chunks share (at most half the chunk size).

## `datasetItemPerChunk` (type: `boolean`):

Output one row per chunk (with document metadata) instead of one row per document. Handy for loading straight into vector databases (Pinecone, Qdrant, Weaviate, Chroma integrations).

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

Auto: OCR only pages without a usable text layer (scans, photos, broken fonts). Always: OCR every page. Off: never OCR. OCR pages are billed separately.

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

Languages printed in the scans. Pick all that apply (fewer is faster and more accurate).

## `maxOcrPagesPerDocument` (type: `integer`):

Safety limit for OCR cost/time per document. Pages beyond it are listed in warnings.

## `saveFiles` (type: `array`):

Save converted files to the run's key-value store; download links appear in each item's 'files'. Word = editable DOCX, Excel = every extracted table as a sheet, searchable PDF = OCR text layer added to scans.

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

Add a 'pages' array with the text of every page (PDF, PPTX slides, XLSX sheets).

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

Add a 'tables' array with each table's rows (JSON) and Markdown.

## `tableFormat` (type: `string`):

How tables appear in the document content and chunks. HTML keeps merged/spanning cells exactly; Markdown is simpler. Each item in tables\[] always has rows, markdown and (when cells are merged) html.

## `includeQuality` (type: `boolean`):

Adds a quality object to each page: source (text-layer/ocr), OCR confidence, table count and confidence, image coverage, figure count and needsVision (route the page to a vision model).

## `includeElements` (type: `boolean`):

Adds elements\[] to each page: headings, paragraphs, list items and tables with their bounding box \[x0, top, x1, bottom] in PDF points (top-left origin). Useful for citations and highlighting. Chunks always carry page boxes for PDFs.

## `pageRange` (type: `string`):

Only convert these pages, e.g. '1-5, 8, 12-'. Empty = all pages.

## `pdfPassword` (type: `string`):

Password for encrypted PDFs (used for every PDF in the run).

## `extractTables` (type: `boolean`):

Detect ruled and borderless tables and output them as Markdown tables.

## `removeHeadersFooters` (type: `boolean`):

Drop text repeated at the top/bottom of pages (page numbers, running titles).

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

Only the first N pages of each document are converted.

## `htmlMainContentOnly` (type: `boolean`):

For web pages, keep the article/main content and drop menus, sidebars, cookie banners and footers.

## `maxFileSizeMb` (type: `integer`):

Larger files are skipped with a FILE_TOO_LARGE error item (not charged).

## `maxDocuments` (type: `integer`):

Stop after this many documents.

## `maxConcurrency` (type: `integer`):

How many documents are processed at once. Default: 1 per GB of memory.

## `downloadTimeoutSecs` (type: `integer`):

Per-file download timeout.

## `keyValueStoreId` (type: `string`):

Convert files stored in this key-value store (ID or name).

## `keyValueStoreKeys` (type: `array`):

Record keys to convert. Empty = every record in the store.

## Actor input object example

```json
{
  "files": [
    "https://arxiv.org/pdf/1706.03762"
  ],
  "base64Files": [
    {
      "fileName": "hello.txt",
      "data": "SGVsbG8gd29ybGQ="
    }
  ],
  "outputFormat": "markdown",
  "chunkSize": 1500,
  "chunkOverlap": 150,
  "datasetItemPerChunk": false,
  "ocrMode": "auto",
  "ocrLanguages": [
    "eng"
  ],
  "maxOcrPagesPerDocument": 100,
  "saveFiles": [],
  "includePages": true,
  "includeTables": true,
  "tableFormat": "markdown",
  "includeQuality": true,
  "includeElements": false,
  "extractTables": true,
  "removeHeadersFooters": true,
  "maxPagesPerDocument": 500,
  "htmlMainContentOnly": true,
  "maxFileSizeMb": 100,
  "maxDocuments": 10000,
  "downloadTimeoutSecs": 120
}
```

# Actor output Schema

## `results` (type: `string`):

All dataset items: content, pages, tables, chunks and metadata per document, with views 'Overview' and 'Errors'.

## `wordFiles` (type: `string`):

Editable DOCX exports (saveFiles: docx).

## `excelFiles` (type: `string`):

Table workbooks (saveFiles: xlsx).

## `searchablePdfFiles` (type: `string`):

PDFs with OCR text layer (saveFiles: searchablePdf).

## `markdownFiles` (type: `string`):

Full .md exports (saveFiles: markdown).

## `allFiles` (type: `string`):

Every record in the default key-value store, including text and JSON exports.

# 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 = {
    "files": [
        "https://arxiv.org/pdf/1706.03762"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tobbyb/document-to-markdown-converter").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 = { "files": ["https://arxiv.org/pdf/1706.03762"] }

# Run the Actor and wait for it to finish
run = client.actor("tobbyb/document-to-markdown-converter").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 '{
  "files": [
    "https://arxiv.org/pdf/1706.03762"
  ]
}' |
apify call tobbyb/document-to-markdown-converter --silent --output-dataset

```

## MCP server setup

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

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/jnI1VG9kK2IEGbRLQ/builds/hSZOjgBnkcFZxgkSJ/openapi.json
