# Document to Markdown & RAG Chunks: PDF, DOCX, XLSX, PPTX, HTML (`noisy_jubilee/document-to-markdown`) Actor

Convert PDF, Word, Excel, PowerPoint, HTML and CSV files from URLs into clean Markdown and heading-aware RAG chunks with token estimates. No OCR. Pay per document and page.

- **URL**: https://apify.com/noisy_jubilee/document-to-markdown.md
- **Developed by:** [Stephen](https://apify.com/noisy_jubilee) (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 $3.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.

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 & RAG Chunks

Turn **PDF, Word (DOCX), Excel (XLSX), PowerPoint (PPTX), HTML, CSV/TSV, TXT, Markdown and JSON** files into clean **Markdown** plus **ready-to-embed chunks** for RAG pipelines, vector databases and LLM prompts. Paste file URLs, get structured output. No API key, no setup.

### What you get per document

| Field | Description |
|---|---|
| `url`, `finalUrl` | Input URL and URL after redirects |
| `status` | `ok` or `failed` (failed documents are **not charged**) |
| `format` | Detected from file content (works for links without extensions) |
| `title` | Document title (metadata, `<title>`, or first heading) |
| `pages` | PDF pages / PPTX slides converted |
| `billablePages` | Pages billed (see pricing) |
| `chars`, `approxTokens` | Size of the Markdown (token estimate ≈ 4 chars/token, 1 per CJK character) |
| `markdown` | Full Markdown: headings, lists, tables (DOCX/XLSX/HTML/CSV), page/slide markers |
| `chunks[]` | `{index, headings, text, chars, approxTokens}`; heading-aware, configurable size and overlap |
| `warnings[]` | e.g. truncated PDF, likely scanned PDF |

Real example (RFC 8461 as plain text, trimmed): [listing/output-example.json](listing/output-example.json).

### Pricing (pay per event)

| Event | Price |
|---|---|
| Document converted | $0.003 |
| Page converted | $0.0005 |
| Actor start (Apify standard, once per run) | $0.0003 |

*Pages* = PDF pages or PPTX slides; for other formats, one page per 3,000 characters of output (minimum 1).
Example: a 10-page PDF costs **$0.008**; a 200-page PDF **$0.103**; a 1-page web page **$0.0035** (plus $0.0003 per run). Failed downloads and unsupported files are free. Set a maximum charge per run in the run options and the Actor stops cleanly when it is reached.

### Limits

- **No OCR.** Scanned/image-only PDFs produce little text; the Actor warns you (`likely scanned PDF`).
- Max file size and max PDF pages are configurable (defaults 50 MB, 500 pages).
- Excel sheets are capped at 5,000 rows per sheet in Markdown output.
- Complex layouts (multi-column PDFs, nested tables, footnotes) can come out in the wrong order or flattened.
- Default memory 512 MB. Our test run (one 59 kB text file) peaked at 55 MB; very large PDFs or spreadsheets may need more memory.

### Data and credit

Your files are processed inside your run with open-source libraries (see requirements.txt). Nothing is sent to third-party services.

### Responsible use

- Only submit files you have the right to process (your own files, open data, public documents whose terms allow it).
- The Actor **respects robots.txt** by default (user agent `DocumentToMarkdownActor`), downloads each URL once, and refuses private/internal network addresses.
- Personal metadata (author, last-modified-by) is **dropped** from output. The Actor does not store your documents beyond your run's own storage.

### Integrations

The output is plain JSON, so you can feed the chunks to your own embedding/vector-store code or to Apify integrations (we have not tested specific vector-database connectors). Call it from the Apify API:

```bash
curl -X POST "https://api.apify.com/v2/acts/<username>~document-to-markdown/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' -d '{"fileUrls":["https://www.rfc-editor.org/rfc/rfc9309.pdf"]}'
```

### No warranty

Provided as is, without warranty of any kind. Results are automated and can be incomplete or wrong; check anything important against the original source before relying on it.

# Actor input Schema

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

Direct http(s) links to files you have the right to process: PDF, DOCX, XLSX, PPTX, HTML, CSV/TSV, TXT, MD or JSON. Format is detected from content, so links without extensions work.

## `includeMarkdown` (type: `boolean`):

Add the full Markdown of each document to the output item.

## `includeChunks` (type: `boolean`):

Split each document into heading-aware chunks with approximate token counts, ready for embedding.

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

Target maximum characters per chunk.

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

Characters repeated between consecutive chunks (capped at half the chunk size).

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

PDFs longer than this are truncated (and only the converted pages are billed).

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

Larger files are skipped (not billed).

## `respectRobotsTxt` (type: `boolean`):

Skip URLs that the hosting site's robots.txt disallows. Turn off only for files on servers you control.

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

Documents downloaded and converted in parallel.

## Actor input object example

```json
{
  "fileUrls": [
    "https://www.rfc-editor.org/rfc/rfc8461.txt"
  ],
  "includeMarkdown": true,
  "includeChunks": true,
  "chunkSize": 2000,
  "chunkOverlap": 200,
  "maxPagesPerDocument": 500,
  "maxFileSizeMb": 50,
  "respectRobotsTxt": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

One row per input file: Markdown, RAG chunks, token estimate, or a failed status with error.

## `summary` (type: `string`):

SUMMARY record in the default key-value store: counts, charges and status of the run.

# 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://www.rfc-editor.org/rfc/rfc8461.txt"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("noisy_jubilee/document-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://www.rfc-editor.org/rfc/rfc8461.txt"] }

# Run the Actor and wait for it to finish
run = client.actor("noisy_jubilee/document-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://www.rfc-editor.org/rfc/rfc8461.txt"
  ]
}' |
apify call noisy_jubilee/document-to-markdown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,noisy_jubilee/document-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/RuMHCb4U7AbJGiCnP/builds/DWuhz11gYmtXtBNUL/openapi.json
