# Document to Markdown & JSON: DOCX, XLSX, PPTX, HTML, EPUB, CSV (`plotpointtech/document-to-markdown-json`) Actor

Convert Word, PowerPoint, HTML and EPUB files to clean Markdown, and Excel or CSV to typed JSON rows, with metadata, image extraction and RAG chunks. Bulk links or upload. $2 per 1,000 documents, no page fees; failed files are free.

- **URL**: https://apify.com/plotpointtech/document-to-markdown-json.md
- **Developed by:** [Plot Point Technologies](https://apify.com/plotpointtech) (community)
- **Categories:** AI, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.24 / 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 & JSON: DOCX, XLSX, PPTX, HTML, EPUB, CSV

**Give this tool links to Word, Excel, PowerPoint, HTML, EPUB or CSV files, or upload one, and get clean, structured output for each document:** Markdown with headings, lists, tables and image references for text documents, typed JSON rows for every spreadsheet sheet, and metadata (title, author, dates, pages, slides, sheets, word count) for everything. Optional RAG chunks and embedded-image extraction. **$2 per 1,000 documents, with no per-page or per-row fees.**

### What can this document converter do?

- **Word to Markdown (DOCX):** headings, bold and italic, bullet and numbered lists (including nested levels), tables, links, footnotes and image references.
- **PowerPoint to Markdown (PPTX):** one section per slide with its title, bullet levels, tables, pictures, chart data as a table, and speaker notes.
- **Excel to JSON (XLSX):** one JSON object per row for every sheet, with automatic header-row detection (even below title rows), typed values (numbers, booleans, ISO dates), merged cells filled in, saved formula results, and a Markdown table per sheet.
- **CSV to JSON:** delimiter and encoding detection, typed values, and codes with leading zeros (postcodes, SKUs, IDs) kept as text.
- **HTML to Markdown:** keeps the main content and drops navigation, headers, footers and cookie banners; links and images become absolute URLs.
- **EPUB to Markdown:** chapters in reading order, book metadata and a chapter list with word counts.
- **RAG chunks:** split at headings, paragraphs and table rows with your chunk size and overlap; table headers repeat in every chunk and each chunk carries its heading path.
- **Extract embedded images** from DOCX, PPTX and EPUB to the run's key-value store, with links in the Markdown.

PDFs are handled by our separate [PDF to Text & Tables Extractor](https://apify.com/plotpointtech/pdf-text-markdown-tables-extractor), which adds OCR for scanned pages. PDF links given to this tool are skipped and not charged.

### What data do you get?

| Field | Description |
|---|---|
| `url`, `fileName`, `format` | The document and its detected format (`docx`, `pptx`, `xlsx`, `html`, `epub`, `csv`, `text`) |
| `title`, `author`, `createdAt`, `modifiedAt`, `metadata` | Document properties (subject, keywords, company, last modified by and more in `metadata`) |
| `pageCount`, `pageCountSource` | Word pages from the file's own statistics when Word saved them, otherwise an estimate (500 words per page) |
| `slideCount`, `sheetCount`, `chapterCount` | Size of presentations, workbooks and e-books |
| `wordCount`, `characterCount`, `language`, `tableCount`, `imageCount`, `fileSizeBytes` | Content statistics |
| `markdown`, `text` | Full Markdown and (optional) plain text |
| `sheets` | Per sheet: `name`, `headerRow`, `headers`, `columnTypes`, `title`, `rowCount`, `truncated`, `rows`, `mergedRanges` |
| `slides`, `chapters` | Per slide title and notes; per chapter title and word count |
| `images` | Embedded images: name, type, size, alt text and saved `url` when extraction is on |
| `chunks`, `chunkCount` | Optional RAG chunks: `text`, `charCount`, `tokenEstimate`, `headings` |
| `warnings`, `fullOutputUrl` | Notes, and a link to the complete JSON when a very large file does not fit in one dataset item |

### Who uses it?

- **AI and RAG builders** loading company handbooks, decks and spreadsheets into vector databases or LLM prompts.
- **Data and operations teams** turning Excel exports and CSV files into clean JSON for databases, APIs and automations.
- **Knowledge-base and documentation teams** migrating Word and HTML content to Markdown-based tools.
- **Developers** who want "document in, JSON out" without maintaining their own conversion servers.

### How to use it

1. Click **Try for free** (or **Start**).
2. Paste **document URLs** (or upload a text file of URLs), or **upload a file**.
3. Choose outputs: Markdown, plain text, image extraction and RAG chunks with your chunk size and overlap.
4. For spreadsheets, pick header detection, typed values and merged-cell handling, or limit to certain sheets.
5. Run it and download JSON, or open the **Documents**, **Markdown** and **Spreadsheet rows** views. Schedule it or call it from the API to convert new files as they arrive.

### Input example

```json
{
  "startUrls": [
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx"
    }
  ],
  "includeMarkdown": true,
  "extractImages": false,
  "chunking": false,
  "headerDetection": "auto",
  "typedValues": true,
  "fillMergedCells": true
}
```

### Output example

The Excel file from the default run (Markdown shortened, first rows shown):

```json
{
  "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx",
  "fileName": "regional-sales.xlsx",
  "format": "xlsx",
  "title": "Regional Sales Q1 2026",
  "author": "Sales Operations, Example Corp",
  "createdAt": "2026-11-05T19:39:12Z",
  "modifiedAt": "2026-11-05T19:39:12Z",
  "sheetCount": 2,
  "wordCount": 147,
  "characterCount": 701,
  "tableCount": 2,
  "imageCount": 0,
  "fileSizeBytes": 8211,
  "markdown": "# Regional Sales Q1 2026\n\n## Sales Q1 2026\n\nRegional Sales - Q1 2026\n\n| Region | Sales rep | Month | Units | Revenue (USD) | Target met | Revenue per unit |\n| -...",
  "sheets": [
    {
      "name": "Sales Q1 2026",
      "headerRow": 3,
      "headers": [
        "Region",
        "Sales rep",
        "Month"
      ],
      "columnTypes": {
        "Region": "string",
        "Sales rep": "string",
        "Month": "date",
        "Units": "integer",
        "Revenue (USD)": "number",
        "Target met": "boolean",
        "Revenue per unit": "number"
      },
      "title": "Regional Sales - Q1 2026",
      "rowCount": 7,
      "columnCount": 7,
      "truncated": false,
      "rows": [
        {
          "_row": 4,
          "Region": "North",
          "Sales rep": "A. Patel",
          "Month": "2026-01-01",
          "Units": 120,
          "Revenue (USD)": 18450.5,
          "Target met": true,
          "Revenue per unit": 153.75
        },
        {
          "_row": 5,
          "Region": "North",
          "Sales rep": "B. Okafor",
          "Month": "2026-02-01",
          "Units": 98,
          "Revenue (USD)": 15020,
          "Target met": false,
          "Revenue per unit": 153.27
        },
        {
          "_row": 6,
          "Region": "North",
          "Sales rep": "C. Novak",
          "Month": "2026-03-01",
          "Units": 143,
          "Revenue (USD)": 22110.75,
          "Target met": true,
          "Revenue per unit": 154.62
        }
      ],
      "hidden": false,
      "mergedRanges": [
        "A7:A8",
        "A1:G1",
        "A4:A6"
      ]
    },
    {
      "name": "Products",
      "headerRow": 1,
      "headers": [
        "SKU",
        "Product",
        "Unit price"
      ],
      "columnTypes": {
        "SKU": "string",
        "Product": "string",
        "Unit price": "number",
        "Launched": "date",
        "In stock": "boolean",
        "Notes": "string"
      },
      "title": null,
      "rowCount": 4,
      "columnCount": 6,
      "truncated": false,
      "rows": [
        {
          "_row": 2,
          "SKU": "00123",
          "Product": "Desk lamp",
          "Unit price": 39.9,
          "Launched": "2024-05-14",
          "In stock": true,
          "Notes": "Best seller"
        },
        {
          "_row": 3,
          "SKU": "00456",
          "Product": "Standing desk",
          "Unit price": 349,
          "Launched": "2025-02-03",
          "In stock": true,
          "Notes": null
        },
        {
          "_row": 4,
          "SKU": "00789",
          "Product": "Monitor arm",
          "Unit price": 89.5,
          "Launched": "2025-09-22",
          "In stock": false,
          "Notes": "Back in stock in April"
        }
      ],
      "hidden": false,
      "mergedRanges": null
    }
  ],
  "metadata": {
    "title": "Regional Sales Q1 2026",
    "author": "Sales Operations, Example Corp",
    "language": "en-US",
    "createdAt": "2026-11-05T19:39:12Z",
    "modifiedAt": "2026-11-05T19:39:12Z",
    "application": "LibreOffice/24.2.7.2$Linux_X86_64 LibreOffice_project/420$Build-2"
  }
}
```

### How much does it cost?

You pay per converted document, whatever its length:

| Event | Price | Per 1,000 |
|---|---|---|
| Document converted | $0.002 | **$2** |
| Run start | $0.00005 | |

Examples: the 3-document default run costs about $0.006; 500 Word contracts about $1; 10,000 CSV exports about $20. Failed downloads, unsupported formats (including PDFs) and files over your size limit are not charged. A spreadsheet with many sheets or a long book is still one document.

**Volume discounts on higher Apify plans.** The prices above are for the Apify Free plan. On paid plans the per-result price drops automatically: about 15% lower on Bronze, 25% lower on Silver and 38% lower on Gold and above.

### Use it via API, Make, Zapier, n8n or an AI agent

**Apify API.** Start a run and get the results back in one HTTP request (replace `YOUR_API_TOKEN` with the token from Apify Console > Settings > Integrations):

```bash
curl -X POST "https://api.apify.com/v2/acts/plotpointtech~document-to-markdown-json/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": [{"url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx"}, {"url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx"}, {"url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx"}], "includeMarkdown": true, "extractImages": false, "chunking": false, "headerDetection": "auto", "typedValues": true, "fillMergedCells": true}'
```

For longer jobs, start the run asynchronously and read the dataset when it finishes. Official `apify-client` libraries exist for Python and JavaScript; the **API** tab on this page has ready-made code.

**No-code automation.** Connect the tool to **Make, Zapier, n8n, Google Sheets, Slack, Airtable** or any webhook with Apify integrations, and use **Schedules** in Apify Console to run it hourly, daily or weekly.

**AI agents (MCP).** Give Claude, ChatGPT, Cursor, VS Code or any MCP-compatible agent direct access to this tool through the hosted Apify MCP server. Add this server URL to your client:

```
https://mcp.apify.com?tools=plotpointtech/document-to-markdown-json
```

The agent can then call the tool with the same input fields shown above and read the results.

### FAQ

**Is it legal to convert these documents?**
Yes, for documents you are allowed to access and use. The tool downloads exactly the URLs you provide (or your upload) and does not log in anywhere. Respect copyright and the confidentiality of the documents you process; files are processed in your own Apify run and are not shared.

**Which formats are supported?**
DOCX, PPTX, XLSX (and XLSM), HTML web pages, EPUB, CSV/TSV, plain text and Markdown. Older binary .doc, .xls and .ppt files, OpenDocument files and password-protected Office files are not supported; save them as DOCX/XLSX/PPTX first. Use our PDF tool for PDFs.

**How are spreadsheet headers and types detected?**
The header is the first row (within the first 20) whose cells are mostly distinct text and that is followed by data, so title rows above a table are kept separately as the sheet `title`. Numbers, booleans and dates become JSON types; columns that mix words and numbers in CSV files stay text. Formula cells return the result saved in the file; if a file was never calculated by a spreadsheet app, the formula text is returned with a warning.

**How large can files be?**
Up to 200 MB per file (50 MB by default). Sheets are capped at 10,000 rows by default (set 0 for no limit). If one document's output exceeds what a dataset item can hold (about 9 MB), the complete JSON is saved to the key-value store and linked in `fullOutputUrl`.

**Are page counts exact?**
Pages exist only after a document is laid out, so DOCX page counts come from the statistics Word stores when it saves a file. When those are missing or stale (common for files generated by software), an estimate is returned and `pageCountSource` says `estimate`.

### Related tools from Plot Point Technologies

- [PDF to Text & Tables Extractor - Markdown + OCR, $0.40/1K](https://apify.com/plotpointtech/pdf-text-markdown-tables-extractor): PDFs to text, Markdown and CSV tables, with OCR for scans.
- [Website to Markdown Crawler for AI, LLM & RAG - $1/1K](https://apify.com/plotpointtech/website-to-markdown-crawler): any website as clean Markdown for LLMs and RAG.
- [Image OCR - Image to Text in Bulk, Tesseract & AI Vision](https://apify.com/plotpointtech/image-to-text-ocr-bulk): text from images in bulk, with AI mode for receipts and handwriting.

Plot Point Technologies is not affiliated with Microsoft, the EPUB or CSV standards bodies, or the publishers of any document you process.

Questions or feature requests: support@plotpoint.tech.

***

If this tool saved you time, we would be grateful for a short review on this page; it helps other people find it. If something did not work as expected, please open an issue on the **Issues** tab and we will look into it quickly.

# Actor input Schema

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

Direct links to DOCX, XLSX, PPTX, HTML, EPUB, CSV/TSV, TXT or Markdown files. Paste many at once or upload a text file with one URL per line. The format is detected from the file itself. Links that fail to download or are not a supported format are skipped and not charged. For PDFs use our PDF to Text & Tables Extractor.

## `uploadedFile` (type: `string`):

Upload a document from your computer. It is stored in your Apify key-value store and converted together with any URLs above.

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

Clean Markdown of the whole document: headings, lists, tables, links and image references. Spreadsheets become one Markdown table per sheet.

## `includeText` (type: `boolean`):

Plain text version without Markdown syntax.

## `extractImages` (type: `boolean`):

Save images embedded in DOCX, PPTX and EPUB files to the run's key-value store. Markdown image references then point to the saved files. Images on HTML pages are always listed by their original URL and are not downloaded.

## `maxImagesPerDocument` (type: `integer`):

Only used when image extraction is on.

## `chunking` (type: `boolean`):

Add a list of chunks split at headings, paragraphs and table rows (table headers are repeated in every chunk). Each chunk carries its heading path, so you can load it straight into a vector database.

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

Maximum characters per chunk. About 4 characters make one token in English, so 2000 characters is roughly 500 tokens.

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

Characters of text repeated from the end of the previous chunk (whole lines; headings and table rows are not repeated). Capped at half the chunk size.

## `headerDetection` (type: `string`):

Auto finds the header row even below title rows. First row always uses the first non-empty row. None keys rows by column letter (A, B, C...).

## `typedValues` (type: `boolean`):

Return numbers, booleans and dates (ISO 8601) as real JSON types. Codes with leading zeros (postcodes, IDs) stay text. Off returns every cell as text.

## `fillMergedCells` (type: `boolean`):

Copy the value of a vertically merged cell (for example a region label spanning several rows) into every row it covers, so each JSON row is complete.

## `includeRows` (type: `boolean`):

One JSON object per row, keyed by the header.

## `includeRowNumbers` (type: `boolean`):

Add a \_row field with the original spreadsheet row number to each JSON row.

## `includeSheetMarkdown` (type: `boolean`):

Also put each sheet's Markdown table inside its sheet object (it is always part of the document Markdown).

## `maxRowsPerSheet` (type: `integer`):

Stop reading a sheet or CSV after this many data rows; the sheet is then marked truncated. 0 = no limit.

## `sheetNames` (type: `array`):

Optional list of sheet names to convert. Empty = all visible sheets.

## `includeHiddenSheets` (type: `boolean`):

Also convert sheets that are hidden in the workbook.

## `csvDelimiter` (type: `string`):

Auto-detect works for comma, semicolon, tab and pipe.

## `includeSpeakerNotes` (type: `boolean`):

Add each slide's speaker notes below the slide in the Markdown and in the slides list.

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

For web pages, keep the main content and drop navigation, headers, footers, sidebars and forms. Off converts the whole page body.

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

Larger files are skipped and not charged.

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

How many documents to download in parallel.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx"
    }
  ],
  "includeMarkdown": true,
  "includeText": false,
  "extractImages": false,
  "maxImagesPerDocument": 100,
  "chunking": false,
  "chunkSize": 2000,
  "chunkOverlap": 200,
  "headerDetection": "auto",
  "typedValues": true,
  "fillMergedCells": true,
  "includeRows": true,
  "includeRowNumbers": true,
  "includeSheetMarkdown": false,
  "maxRowsPerSheet": 10000,
  "includeHiddenSheets": false,
  "csvDelimiter": "auto",
  "includeSpeakerNotes": true,
  "htmlMainContentOnly": true,
  "maxFileSizeMb": 50,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx"
        },
        {
            "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx"
        },
        {
            "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plotpointtech/document-to-markdown-json").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 = { "startUrls": [
        { "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx" },
        { "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx" },
        { "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("plotpointtech/document-to-markdown-json").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 '{
  "startUrls": [
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/quarterly-report.docx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/regional-sales.xlsx"
    },
    {
      "url": "https://api.apify.com/v2/key-value-stores/6tG74dmDqhbuixGpx/records/product-roadmap.pptx"
    }
  ]
}' |
apify call plotpointtech/document-to-markdown-json --silent --output-dataset

```

## MCP server setup

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

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/670VaXpcj2ExsuO9w/builds/JJGnS7HuJEggQfVgq/openapi.json
