# Office Docs to Markdown: DOCX, PPTX, XLSX to Markdown (`examsens.ai/office-docs-to-markdown`) Actor

Converts Word, PowerPoint and Excel files (by URL or upload) to Markdown and plain text, keeping headings, lists and tables, with one section per slide and one table per sheet.

- **URL**: https://apify.com/examsens.ai/office-docs-to-markdown.md
- **Developed by:** [Ed Rayyis](https://apify.com/examsens.ai) (community)
- **Categories:** AI, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.60 / 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

## Office Docs to Markdown: DOCX, PPTX, XLSX to Markdown

Give it Word, PowerPoint and Excel files, by link or by upload, and it returns each one as Markdown and as plain text, with the structure kept: headings, lists, tables, one section per slide and one table per sheet.

### What is kept

**Word (DOCX)**

- Word heading styles become Markdown headings (`#`, `##`, `###`)
- Bulleted and numbered lists, bold and italic text
- Tables become Markdown tables, with the first row as the header. A merged cell keeps its text in the first cell it covers.
- Pictures become `[Image: alt text]` when they have alt text, or are left out

**PowerPoint (PPTX)**

- One section per slide, headed `Slide 3: Title`
- Text boxes in reading order (top to bottom, then left to right), with bullet levels kept as nested lists, including text inside grouped shapes
- Tables on slides become Markdown tables
- Speaker notes after each slide's content (can be turned off)
- Pictures with alt text become `[Image: alt text]`

**Excel (XLSX)**

- One section per sheet, with the sheet's cells as a Markdown table. Empty rows and columns around the data are trimmed.
- Formula cells show the value saved in the file. `formulasWithoutSavedValue` counts formula cells that had no saved value (a file written by a program that never calculated it), which come out empty.
- Dates are written as `2026-10-04`. A pipe or a line break inside a cell is escaped so the table stays intact.
- Hidden sheets are skipped unless you ask for them, and long sheets are cut at a row limit you set (1,000 by default), with a note saying how many rows were left out.

The plain text version has the same content with the Markdown marks removed and table cells separated by tabs.

### Input

- Files: paste direct links or upload files. The format is read from the file itself, so a link with no file extension works.
- Store with uploaded files: when you upload, also choose the key value store the files went into. The run then gets read access to that store only. With no files listed, every record in the chosen store whose key ends in `.docx`, `.pptx` or `.xlsx` is converted.
- Include speaker notes (default on), keep image alt text (default on)
- Maximum rows per sheet (default 1,000; 0 for no limit), include hidden sheets (default off)
- Maximum file size (default 50 MB) and files at once (default 3)

### Output

Dataset: one item per file with `source`, `fileName`, `bytes`, `format` (`docx`, `pptx` or `xlsx`), `title`, `subject`, `created` and `modified` when the file has them, `markdown`, `text`, `characters` and `words`. Word files add `headings` and `tables`. PowerPoint files add `slideCount` and `slides` (title, table count, whether it has notes). Excel files add `sheetCount`, `sheets` (name, rows, columns, whether it was cut) and `formulasWithoutSavedValue`.

Author and last editor names stored in a file are not read.

A file that cannot be converted returns an item with `ok: false` and the reason, such as `HTTP 404`, an older `.doc`, `.ppt` or `.xls` file, a file that is not a DOCX, PPTX or XLSX document, or an upload whose store was not chosen. The rest of the run carries on.

Export as JSON, CSV or Excel, or read it over the API.

### Pricing

Pay per event: one event per file converted. A file that fails is not charged. The run stops when it reaches the maximum charge you set.

### Scope and conduct

Only the files you list, or the store you choose, are read. Use files you own or are allowed to process. No login is used.

### Support

Questions and problems: the Issues tab on this page. Replies are written by an AI assistant on behalf of the developer and reviewed by the developer.

# Actor input Schema

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

DOCX, PPTX or XLSX files: paste direct links, or upload files. The format is read from the file itself, so a link without a file extension works. When you upload files, also choose the store they went into under "Store with uploaded files" so the run may read them.

## `uploadStore` (type: `string`):

The key value store your uploads went into. The run gets read access to this store only. With no files listed above, every record in it whose key ends in .docx, .pptx or .xlsx is converted.

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

Add each slide's speaker notes after its content.

## `imageAltText` (type: `boolean`):

Write \[Image: alt text] where a picture with alt text sits. Turn off to leave pictures out entirely. Picture files are never included.

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

Rows of each spreadsheet sheet to write after the first row. Set 0 for no limit.

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

Also convert spreadsheet sheets that are hidden.

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

Larger files are skipped with an error item.

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

How many files to download and convert in parallel.

## Actor input object example

```json
{
  "files": [
    "https://raw.githubusercontent.com/mwilliamson/python-mammoth/master/tests/test-data/tables.docx"
  ],
  "includeSpeakerNotes": true,
  "imageAltText": true,
  "maxRowsPerSheet": 1000,
  "includeHiddenSheets": false,
  "maxFileSizeMb": 50,
  "maxConcurrency": 3
}
```

# 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 = {
    "files": [
        "https://raw.githubusercontent.com/mwilliamson/python-mammoth/master/tests/test-data/tables.docx"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("examsens.ai/office-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 = { "files": ["https://raw.githubusercontent.com/mwilliamson/python-mammoth/master/tests/test-data/tables.docx"] }

# Run the Actor and wait for it to finish
run = client.actor("examsens.ai/office-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 '{
  "files": [
    "https://raw.githubusercontent.com/mwilliamson/python-mammoth/master/tests/test-data/tables.docx"
  ]
}' |
apify call examsens.ai/office-docs-to-markdown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,examsens.ai/office-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/JkV4aMuyipU7hY3Aq/builds/fcDdon7orKJTuwrJU/openapi.json
