# Markdown to PDF and HTML: themes, code and tables (`examsens.ai/markdown-to-pdf`) Actor

Turns Markdown text, .md links or stored files into styled PDF and standalone HTML. Four themes, colored code blocks, tables, task lists, footnotes, an optional table of contents and page numbers. Returns download links for each document.

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

## Pricing

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

## Markdown to PDF and HTML: themes, code and tables

Give it Markdown as text, as links to `.md` files, or from one of your key value stores, and it makes a styled PDF and a standalone HTML page for each document. Pick a theme, the code colors, the paper size and margins, and add a table of contents and page numbers. Every file goes into the run's key value store, and the dataset gives you the download links with the title, page count and size.

### What it does

- Four themes: Modern (sans serif, like a project README), Serif (book style with justified text), Compact (smaller type and tighter spacing for reports) and Dark (light text on a dark background, edge to edge on every PDF page)
- Code blocks colored by language with Pygments, in nine color schemes or one picked to match the theme. Long lines wrap in the PDF
- Tables with column alignment, borders and striped rows
- Task lists, **footnotes**, **strikethrough**, quotes and links found in plain text
- Table of contents: a linked list of the level 1 to 3 headings on its own first page
- Page numbers: page and page count at the foot of every PDF page, on by default
- Paper: A4, US Letter, US Legal, A3 or A5, wide pages for wide tables, and margins in millimeters
- Images in the Markdown are loaded. In a file from a link, relative image paths load from the file's own location
- HTML in Markdown is shown as text by default, or rendered when you allow it. Scripts never run
- Title for the PDF properties and the HTML page, taken from the first level 1 heading unless you set one
- Extra CSS added after the theme
- HTML output: one standalone file per document with the styles inside

### Example

A project README from a raw GitHub link, with a logo, screenshots, 23 headings and relative image paths, came out as a 10 page A4 PDF with every image in place, and with the table of contents on page 1. A one page report with a table, a task list, Python and JSON code and a footnote came out on one US Letter page in each of the four themes.

### Input

- Markdown: one document as text, and its document name
- More documents: a JSON list such as `[{"name": "report", "markdown": "# Title"}]`
- Markdown file URLs: links to raw Markdown files
- Files in a key value store: to use Markdown files from your computer, upload them to one of your key value stores and pick that store. Every record whose key ends in `.md`, `.markdown` or `.txt` is converted
- Record keys: only convert these records from that store
- Output: PDF and HTML (default), PDF only or HTML only
- Theme: Modern (default), Serif, Compact or Dark
- Code colors: auto (default) or one of nine schemes
- Table of contents (default off)
- Page size: A4 (default), US Letter, US Legal, A3 or A5, and wide pages (default off)
- Margin in millimeters (default 18)
- Page numbers (default on)
- Title (default: the first level 1 heading)
- Language code (default `en`)
- Allow HTML in Markdown (default off)
- Extra CSS
- Maximum file size in MB (default 5)

### Output

Dataset: one item per document with `pdfUrl` and `htmlUrl` (download links), `pdfKey`, `htmlKey`, `title`, `name`, `source`, `pdfPages`, `pdfBytes`, `headings` and `markdownChars`. Files are named by the document's position and name, such as `0003-readme.pdf`.

A document that cannot be converted gets `ok: false` and an `error`, such as `HTTP 404`, "the link returns a web page, not a Markdown file; use the raw file link", or "the Markdown is empty". One bad document never stops the run.

### Pricing

Pay per event: one event per document converted, with the PDF and the HTML together counting as one. Failed documents are not charged. The run stops when it reaches the maximum charge you set.

### Scope and conduct

Only the files you supply are downloaded, plus the images your Markdown links to. The actor does not log in anywhere and uses no proxies. Convert documents you have the right to use.

### 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

## `markdown` (type: `string`):

One document as Markdown text.

## `documentName` (type: `string`):

File name for the Markdown above.

## `documents` (type: `array`):

Several documents at once, as a JSON list: \[{"name": "report", "markdown": "# Title ..."}].

## `markdownUrls` (type: `array`):

Links to raw Markdown files, such as raw.githubusercontent.com links. Relative image links in a file are loaded from the file's own location.

## `inputStore` (type: `string`):

To use Markdown files from your computer, upload them to one of your key value stores, then pick that store here. Every record whose key ends in .md, .markdown or .txt is converted, or only the keys you list below.

## `inputKeys` (type: `array`):

Only convert these records from the store above, one key per line.

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

PDF, standalone HTML with the styles inside, or both.

## `theme` (type: `string`):

Modern: sans serif, like a project README. Serif: book style, justified text. Compact: smaller type and tighter spacing for reports. Dark: light text on a dark background.

## `codeStyle` (type: `string`):

Color scheme for fenced code blocks. Auto picks one to match the theme.

## `tableOfContents` (type: `boolean`):

Add a linked list of the level 1 to 3 headings at the start, on its own page in the PDF.

## `pageSize` (type: `string`):

Paper size of the PDF.

## `landscape` (type: `boolean`):

Turn the pages sideways, for wide tables.

## `marginMm` (type: `number`):

Page margin on every side, in millimeters.

## `pageNumbers` (type: `boolean`):

Print the page number and page count at the foot of every PDF page.

## `title` (type: `string`):

Document title for the PDF properties and the HTML title. Empty uses the first level 1 heading, or the document name.

## `language` (type: `string`):

Language code for the document, such as en, de or fr. Used for hyphenation in the Serif theme.

## `allowHtml` (type: `boolean`):

Render HTML tags written in the Markdown. When off, they are shown as text. Scripts never run.

## `customCss` (type: `string`):

CSS added after the theme, such as body{font-size:14px}.

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

Larger Markdown files are skipped with an error item and are not charged.

## Actor input object example

````json
{
  "markdown": "# Project report\n\nA short **example** with a table, a task list and code.\n\n## Results\n\n| Metric | Q1 | Q2 |\n| --- | ---: | ---: |\n| Visits | 1,200 | 1,450 |\n| Sign ups | 85 | 112 |\n\n- [x] Draft written\n- [ ] Review\n\n```python\ndef total(rows):\n    return sum(r[\"value\"] for r in rows)\n```\n",
  "documentName": "document",
  "outputFormat": "both",
  "theme": "modern",
  "codeStyle": "auto",
  "tableOfContents": false,
  "pageSize": "A4",
  "landscape": false,
  "marginMm": 18,
  "pageNumbers": true,
  "language": "en",
  "allowHtml": false,
  "maxFileSizeMb": 5
}
````

# 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 = {
    "markdown": `# Project report

A short **example** with a table, a task list and code.

## Results

| Metric | Q1 | Q2 |
| --- | ---: | ---: |
| Visits | 1,200 | 1,450 |
| Sign ups | 85 | 112 |

- [x] Draft written
- [ ] Review

```python
def total(rows):
    return sum(r["value"] for r in rows)
````

};

// Run the Actor and wait for it to finish
const run = await client.actor("examsens.ai/markdown-to-pdf").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 = { "markdown": """# Project report

A short **example** with a table, a task list and code.

## Results

| Metric | Q1 | Q2 |
| --- | ---: | ---: |
| Visits | 1,200 | 1,450 |
| Sign ups | 85 | 112 |

- [x] Draft written
- [ ] Review

```python
def total(rows):
    return sum(r[\"value\"] for r in rows)
````

""" }

# Run the Actor and wait for it to finish

run = client.actor("examsens.ai/markdown-to-pdf").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 '{
  "markdown": "# Project report\\n\\nA short **example** with a table, a task list and code.\\n\\n## Results\\n\\n| Metric | Q1 | Q2 |\\n| --- | ---: | ---: |\\n| Visits | 1,200 | 1,450 |\\n| Sign ups | 85 | 112 |\\n\\n- [x] Draft written\\n- [ ] Review\\n\\n```python\\ndef total(rows):\\n    return sum(r[\\"value\\"] for r in rows)\\n```\\n"
}' |
apify call examsens.ai/markdown-to-pdf --silent --output-dataset

````

## MCP server setup

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

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/Ig4e4tmLfKlo8Zx0e/builds/e0vKCRyaJc9GDvX6I/openapi.json
