# Docs to Markdown for RAG (PDF, Word, PowerPoint, Excel) (`tillwork/docs-to-markdown`) Actor

Turn PDF, Word, PowerPoint, Excel, CSV and HTML files into clean Markdown with real tables, then split it into token-counted chunks with heading paths, ready for embeddings, RAG and AI agents.

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

## Pricing

$4.00 / 1,000 page converteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Docs to Markdown for RAG: PDF, Word, PowerPoint, Excel

Turn documents into clean Markdown that AI models read well, then split it into token-counted chunks ready for embeddings. Paste file links; get Markdown with real tables and chunks that keep their headings.

### What you get

- **Seven formats, one output:** PDF, Word (DOCX), PowerPoint (PPTX), Excel (XLSX), CSV, HTML, Markdown and plain text.
- **Real tables.** Word, Excel, CSV and HTML tables become Markdown tables, not jumbled text.
- **Readable PDFs.** Lines that a PDF wrapped are joined back into paragraphs, words split with a hyphen are rejoined, and bullets become lists. Optional `<!-- page N -->` markers let you cite page numbers.
- **Slides with notes.** Each slide becomes a section with its title, bullet points and speaker notes.
- **Chunks for RAG.** Split by headings, then paragraphs, then sentences, up to your token limit, with overlap. Each chunk carries its heading path (for example `Guide > Install > Linux`) and its token count, using the cl100k tokenizer used by OpenAI embedding models.
- **Two output shapes.** One row per document, or one row per chunk, ready to load into Pinecone, Qdrant, Weaviate, pgvector or any vector database.

### Input

| Field | Example |
|---|---|
| File URLs | `https://arxiv.org/pdf/1706.03762`, a Dropbox or S3 link, any direct download link |
| Split into chunks | on |
| Chunk size (tokens) | `512` |
| Chunk overlap (tokens) | `50` |
| Output | One row per document, or one row per chunk |
| Add page markers to PDFs | off |

### Output (one row per chunk)

```json
{
  "sourceUrl": "https://example.com/handbook.pdf",
  "fileName": "handbook.pdf",
  "fileType": "pdf",
  "pages": 42,
  "chunkIndex": 3,
  "chunkCount": 97,
  "headingPath": "Benefits > Leave",
  "text": "## Leave\n\nEmployees get 20 days of paid leave...",
  "tokens": 486
}
```

Files that fail (a broken link, an unsupported type) get a row with an `error` field, so you can see exactly which ones to fix.

### Pricing

You pay per page converted. A page is a PDF page or a slide. For formats without pages (Word, Excel, CSV, HTML, text), every 3,000 characters of output count as one page. A file is only charged if it converts.

### Good to know

- **Scanned PDFs** (images of text) have no text layer, and this Actor does not run OCR. They come back with a warning saying so.
- Links must download the file directly. A Google Drive share link usually opens a preview page instead; use a direct download link.
- PDF headings are kept as their own paragraphs but are not marked as Markdown headings, because PDFs don't store which lines are headings. Word and HTML headings become real Markdown headings.
- Files up to 50 MB by default; raise "Max file size" for larger ones.

# Actor input Schema

## `fileUrls` (type: `array`):

Direct links to PDF, DOCX, PPTX, XLSX, CSV, HTML, Markdown or text files, one per line. Links from Google Drive, Dropbox or S3 work if they download the file directly.

## `chunk` (type: `boolean`):

Split the Markdown into token-counted chunks for embeddings. Each chunk keeps the headings it sits under.

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

Maximum tokens per chunk, counted with the cl100k tokenizer used by OpenAI embedding models.

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

Tokens repeated from the end of one chunk at the start of the next, so context isn't cut mid-thought.

## `outputMode` (type: `string`):

One row per document (Markdown plus its chunks), or one row per chunk, which is easier to load into a vector database.

## `pageMarkers` (type: `boolean`):

Insert a  comment before each PDF page so you can cite page numbers.

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

Skip files larger than this.

## Actor input object example

```json
{
  "fileUrls": [
    "https://arxiv.org/pdf/1706.03762"
  ],
  "chunk": true,
  "chunkSize": 512,
  "chunkOverlap": 50,
  "outputMode": "documents",
  "pageMarkers": false,
  "maxFileSizeMb": 50
}
```

# Actor output Schema

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

Markdown per document, or token-counted chunks in chunks mode

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

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

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

```

## MCP server setup

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

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/LFAL3sEx4eu0Uhddo/builds/bXV3sP5NhmhQY5tZ4/openapi.json
